[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