[pypy-svn] r18678 - in pypy/dist/pypy/rpython: . lltypesystem ootypesystem ootypesystem/test

mwh at codespeak.net mwh at codespeak.net
Sun Oct 16 12:54:46 CEST 2005


Author: mwh
Date: Sun Oct 16 12:54:43 2005
New Revision: 18678

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
   pypy/dist/pypy/rpython/typesystem.py
Log:
(mwh, bert, samuele)
We didn't have a test that had a variable that potentially
contained an instance of either of a base class or its subclass.
When we added one, we found a range of subtle problems with lltype-era
assumptions in llinterp and other places.  OOTypes now has a notion
of upcasting and llinterp has a few changes to accomodate this.


Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sun Oct 16 12:54:43 2005
@@ -124,7 +124,7 @@
 
     def setvar(self, var, val):
         if var.concretetype != self.llt.Void:
-            assert var.concretetype == self.llt.typeOf(val)
+            assert self.llinterpreter.typer.type_system.isCompatibleType(self.llt.typeOf(val), var.concretetype)
         assert isinstance(var, Variable)
         self.bindings[var] = val
 
@@ -221,7 +221,7 @@
         ophandler = self.getoperationhandler(operation.opname)
         vals = [self.getval(x) for x in operation.args]
         # if these special cases pile up, do something better here
-        if operation.opname == 'cast_pointer':
+        if operation.opname in ['cast_pointer', 'ooupcast']:
             vals.insert(0, operation.result.concretetype)
         retval = ophandler(*vals)
         self.setvar(operation.result, retval)
@@ -641,6 +641,9 @@
         assert isinstance(inst, ootype._instance)
         assert isinstance(message, str)
         return getattr(inst, message)(*args)
+
+    def op_ooupcast(self, INST, inst):
+        return ootype.ooupcast(INST, inst)
     
 # by default we route all logging messages to nothingness
 # e.g. tests can then switch on logging to get more help

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Sun Oct 16 12:54:43 2005
@@ -962,6 +962,9 @@
                                  "        returned: %s,\n"
                                  "should have been: %s" % (p, result2, result))
     return result
+
+def isCompatibleType(TYPE1, TYPE2):
+    return TYPE1 == TYPE2
     
 # FIXME
 __all__ = ['Array', 'Bool', 'Char', 'ContainerType', 'Float',
@@ -974,5 +977,5 @@
 'castable', 'flavored_malloc', 'frozendict', 'functionptr',
 'getRuntimeTypeInfo', 'log', 'malloc', 'nullptr', 'opaqueptr', 'operator',
 'parentlink', 'py', 'pyobjectptr', 'r_uint', 'runtime_type_info', 'safe_equal',
-'saferecursive', 'tlsobject', 'typeOf', 'weakref']
+'saferecursive', 'tlsobject', 'typeOf', 'weakref', 'isCompatibleType']
 

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Sun Oct 16 12:54:43 2005
@@ -190,10 +190,7 @@
 	   raise TypeError,"calling %r with wrong argument number: %r" % (self._TYPE, args)
 
        for a, ARG in zip(args, self._TYPE.ARGS):
-           if typeOf(a) != ARG:
-               if isinstance(ARG, Instance) and isinstance(a, _instance):
-                    if instanceof(a, ARG):
-                        continue
+           if not isCompatibleType(typeOf(a), ARG):
                raise TypeError,"calling %r with wrong argument types: %r" % (self._TYPE, args)
        callb = self._callable
        if callb is None:
@@ -273,3 +270,16 @@
             return c
         c = c._superclass
     return None
+
+def isCompatibleType(TYPE1, TYPE2):
+    if TYPE1 == TYPE2:
+        return True
+    if isinstance(TYPE1, Instance) and isinstance(TYPE2, Instance):
+        return isSubclass(TYPE1, TYPE2)
+    else:
+        return False
+        
+def ooupcast(INSTANCE, instance):
+    assert instanceof(instance, INSTANCE)
+    return instance
+    

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Sun Oct 16 12:54:43 2005
@@ -3,6 +3,7 @@
                                 getinstancerepr
 from pypy.rpython.rpbc import getsignature
 from pypy.rpython.ootypesystem import ootype
+from pypy.annotation.pairtype import pairtype
 
 CLASSTYPE = ootype.Class
 
@@ -90,3 +91,26 @@
 
         return llops.genop("new",
             [inputconst(ootype.Void, self.lowleveltype)], self.lowleveltype)
+
+
+class __extend__(pairtype(InstanceRepr, InstanceRepr)):
+    def convert_from_to((r_ins1, r_ins2), v, llops):
+        # which is a subclass of which?
+        if r_ins1.classdef is None or r_ins2.classdef is None:
+            basedef = None
+        else:
+            basedef = r_ins1.classdef.commonbase(r_ins2.classdef)
+        if basedef == r_ins2.classdef:
+            # r_ins1 is an instance of the subclass: converting to parent
+            v = llops.genop('ooupcast', [v],
+                            resulttype = r_ins2.lowleveltype)
+            return v
+        elif basedef == r_ins1.classdef:
+            # r_ins2 is an instance of the subclass: potentially unsafe
+            # casting, but we do it anyway (e.g. the annotator produces
+            # such casts after a successful isinstance() check)
+            v = llops.genop('oodowncast', [v],
+                            resulttype = r_ins2.lowleveltype)
+            return v
+        else:
+            return NotImplemented

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	Sun Oct 16 12:54:43 2005
@@ -76,6 +76,21 @@
     result = interpret(dummyfn, [], type_system='ootype')
     assert result == 1 + 2 + 3
 
+def test_polymorphic_field():
+    def dummyfn(choosesubclass):
+        if choosesubclass:
+            y = Subclass()
+            y.a = 0
+            y.b = 1
+        else:
+            y = EmptyBase()
+            y.a = 1
+        return y.a
+    result = interpret(dummyfn, [True], type_system='ootype')
+    assert result == 0
+    result = interpret(dummyfn, [False], type_system='ootype')
+    assert result == 1    
+
 class HasAMethod(object):
     def f(self):
         return 1

Modified: pypy/dist/pypy/rpython/typesystem.py
==============================================================================
--- pypy/dist/pypy/rpython/typesystem.py	(original)
+++ pypy/dist/pypy/rpython/typesystem.py	Sun Oct 16 12:54:43 2005
@@ -74,6 +74,9 @@
     def getconcretetype(self, v):
         return getattr(v, 'concretetype', lltype.Ptr(lltype.PyObject))
 
+    def isCompatibleType(self, t1, t2):
+        return lltype.isCompatibleType(t1, t2)
+
 class ObjectOrientedTypeSystem(TypeSystem):
     name = "ootypesystem"
     callable_trait = (ootype.StaticMethod, ootype.static_meth)
@@ -84,6 +87,9 @@
         assert isinstance(ootype.typeOf(obj), ootype.OOType)
         return obj
 
+    def isCompatibleType(self, t1, t2):
+        return ootype.isCompatibleType(t1, t2)
+
 # All typesystems are singletons
 LowLevelTypeSystem.instance = LowLevelTypeSystem()
 ObjectOrientedTypeSystem.instance = ObjectOrientedTypeSystem()



More information about the Pypy-commit mailing list