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

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Mar 9 09:52:51 CET 2006


Author: cfbolz
Date: Thu Mar  9 09:52:50 2006
New Revision: 24149

Added:
   pypy/dist/pypy/objspace/logic.py
   pypy/dist/pypy/objspace/test/test_logicobjspace.py
Modified:
   pypy/dist/pypy/bin/py.py
   pypy/dist/pypy/conftest.py
Log:
add a logic object space, which is some sort of dumbed-down and sanitized
version of the thunk object space: you have Variables which can be bound to
other Variables and to objects. after they are bound to objects they are
replaced by that object everywhere. the "forcing" of logic variables happens at
the same places as in the thunk object space, although since tasklets are not
quite done, we crash if we try to do an operation on unbound variables (what
really should happen is that the current tasklet blocks until another tasklet
binds the variable).


Modified: pypy/dist/pypy/bin/py.py
==============================================================================
--- pypy/dist/pypy/bin/py.py	(original)
+++ pypy/dist/pypy/bin/py.py	Thu Mar  9 09:52:50 2006
@@ -58,6 +58,8 @@
         from pypy.objspace.std import Space
     elif cmdlineopt.objspace == 'thunk':
         from pypy.objspace.thunk import Space
+    elif cmdlineopt.objspace == 'logic':
+        from pypy.objspace.logic import Space
     else:
         raise ValueError("cannot instantiate %r space" %(cmdlineopt.objspace,))
 

Modified: pypy/dist/pypy/conftest.py
==============================================================================
--- pypy/dist/pypy/conftest.py	(original)
+++ pypy/dist/pypy/conftest.py	Thu Mar  9 09:52:50 2006
@@ -54,7 +54,7 @@
     try:
         return _SPACECACHE[key]
     except KeyError:
-        assert name in ('std', 'thunk'), name 
+        assert name in ('std', 'thunk', 'logic'), name 
         mod = __import__('pypy.objspace.%s' % name, None, None, ['Space'])
         Space = mod.Space
         try: 

Added: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/logic.py	Thu Mar  9 09:52:50 2006
@@ -0,0 +1,97 @@
+from pypy.objspace.proxy import patch_space_in_place
+from pypy.interpreter import gateway, baseobjspace, argument
+from pypy.interpreter.error import OperationError
+from pypy.objspace.thunk import nb_forcing_args
+
+# __________________________________________________________________________
+
+class W_Var(baseobjspace.W_Root, object):
+    def __init__(w_self):
+        w_self.w_bound_to = None
+
+
+def force(space, w_self):
+    if not isinstance(w_self, W_Var):
+        return w_self
+    w_bound_to = w_self.w_bound_to
+    while isinstance(w_bound_to, W_Var):
+        w_bound_to = w_bound_to.w_bound_to
+    if w_bound_to is None:
+        # XXX here we would have to suspend the current thread
+        # for now just crash
+        assert 0, "green threads not implemented yet"
+    else:
+        # actually attach the object directly to each variable
+        # to remove indirections
+        w_obj = w_bound_to
+        w_curr = w_self
+        while w_curr.w_bound_to is not w_obj:
+            w_next = w_curr.w_bound_to
+            w_curr.w_bound_to = w_obj
+            w_curr = w_next
+        return w_obj
+
+def newvar(space):
+    return W_Var()
+app_newvar = gateway.interp2app(newvar)
+
+def is_unbound(space, w_var):
+    if not isinstance(w_var, W_Var):
+        return space.newbool(False)
+    w_curr = w_var
+    while isinstance(w_curr, W_Var):
+        w_curr = w_curr.w_bound_to
+    return space.newbool(w_curr is None)
+app_is_unbound = gateway.interp2app(is_unbound)
+
+def bind(space, w_var, w_obj):
+    if not space.is_true(is_unbound(space, w_var)):
+        raise OperationError(space.w_TypeError,
+                             space.wrap("can only bind unbound logic variable"))
+    w_curr = w_var
+    while w_curr is not None:
+        w_next = w_curr.w_bound_to
+        w_curr.w_bound_to = w_obj
+        w_curr = w_next
+    return space.w_None
+app_bind = gateway.interp2app(bind)
+
+
+# __________________________________________________________________________
+
+def proxymaker(space, opname, parentfn):
+    nb_args = nb_forcing_args[opname]
+    if nb_args == 0:
+        proxy = None
+    elif nb_args == 1:
+        def proxy(w1, *extra):
+            w1 = force(space, w1)
+            return parentfn(w1, *extra)
+    elif nb_args == 2:
+        def proxy(w1, w2, *extra):
+            w1 = force(space, w1)
+            w2 = force(space, w2)
+            return parentfn(w1, w2, *extra)
+    elif nb_args == 3:
+        def proxy(w1, w2, w3, *extra):
+            w1 = force(space, w1)
+            w2 = force(space, w2)
+            w3 = force(space, w3)
+            return parentfn(w1, w2, w3, *extra)
+    else:
+        raise NotImplementedError("operation %r has arity %d" %
+                                  (opname, nb_args))
+    return proxy
+
+def Space(*args, **kwds):
+    # for now, always make up a wrapped StdObjSpace
+    from pypy.objspace import std
+    space = std.Space(*args, **kwds)
+    patch_space_in_place(space, 'logic', proxymaker)
+    space.setitem(space.builtin.w_dict, space.wrap('newvar'),
+                  space.wrap(app_newvar))
+    space.setitem(space.builtin.w_dict, space.wrap('is_unbound'),
+                  space.wrap(app_is_unbound))
+    space.setitem(space.builtin.w_dict, space.wrap('bind'),
+                 space.wrap(app_bind))
+    return space

Added: pypy/dist/pypy/objspace/test/test_logicobjspace.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/test/test_logicobjspace.py	Thu Mar  9 09:52:50 2006
@@ -0,0 +1,45 @@
+from pypy.conftest import gettestobjspace
+
+class AppTest_Logic(object):
+
+    def setup_class(cls):
+        cls.space = gettestobjspace('logic')
+
+    def test_simple(self):
+        X = newvar()
+        assert is_unbound(X)
+        bind(X, 1)
+        assert type(X) == int
+        assert not is_unbound(X)
+        assert not is_unbound(1)
+        raises(TypeError, bind, 1, 2)
+
+    def test_setitem(self):
+        x = newvar()
+        d = {5: x}
+        d[6] = x
+        d[7] = []
+        d[7].append(x)
+        y = d[5], d[6], d.values(), d.items()
+        for x in [d[5], d[6], d[7][0]]:
+            assert is_unbound(d[5])
+        bind(x, 1)
+        for x in [d[5], d[6], d[7][0]]:
+            assert not is_unbound(d[5])
+
+    def test_unbound_unification_simple(self):
+        X = newvar()
+        Y = newvar()
+        bind(X, Y)
+        bind(X, 1)
+        assert X == 1
+        assert Y == 1
+
+    def test_unbound_unification_long(self):
+        l = [newvar() for i in range(40)]
+        for i in range(39):
+            bind(l[i], l[i + 1])
+        bind(l[20], 1)
+        for i in range(40):
+            assert l[i] == 1
+



More information about the Pypy-commit mailing list