[pypy-svn] r17617 - in pypy/dist/pypy/rpython: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Sep 17 18:14:15 CEST 2005


Author: cfbolz
Date: Sat Sep 17 18:14:12 2005
New Revision: 17617

Modified:
   pypy/dist/pypy/rpython/exceptiondata.py
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/normalizecalls.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rclass.py
   pypy/dist/pypy/rpython/test/test_exception.py
   pypy/dist/pypy/rpython/test/test_rbuiltin.py
Log:
issue141: testing

implemented issubclass checks using relative numbering including some more
isinstance tests. This required quite some fixes in various places because of
exceptions.


Modified: pypy/dist/pypy/rpython/exceptiondata.py
==============================================================================
--- pypy/dist/pypy/rpython/exceptiondata.py	(original)
+++ pypy/dist/pypy/rpython/exceptiondata.py	Sat Sep 17 18:14:12 2005
@@ -4,7 +4,7 @@
 from pypy.rpython.lltype import Array, malloc, Ptr, PyObject, pyobjectptr
 from pypy.rpython.lltype import FuncType, functionptr, Signed
 from pypy.rpython.extfunctable import standardexceptions
-
+from pypy.annotation.classdef import FORCE_ATTRIBUTES_INTO_CLASSES
 
 class ExceptionData:
     """Public information for the code generators to help with exceptions."""
@@ -70,7 +70,7 @@
             if (clsdef and clsdef.cls is not Exception
                 and issubclass(clsdef.cls, Exception)):
                 cls = clsdef.cls
-                if cls in self.standardexceptions:
+                if cls in self.standardexceptions and cls not in FORCE_ATTRIBUTES_INTO_CLASSES:
                     is_standard = True
                     assert not clsdef.attrs, (
                         "%r should not have grown atributes" % (cls,))

Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Sat Sep 17 18:14:12 2005
@@ -214,4 +214,9 @@
     ZeroDivisionError: True,
     MemoryError      : True,
     IOError          : True,
+    OSError          : True,
+    StopIteration    : True,
+    KeyError         : True,
+    IndexError       : True,
+    AssertionError   : True,
     }

Modified: pypy/dist/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/normalizecalls.py	Sat Sep 17 18:14:12 2005
@@ -340,7 +340,19 @@
     annotator.setbinding(graph.getreturnvar(), generalizedresult)
     classdef.my_instantiate = my_instantiate
 
-
+def assign_inheritance_ids(annotator):
+    def assign_id(classdef, nextid):
+        classdef.minid = nextid
+        nextid += 1
+        for subclass in classdef.subdefs.values():
+            nextid = assign_id(subclass, nextid)
+        classdef.maxid = nextid
+        return classdef.maxid
+    id_ = 0
+    for cls, classdef in annotator.getuserclasses().items():
+        if classdef.basedef is None:
+            id_ = assign_id(classdef, id_)
+        
 def perform_normalizations(rtyper):
     create_class_constructors(rtyper)
     rtyper.annotator.frozen += 1
@@ -348,6 +360,7 @@
         normalize_function_signatures(rtyper.annotator)
         specialize_pbcs_by_memotables(rtyper.annotator) 
         merge_classpbc_getattr_into_classdef(rtyper)
+        assign_inheritance_ids(rtyper.annotator)
     finally:
         rtyper.annotator.frozen -= 1
     create_instantiate_functions(rtyper.annotator)

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Sat Sep 17 18:14:12 2005
@@ -151,8 +151,13 @@
     instance_repr = hop.args_r[0].common_repr()
 
     v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
-
-    return hop.gendirectcall(rclass.ll_isinstance, v_obj, v_cls)
+    if isinstance(v_cls, Constant):
+        minid = hop.inputconst(lltype.Signed, v_cls.value.subclassrange_min)
+        maxid = hop.inputconst(lltype.Signed, v_cls.value.subclassrange_max)
+        return hop.gendirectcall(rclass.ll_isinstance_const, v_obj, minid,
+                                 maxid)
+    else:
+        return hop.gendirectcall(rclass.ll_isinstance, v_obj, v_cls)
 
 #def rtype_builtin_range(hop): see rrange.py
 

Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py	(original)
+++ pypy/dist/pypy/rpython/rclass.py	Sat Sep 17 18:14:12 2005
@@ -1,7 +1,9 @@
+import sys
 import types
 from pypy.annotation.pairtype import pairtype, pair
 from pypy.annotation import model as annmodel
 from pypy.annotation.classdef import isclassdef
+from pypy.objspace.flow.model import Constant
 from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning, needsgc
 from pypy.rpython.lltype import ForwardReference, GcForwardReference
 from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc
@@ -17,6 +19,8 @@
 #      struct object_vtable {
 #          struct object_vtable* parenttypeptr;
 #          RuntimeTypeInfo * rtti;
+#          Signed subclassrange_min;  //this is also the id of the class itself
+#          Signed subclassrange_max;
 #          array { char } * name;
 #          struct object * instantiate();
 #      }
