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

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Mar 9 12:20:23 CET 2006


Author: cfbolz
Date: Thu Mar  9 12:20:21 2006
New Revision: 24167

Modified:
   pypy/dist/pypy/objspace/logic.py
   pypy/dist/pypy/objspace/test/test_logicobjspace.py
Log:
(cfbolz, pedronis):

experimental change to the logic object space:

use == and cmp and is to unify logical variables. This is really only to get a
feeling for the issues but it's actually very cool, because you can unify lists,
tuples, dictionaries, and even class instances, if they have an __eq__ defined
that uses equality of the __dict__ of the instances.


Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py	(original)
+++ pypy/dist/pypy/objspace/logic.py	Thu Mar  9 12:20:21 2006
@@ -1,7 +1,6 @@
 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
 
 # __________________________________________________________________________
 
@@ -9,6 +8,11 @@
     def __init__(w_self):
         w_self.w_bound_to = None
 
+def find_last_var_in_chain(w_var):
+    w_curr = w_var
+    while w_curr.w_bound_to is not None:
+        w_curr = w_curr.w_bound_to
+    return w_curr
 
 def force(space, w_self):
     if not isinstance(w_self, W_Var):
@@ -45,10 +49,16 @@
 app_is_unbound = gateway.interp2app(is_unbound)
 
 def bind(space, w_var, w_obj):
-    if not space.is_true(is_unbound(space, w_var)):
+    if (not isinstance(w_var, W_Var) and
+        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
+    if isinstance(w_obj, W_Var) and space.is_true(is_unbound(space, w_var)):
+        w_last1 = find_last_var_in_chain(w_var)
+        w_last2 = find_last_var_in_chain(w_obj)
+        if w_last1 is w_last2:
+            return space.w_None
     while w_curr is not None:
         w_next = w_curr.w_bound_to
         w_curr.w_bound_to = w_obj
@@ -59,7 +69,95 @@
 
 # __________________________________________________________________________
 
+nb_forcing_args = {}
+
+def setup():
+    nb_forcing_args.update({
+        'setattr': 2,   # instead of 3
+        'setitem': 2,   # instead of 3
+        'get': 2,       # instead of 3
+        # ---- irregular operations ----
+        'wrap': 0,
+        'str_w': 1,
+        'int_w': 1,
+        'float_w': 1,
+        'uint_w': 1,
+        'interpclass_w': 1,
+        'unwrap': 1,
+        'is_true': 1,
+        'is_w': 2,
+        'newtuple': 0,
+        'newlist': 0,
+        'newstring': 0,
+        'newunicode': 0,
+        'newdict': 0,
+        'newslice': 0,
+        'call_args': 1,
+        'marshal_w': 1,
+        'log': 1,
+        })
+    for opname, _, arity, _ in baseobjspace.ObjSpace.MethodTable:
+        nb_forcing_args.setdefault(opname, arity)
+    for opname in baseobjspace.ObjSpace.IrregularOpTable:
+        assert opname in nb_forcing_args, "missing %r" % opname
+
+setup()
+del setup
+
+def isoreqproxy(space, parentfn):
+    def isoreq(w_obj1, w_obj2):
+        if space.is_true(is_unbound(space, w_obj1)):
+            bind(space, w_obj1, w_obj2)
+            return space.w_True
+        if space.is_true(is_unbound(space, w_obj2)):
+            bind(space, w_obj2, w_obj1)
+            return space.w_True
+        return parentfn(force(space, w_obj1), force(space, w_obj2))
+    return isoreq
+
+def cmpproxy(space, parentfn):
+    def cmp(w_obj1, w_obj2):
+        if space.is_true(is_unbound(space, w_obj1)):
+            bind(space, w_obj1, w_obj2)
+            return space.wrap(0)
+        if space.is_true(is_unbound(space, w_obj2)):
+            bind(space, w_obj2, w_obj1)
+            return space.wrap(0)
+        return parentfn(force(space, w_obj1), force(space, w_obj2))
+    return cmp
+
+def neproxy(space, parentfn):
+    def ne(w_obj1, w_obj2):
+        if (isinstance(w_obj1, W_Var) and isinstance(w_obj2, W_Var) and 
+            space.is_true(is_unbound(space, w_obj1)) and
+            space.is_true(is_unbound(space, w_obj2))):
+            w_var1 = find_last_var_in_chain(w_obj1)
+            w_var2 = find_last_var_in_chain(w_obj2)
+            if w_var1 is w_var2:
+                return space.w_False
+        return parentfn(force(space, w_obj1), force(space, w_obj2))
+    return ne
+
+def is_wproxy(space, parentfn):
+    def is_w(w_obj1, w_obj2):
+        if space.is_true(is_unbound(space, w_obj1)):
+            bind(space, w_obj1, w_obj2)
+            return True
+        if space.is_true(is_unbound(space, w_obj2)):
+            bind(space, w_obj2, w_obj1)
+            return True
+        return parentfn(force(space, w_obj1), force(space, w_obj2))
+    return is_w
+
 def proxymaker(space, opname, parentfn):
+    if opname == "is_w":
+        return is_wproxy(space, parentfn)
+    if opname == "eq" or opname == "is_":
+        return isoreqproxy(space, parentfn)
+    if opname == "ne":
+        return neproxy(space, parentfn)
+    if opname == "cmp":
+        return cmpproxy(space, parentfn)
     nb_args = nb_forcing_args[opname]
     if nb_args == 0:
         proxy = None

Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_logicobjspace.py	(original)
+++ pypy/dist/pypy/objspace/test/test_logicobjspace.py	Thu Mar  9 12:20:21 2006
@@ -48,3 +48,41 @@
         def f(x):
             return x + 1
         raises(ValueError, f, X)
+
+    def test_bind_to_self(self):
+        X = newvar()
+        bind(X, X)
+        bind(X, 1)
+        assert X == 1
+
+    def test_eq_unifies_simple(self):
+        X = newvar()
+        Y = newvar()
+        assert X == Y
+        assert X == 1
+        assert not is_unbound(Y)
+        assert Y == 1
+
+    def test_ne_of_unified_vars(self):
+        X = newvar()
+        Y = newvar()
+        assert X == Y
+        assert not X != Y
+
+    def test_cmp(self):
+        X = newvar()
+        Y = newvar()
+        assert cmp(X, Y) == 0
+        assert is_unbound(X)
+        assert is_unbound(Y)
+        assert X == 1
+        assert not is_unbound(Y)
+        assert Y == 1
+
+    def test_is(self):
+        X = newvar()
+        x = 1
+        assert X is x
+        assert X == 1
+        assert X is x
+



More information about the Pypy-commit mailing list