[pypy-svn] r25379 - in pypy/dist/pypy/rpython: ootypesystem ootypesystem/test test

nik at codespeak.net nik at codespeak.net
Wed Apr 5 15:06:39 CEST 2006


Author: nik
Date: Wed Apr  5 15:06:38 2006
New Revision: 25379

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rlist.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py
   pypy/dist/pypy/rpython/test/test_rlist.py
Log:
make recursive data structures involving lists work in ootypesystem.
this involved letting List types fall back to LowLevelType for
__eq__ and __hash__.


Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Wed Apr  5 15:06:38 2006
@@ -1,6 +1,6 @@
 from pypy.rpython.lltypesystem.lltype import LowLevelType, Signed, Unsigned, Float, Char
 from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, \
-        Primitive, isCompatibleType, enforce
+        Primitive, isCompatibleType, enforce, saferecursive
 from pypy.rpython.lltypesystem.lltype import frozendict, isCompatibleType
 from pypy.tool.uid import uid
 
@@ -186,19 +186,15 @@
             "setitem": Meth([Signed, ITEMTYPE], Void),
         })
 
-    def __str__(self):
-        return '%s(%s)' % (self.__class__.__name__, self._ITEMTYPE)
-
-    def __eq__(self, other):
-        if not isinstance(other, List):
-            return False
-        return self._ITEMTYPE == other._ITEMTYPE
-
-    def __ne__(self, other):
-        return not (self == other)
+    # NB: We are expecting Lists of the same ITEMTYPE to compare/hash
+    # equal. We don't redefine __eq__/__hash__ since the implementations
+    # from LowLevelType work fine, especially in the face of recursive
+    # data structures. But it is important to make sure that attributes
+    # of supposedly equal Lists compare/hash equal.
 
-    def __hash__(self):
-        return hash(self._ITEMTYPE)
+    def __str__(self):
+        return '%s(%s)' % (self.__class__.__name__,
+                saferecursive(str, "...")(self._ITEMTYPE))
 
     def _lookup(self, meth_name):
         METH = self._METHODS.get(meth_name)
@@ -214,6 +210,18 @@
     def _defl(self):
         return self._null
 
+
+class ForwardReference(OOType):
+    def become(self, real_instance):
+        if not isinstance(real_instance, (Instance, List)):
+            raise TypeError("ForwardReference can only be to an instance, "
+                            "not %r" % (real_instance,))
+        self.__class__ = real_instance.__class__
+        self.__dict__ = real_instance.__dict__
+
+    def __hash__(self):
+        raise TypeError("%r object is not hashable" % self.__class__.__name__)
+
 # ____________________________________________________________
 
 class _class(object):
@@ -316,6 +324,9 @@
             if not isinstance(other, klass):
                 raise TypeError("comparing an %s with %r" % (klass.__name__, other))
             return not other
+
+        def __hash__(self):
+            return hash(self._TYPE)
     return mixin
 
 class _null_instance(_null_mixin(_instance), _instance):

Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py	Wed Apr  5 15:06:38 2006
@@ -15,6 +15,7 @@
         if not isinstance(item_repr, Repr):  # not computed yet, done by setup()
             assert callable(item_repr)
             self._item_repr_computer = item_repr
+            self.lowleveltype = ootype.ForwardReference()
         else:
             self.lowleveltype = ootype.List(item_repr.lowleveltype)
             self.external_item_repr, self.item_repr = \
@@ -27,7 +28,8 @@
         if 'item_repr' not in self.__dict__:
             self.external_item_repr, self.item_repr = \
                     externalvsinternal(self.rtyper, self._item_repr_computer())
-            self.lowleveltype = ootype.List(self.item_repr.lowleveltype)
+        if isinstance(self.lowleveltype, ootype.ForwardReference):
+            self.lowleveltype.become(ootype.List(self.item_repr.lowleveltype))
 
     def send_message(self, hop, message, can_raise=False):
         v_args = hop.inputargs(self, *hop.args_r[1:])

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py	Wed Apr  5 15:06:38 2006
@@ -45,6 +45,20 @@
     assert LT1 != LT3
     assert hash(LT1) == hash(LT2)
 
+def test_recursive():
+    FORWARD = ForwardReference()
+    LT = List(FORWARD)
+    FORWARD.become(LT)
+    assert LT == LT
+    assert hash(LT) == hash(LT)
+    str(LT) # make sure this doesn't recurse infinitely
+
+    FORWARD2 = ForwardReference()
+    LT2 = List(FORWARD2)
+    FORWARD2.become(LT2)
+    assert LT == LT2
+    assert hash(LT) == hash(LT2)
+
 class TestInterpreted:
 
     def test_append_length(self):

Modified: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rlist.py	Wed Apr  5 15:06:38 2006
@@ -215,24 +215,24 @@
         res = interpret(dummyfn, [], type_system=self.ts)
         assert res == 25
 
-def test_recursive():
-    def dummyfn(N):
-        l = []
-        while N > 0:
-            l = [l]
-            N -= 1
-        return len(l)
-    res = interpret(dummyfn, [5])
-    assert res == 1
-
-    def dummyfn(N):
-        l = []
-        while N > 0:
-            l.append(l)
-            N -= 1
-        return len(l)
-    res = interpret(dummyfn, [5])
-    assert res == 5
+    def test_recursive(self):
+        def dummyfn(N):
+            l = []
+            while N > 0:
+                l = [l]
+                N -= 1
+            return len(l)
+        res = interpret(dummyfn, [5], type_system=self.ts)
+        assert res == 1
+
+        def dummyfn(N):
+            l = []
+            while N > 0:
+                l.append(l)
+                N -= 1
+            return len(l)
+        res = interpret(dummyfn, [5])
+        assert res == 5
 
 def tolst(l):
     return map(None, l.ll_items())[:l.ll_length()]



More information about the Pypy-commit mailing list