@@ -47,6 +51,8 @@
 OBJECTPTR = Ptr(OBJECT)
 OBJECT_VTABLE.become(Struct('object_vtable',
                             ('parenttypeptr', TYPEPTR),
+                            ('subclassrange_min', Signed),
+                            ('subclassrange_max', Signed),
                             ('rtti', Ptr(RuntimeTypeInfo)),
                             ('name', Ptr(Array(Char))),
                             ('instantiate', Ptr(FuncType([], OBJECTPTR)))))
@@ -230,6 +236,11 @@
             # initialize the 'parenttypeptr' and 'name' fields
             if rsubcls.classdef is not None:
                 vtable.parenttypeptr = rsubcls.rbase.getvtable()
+                vtable.subclassrange_min = rsubcls.classdef.minid
+                vtable.subclassrange_max = rsubcls.classdef.maxid
+            else: #for the root class
+                vtable.subclassrange_min = 0
+                vtable.subclassrange_max = sys.maxint
             rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
             rinstance.setup()
             if rinstance.needsgc: # only gc-case
@@ -338,7 +349,13 @@
     def rtype_issubtype(self, hop): 
         class_repr = get_type_repr(self.rtyper)
         v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr)
-        return hop.gendirectcall(ll_issubclass, v_cls1, v_cls2)
+        if isinstance(v_cls2, Constant):
+            minid = hop.inputconst(Signed, v_cls2.value.subclassrange_min)
+            maxid = hop.inputconst(Signed, v_cls2.value.subclassrange_max)
+            return hop.gendirectcall(ll_issubclass_const, v_cls1, minid, maxid)
+        else:
+            v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr)
+            return hop.gendirectcall(ll_issubclass, v_cls1, v_cls2)
 
 def get_type_repr(rtyper):
     return getclassrepr(rtyper, None)
@@ -717,11 +734,11 @@
     return cast_pointer(OBJECTPTR, obj).typeptr
 
 def ll_issubclass(subcls, cls):
-    while subcls != cls:
-        if not subcls:
-            return False
-        subcls = subcls.parenttypeptr
-    return True
+    return cls.subclassrange_min <= subcls.subclassrange_min < cls.subclassrange_max
+
+def ll_issubclass_const(subcls, minid, maxid):
+    return minid <= subcls.subclassrange_min < maxid
+
 
 def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT
     if not obj:
@@ -729,6 +746,11 @@
     obj_cls = obj.typeptr
     return ll_issubclass(obj_cls, cls)
 
+def ll_isinstance_const(obj, minid, maxid):
+    if not obj:
+        return False
+    return ll_issubclass_const(obj.typeptr, minid, maxid)
+
 def ll_runtime_type_info(obj):
     return obj.typeptr.rtti
 

Modified: pypy/dist/pypy/rpython/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_exception.py	(original)
+++ pypy/dist/pypy/rpython/test/test_exception.py	Sat Sep 17 18:14:12 2005
@@ -42,9 +42,9 @@
     classdef = a.bookkeeper.getclassdef(OverflowError)
     assert ovferr_inst.typeptr == t.rtyper.class_reprs[classdef].getvtable()
 
-    keyerr_inst = data.ll_pyexcclass2exc(pyobjectptr(KeyError))
+    taberr_inst = data.ll_pyexcclass2exc(pyobjectptr(TabError))
     classdef = a.bookkeeper.getclassdef(StandardError) # most precise class seen
-    assert keyerr_inst.typeptr == t.rtyper.class_reprs[classdef].getvtable()
+    assert taberr_inst.typeptr == t.rtyper.class_reprs[classdef].getvtable()
 
     myerr_inst = data.ll_pyexcclass2exc(pyobjectptr(MyException))
     assert myerr_inst.typeptr == t.rtyper.class_reprs[None].getvtable()

Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rbuiltin.py	Sat Sep 17 18:14:12 2005
@@ -199,6 +199,35 @@
     res = interpret(f, [])
     assert res is True
 
+def test_isinstance():
+    class A(object):
+        pass
+    class B(A):
+        pass
+    class C(A):
+        pass
+    def f(x, y):
+        if x == 1:
+            a = A()
+        elif x == 2:
+            a = B()
+        else:
+            a = C()
+        if y == 1:
+            res = isinstance(a, A)
+            cls = A
+        elif y == 2:
+            res = isinstance(a, B)
+            cls = B
+        else:
+            res = isinstance(a, C)
+            cls = C
+        return int(res) + 2 * isinstance(a, cls)
+    for x in [1, 2, 3]:
+        for y in [1, 2, 3]:
+            res = interpret(f, [x, y])
+            assert res == isinstance([A(), B(), C()][x-1], [A, B, C][y-1]) * 3
+
 def test_isinstance_list():
     def f(i):
         if i == 0:



More information about the Pypy-commit mailing list