[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