[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