[pypy-svn] r42689 - in pypy/dist/pypy/objspace: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Fri May 4 19:13:09 CEST 2007


Author: cfbolz
Date: Fri May  4 19:13:08 2007
New Revision: 42689

Modified:
   pypy/dist/pypy/objspace/test/test_thunkobjspace.py
   pypy/dist/pypy/objspace/thunk.py
Log:
solve various recurivity problems in the thunk space


Modified: pypy/dist/pypy/objspace/test/test_thunkobjspace.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_thunkobjspace.py	(original)
+++ pypy/dist/pypy/objspace/test/test_thunkobjspace.py	Fri May  4 19:13:08 2007
@@ -1,4 +1,5 @@
 from pypy.conftest import gettestobjspace
+from pypy.interpreter import gateway
 
 class AppTest_Thunk:
 
@@ -64,6 +65,15 @@
         become(y, z)
         assert x is y is z
 
+    def test_double_become2(self):
+        from __pypy__ import thunk, become
+        x = []
+        y = []
+        z = []
+        become(x, y)
+        become(x, z)
+        assert x is y is z
+
     def test_thunk_forcing_while_forcing(self):
         from __pypy__ import thunk, become
         def f():
@@ -71,7 +81,7 @@
         x = thunk(f)
         raises(RuntimeError, 'x+1')
 
-    def INPROGRESS_test_thunk_forcing_while_forcing_2(self):
+    def test_thunk_forcing_while_forcing_2(self):
         from __pypy__ import thunk, become
         def f():
             return x
@@ -85,6 +95,26 @@
         assert is_thunk(thunk(f))
         assert not is_thunk(42)
 
+    def test_is_thunk2(self):
+        from __pypy__ import thunk, become, is_thunk
+        def f():
+            return 42
+        x = thunk(f)
+        assert is_thunk(x)
+        assert x == 42
+        assert not is_thunk(x)
+
+    def test_is_thunk_become(self):
+        from __pypy__ import thunk, become, is_thunk
+        def f():
+            return 42
+        x = thunk(f)
+        y = []
+        become(y, x)
+        assert is_thunk(y)
+        assert y == 42
+        assert not is_thunk(y)
+
     def test_lazy(self):
         from __pypy__ import lazy
         lst = []
@@ -110,4 +140,10 @@
         assert y == 42
         y = f(0)
         raises(ValueError, "str(y)")
-        raises(ValueError, "str(y)") # raises "RuntimeError: thunk is already being computed"
+        raises(ValueError, "str(y)")
+
+    def test_become_yourself(self):
+        from __pypy__ import become
+        x = []
+        become(x, x)
+        assert str(x) == "[]"

Modified: pypy/dist/pypy/objspace/thunk.py
==============================================================================
--- pypy/dist/pypy/objspace/thunk.py	(original)
+++ pypy/dist/pypy/objspace/thunk.py	Fri May  4 19:13:08 2007
@@ -73,12 +73,30 @@
             except OperationError, operr:
                 w_self.operr = operr
                 raise
-            # XXX detect circular w_alias result
+            if _is_circular(w_self, w_alias):
+                operr = OperationError(space.w_RuntimeError,
+                                       space.wrap("circular thunk alias"))
+                w_self.operr = operr
+                raise operr
             w_self.w_thunkalias = w_alias
+        # XXX do path compression?
         w_self = w_alias
         w_alias = w_self.w_thunkalias
     return w_self
 
+def _is_circular(w_obj, w_alias):
+    assert (w_obj.w_thunkalias is None or
+            w_obj.w_thunkalias is w_NOT_COMPUTED_THUNK)
+    while 1:
+        if w_obj is w_alias:
+            return True
+        w_next = w_alias.w_thunkalias
+        if w_next is None:
+            return False
+        if w_next is w_NOT_COMPUTED_THUNK:
+            return False
+        w_alias = w_next
+
 def force(space, w_self):
     if w_self.w_thunkalias is not None:
         w_self = _force(space, w_self)
@@ -93,13 +111,20 @@
 
 def is_thunk(space, w_obj):
     """Check if an object is a thunk that has not been computed yet."""
-    return space.newbool(w_obj.w_thunkalias is w_NOT_COMPUTED_THUNK)
+    while 1:
+        w_alias = w_obj.w_thunkalias
+        if w_alias is None:
+            return space.w_False
+        if w_alias is w_NOT_COMPUTED_THUNK:
+            return space.w_True
+        w_obj = w_alias
 app_is_thunk = gateway.interp2app(is_thunk)
 
 def become(space, w_target, w_source):
     """Globally replace the target object with the source one."""
     w_target = force(space, w_target)
-    w_target.w_thunkalias = w_source
+    if not _is_circular(w_target, w_source):
+        w_target.w_thunkalias = w_source
     return space.w_None
 app_become = gateway.interp2app(become)
 



More information about the Pypy-commit mailing list