[pypy-svn] r31161 - in pypy/dist/pypy/objspace: . cclp constraint constraint/test test
auc at codespeak.net
auc at codespeak.net
Tue Aug 8 15:23:34 CEST 2006
Author: auc
Date: Tue Aug 8 15:23:30 2006
New Revision: 31161
Modified:
pypy/dist/pypy/objspace/cclp/scheduler.py
pypy/dist/pypy/objspace/cclp/space.py
pypy/dist/pypy/objspace/cclp/types.py
pypy/dist/pypy/objspace/cclp/variable.py
pypy/dist/pypy/objspace/constraint/domain.py
pypy/dist/pypy/objspace/constraint/test/test_fd.py
pypy/dist/pypy/objspace/logic.py
pypy/dist/pypy/objspace/test/test_logicobjspace.py
Log:
many fixes, constraint vars, domain_of, ....
Modified: pypy/dist/pypy/objspace/cclp/scheduler.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/scheduler.py (original)
+++ pypy/dist/pypy/objspace/cclp/scheduler.py Tue Aug 8 15:23:30 2006
@@ -9,8 +9,6 @@
#-- Singleton scheduler ------------------------------------------------
-class FunnyBoat: pass
-
class Scheduler(object):
def __init__(self, space):
@@ -89,7 +87,7 @@
import traceback
traceback.print_exc()
self.display_head()
- thread._next = thread._prev = FunnyBoat
+ thread._next = thread._prev = None
# cspace/threads account mgmt
if thread._cspace is not None:
count = self.dec_live_thread_count(thread._cspace)
@@ -99,12 +97,14 @@
#-- cspace helper
def is_stable(self, cspace):
- if not self._per_space_live_threads.has_key(cspace):
+ assert isinstance(cspace, W_CSpace)
+ if cspace not in self._per_space_live_threads.keys():
#XXX meaning ?
return True
return self._per_space_live_threads[cspace] == 0
def wait_stable(self, cspace):
+ assert isinstance(cspace, W_CSpace)
if self.is_stable(cspace):
return
curr = ClonableCoroutine.w_getcurrent(self.space)
@@ -120,11 +120,13 @@
#-- cspace -> thread_count helpers
def inc_live_thread_count(self, cspace):
+ assert isinstance(cspace, W_CSpace)
count = self._per_space_live_threads.get(cspace, 0) + 1
self._per_space_live_threads[cspace] = count
return count
def dec_live_thread_count(self, cspace):
+ assert isinstance(cspace, W_CSpace)
count = self._per_space_live_threads[cspace] -1
assert count >= 0
self._per_space_live_threads[cspace] = count
Modified: pypy/dist/pypy/objspace/cclp/space.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/space.py (original)
+++ pypy/dist/pypy/objspace/cclp/space.py Tue Aug 8 15:23:30 2006
@@ -47,18 +47,20 @@
def __init__(self, space, thread, parent=None):
assert isinstance(thread, ClonableCoroutine)
- assert (parent is None) or isinstance(parent, CSpace)
+ assert (parent is None) or isinstance(parent, W_CSpace)
self.space = space # the object space ;-)
self.parent = parent
self.main_thread = thread
# choice mgmt
self._choice = newvar(space)
self._committed = newvar(space)
+ # constraint store ...
+
def w_ask(self):
scheduler[0].wait_stable(self)
self.space.wait(self._choice)
- return self.space.newint(self._choice)
+ return self._choice
def choose(self, n):
assert n > 1
@@ -74,10 +76,13 @@
def w_commit(self, w_n):
assert self.space.is_true(self.space.is_bound(self._choice))
assert 0 < self.space.int_w(w_n)
- assert self.space.int_w(w_n) <= self._choice
+ assert self.space.int_w(w_n) <= self._choice.w_bound_to
self.space.bind(self._committed, w_n)
self._choice = newvar(self.space)
-
+
+
+ def tell(self, w_constraint):
+ pass
W_CSpace.typedef = typedef.TypeDef("W_CSpace",
ask = gateway.interp2app(W_CSpace.w_ask),
@@ -86,13 +91,6 @@
-## def is_top_level(self):
-## return self.parent is None
-
-## def current_space():
-## #XXX return w_getcurrent().cspace
-## pass
-
## def clone(self):
## if self.is_top_level():
@@ -105,20 +103,3 @@
## tclone.cspace = new
## new.threads[tclone] = True
-## def choose(self, n):
-## if self.is_top_level():
-## raise OperationError(self.space.w_RuntimeError,
-## self.space.wrap("Choose"+forbidden_boilerplate))
-
-## def ask(self):
-## if self.is_top_level():
-## raise OperationError(self.space.w_RuntimeError,
-## self.space.wrap("Ask"+forbidden_boilerplate))
-## #XXX basically hang until a call to choose, then return n
-
-## def commit(self, n):
-## if self.is_top_level():
-## raise OperationError(self.space.w_RuntimeError,
-## self.space.wrap("Commit"+forbidden_boilerplate))
-## # ensure 0 < n < chosen n
-## # ...
Modified: pypy/dist/pypy/objspace/cclp/types.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/types.py (original)
+++ pypy/dist/pypy/objspace/cclp/types.py Tue Aug 8 15:23:30 2006
@@ -1,6 +1,7 @@
-from pypy.interpreter import baseobjspace, typedef
+from pypy.interpreter import baseobjspace, gateway, typedef
from pypy.objspace.cclp.misc import w, ClonableCoroutine
+from pypy.objspace.constraint.domain import W_FiniteDomain
W_Root = baseobjspace.W_Root
@@ -20,6 +21,7 @@
prettyfy_id(id(w_self)))
__str__ = __repr__
+
class W_Future(W_Var):
"a read-only-by-its-consummer variant of logic. var"
def __init__(w_self, space):
@@ -27,6 +29,18 @@
w_self._client = ClonableCoroutine.w_getcurrent(space)
w("FUT", str(w_self))
+
+class W_CVar(W_Var):
+ def __init__(w_self, space, w_dom):
+ assert isinstance(w_dom, W_FiniteDomain)
+ W_Var.__init__(w_self, space)
+ w_self.w_dom = w_dom
+
+def domain_of(space, w_v):
+ assert isinstance(w_v, W_CVar)
+ return w_v.w_dom
+app_domain_of = gateway.interp2app(domain_of)
+
#-- Exception types ----------------------------------------
class W_FailedValue(W_Root):
@@ -36,50 +50,6 @@
def __init__(w_self, exc):
w_self.exc = exc
-#-- Something to hold the ring of coros --------------------------------
-
-## class Triple(object):
-
-## def __init__(self, thread):
-## assert isinstance(thread, ClonableCoroutine)
-## self._thread = thread
-## self._prev = self._next = self
-
-## def get_next(self):
-## return self._next
-
-## def get_prev(self):
-## return self._prev
-
-## def set_next(self, triple):
-## assert isinstance(triple, Triple)
-## self._next = triple
-
-## def set_prev(self, triple):
-## assert isinstance(triple, Triple)
-## self._prev = triple
-
-## next = property(get_next, set_next)
-## prev = property(get_prev, set_prev)
-
-## def insert_before(self, triple):
-## assert isinstance(triple, Triple)
-## before = self.prev
-## # ...
-## before.next = triple
-## triple.prev = before
-## # ...
-## self.prev = triple
-## triple.next = self
-
-## def __str__(self):
-## curr = self
-## out = ['[', str(id(self._thread))]
-## while curr != self:
-## curr = self.next
-## out.append(str(id(curr._thread)))
-## return ''.join(out)
-
#-- Misc ---------------------------------------------------
def deref(space, w_var):
Modified: pypy/dist/pypy/objspace/cclp/variable.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/variable.py (original)
+++ pypy/dist/pypy/objspace/cclp/variable.py Tue Aug 8 15:23:30 2006
@@ -6,8 +6,9 @@
from pypy.objspace.cclp.misc import w, v, ClonableCoroutine
from pypy.objspace.cclp.global_state import scheduler
-from pypy.objspace.cclp.types import deref, W_Var, W_Future, W_FailedValue
+from pypy.objspace.cclp.types import deref, W_Var, W_CVar, W_Future, W_FailedValue
+from pypy.objspace.constraint.domain import W_FiniteDomain
W_Root = baseobjspace.W_Root
all_mms = {}
@@ -18,6 +19,14 @@
return w_v
app_newvar = gateway.interp2app(newvar)
+def domain(space, w_values):
+ assert isinstance(w_values, W_ListObject)
+ w_dom = W_FiniteDomain(space, w_values)
+ w_var = W_CVar(space, w_dom)
+ w("CVAR", str(w_var))
+ return w_var
+app_domain = gateway.interp2app(domain)
+
#-- Wait -------------------------------------------------
def wait__Root(space, w_obj):
@@ -110,7 +119,7 @@
all_mms['is_bound'] = is_bound_mm
-def alias_of(space, w_var1, w_var2): # FIXME: appears to block
+def alias_of(space, w_var1, w_var2):
assert isinstance(w_var1, W_Var)
assert isinstance(w_var2, W_Var)
assert space.is_true(space.is_free(w_var1))
@@ -118,9 +127,9 @@
w_curr = w_var1
while 1:
w_next = w_curr.w_bound_to
- if space.is_true(space.is_nb_(w_next, w_var2)):
+ if w_next is w_var2:
return space.newbool(True)
- if space.is_true(space.is_nb_(w_next, w_var1)):
+ if w_next is w_var1:
break
w_curr = w_next
return space.newbool(False)
@@ -140,11 +149,11 @@
w_curr = w_next
-def raise_unification_failure(space):
+def raise_unification_failure(space, comment="Unification failure"):
"""raises a specific exception for bind/unify
should fail the current comp. space at some point"""
raise OperationError(space.w_UnificationError,
- space.wrap("Unification failure"))
+ space.wrap(comment))
# to signal a future binding exception
def raise_future_binding(space):
@@ -170,19 +179,26 @@
#w("var val", str(id(w_var)))
# 3. var and value
if space.is_true(space.is_free(w_var)):
- return _assign(space, w_var, w_obj)
+ return _assign_aliases(space, w_var, w_obj)
if space.is_true(space.eq(w_var.w_bound_to, w_obj)):
return
raise OperationError(space.w_RebindingError,
space.wrap("Cannot bind twice but two identical values"))
-
def bind__Future_Root(space, w_fut, w_obj):
#v("future val", str(id(w_fut)))
if w_fut._client == ClonableCoroutine.w_getcurrent(space):
raise_future_binding(space)
return bind__Var_Root(space, w_fut, w_obj) # call-next-method ?
+def bind__CVar_Root(space, w_cvar, w_obj):
+ #XXX we should (want to) be able to test membership
+ # in a wrapped against wrappeds into a non-wrapped dict
+ if [True for elt in w_cvar.w_dom._values
+ if space.is_true(space.eq(w_obj, elt))]:
+ return bind__Var_Root(space, w_cvar, w_obj)
+ raise_unification_failure(space, "value not in variable domain")
+
def bind__Var_Var(space, w_v1, w_v2):
#w("var var")
if space.is_true(space.is_bound(w_v1)):
@@ -192,10 +208,10 @@
deref(space, w_v1),
deref(space, w_v2))
# 2. a (obj unbound, var bound)
- return _assign(space, w_v2, deref(space, w_v1))
+ return _assign_aliases(space, w_v2, deref(space, w_v1))
elif space.is_true(space.is_bound(w_v2)):
# 2. b (var unbound, obj bound)
- return _assign(space, w_v1, deref(space, w_v2))
+ return _assign_aliases(space, w_v1, deref(space, w_v2))
else: # 1. both are unbound
return _alias(space, w_v1, w_v2)
@@ -205,6 +221,24 @@
raise_future_binding(space)
return bind__Var_Var(space, w_fut, w_var)
+def bind__CVar_CVar(space, w_cvar1, w_cvar2):
+ w_inter_dom = space.intersection(w_cvar1.w_dom, w_cvar2.w_dom)
+ if w_inter_dom.__len__() > 0:
+ if w_inter_dom.__len__() == 1:
+ w_value = w_inter_dom.get_values()[0]
+ _assign_aliases(space, w_cvar1, w_value)
+ _assign_aliases(space, w_cvar2, w_value)
+ else:
+ w_cvar1.w_dom = w_cvar2.w_dom = w_inter_dom
+ _alias(space, w_cvar1, w_cvar2)
+ else:
+ raise_unification_failure(space, "incompatible domains")
+
+def bind__CVar_Var(space, w_cvar, w_var):
+ if space.is_true(space.is_bound(w_var)):
+ return bind__CVar_Root(space, w_cvar, w_var)
+ return bind__Var_Var(space, w_cvar, w_var)
+
def bind__Var_Future(space, w_var, w_fut):
if space.is_true(space.is_bound(w_fut)): #XXX write a test for me !
return bind__Var_Root(space, w_var, deref(space, w_fut))
@@ -218,16 +252,19 @@
bind_mm.register(bind__Future_Root, W_Future, W_Root)
bind_mm.register(bind__Future_Var, W_Future, W_Var)
bind_mm.register(bind__Var_Future, W_Var, W_Future)
+bind_mm.register(bind__CVar_CVar, W_CVar, W_CVar)
+bind_mm.register(bind__CVar_Root, W_CVar, W_Root)
+bind_mm.register(bind__CVar_Var, W_CVar, W_Var)
all_mms['bind'] = bind_mm
-def _assign(space, w_var, w_val):
+def _assign_aliases(space, w_var, w_val):
w(" :assign")
assert isinstance(w_var, W_Var)
assert isinstance(w_val, W_Root)
w_curr = w_var
while 1:
w_next = w_curr.w_bound_to
- w_curr.w_bound_to = w_val
+ _assign(space, w_curr, w_val)
# notify the blocked threads
scheduler[0].unblock_on(w_curr)
if space.is_true(space.is_nb_(w_next, w_var)):
@@ -236,6 +273,14 @@
w_curr = w_next
w(" :assigned")
return space.w_None
+
+def _assign(space, w_var, w_val):
+ assert isinstance(w_var, W_Var)
+ if isinstance(w_var, W_CVar):
+ if not w_val in w_var.w_dom._values:
+ raise_unification_failure(space, "assignment out of domain")
+ w_var.w_bound_to = w_val
+
def _alias(space, w_v1, w_v2):
"""appends one var to the alias chain of another
Modified: pypy/dist/pypy/objspace/constraint/domain.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/domain.py (original)
+++ pypy/dist/pypy/objspace/constraint/domain.py Tue Aug 8 15:23:30 2006
@@ -91,6 +91,7 @@
def size(self):
"""computes the size of a finite domain"""
return len(self._values)
+ __len__ = size
def w_get_values(self):
"""return all the values in the domain
@@ -136,9 +137,9 @@
def intersection__FiniteDomain_FiniteDomain(space, w_fd1, w_fd2):
w_v1 = w_fd1._values
- w_res = [w_v for w_v in w_fd2._values
+ res = [w_v for w_v in w_fd2._values
if w_v in w_v1]
- return make_fd(space, space.newlist(w_res))
+ return make_fd(space, space.newlist(res))
intersection_mm = StdObjSpaceMultiMethod('intersection', 2)
intersection_mm.register(intersection__FiniteDomain_FiniteDomain,
Modified: pypy/dist/pypy/objspace/constraint/test/test_fd.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_fd.py (original)
+++ pypy/dist/pypy/objspace/constraint/test/test_fd.py Tue Aug 8 15:23:30 2006
@@ -2,7 +2,6 @@
from py.test import skip
class AppTest_FiniteDomain(object):
- skip("currently unplugged")
def setup_class(cls):
cls.space = gettestobjspace('logic', usemodules=('_stackless', ))
Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py (original)
+++ pypy/dist/pypy/objspace/logic.py Tue Aug 8 15:23:30 2006
@@ -27,17 +27,19 @@
from pypy.objspace.cclp.variable import app_newvar, wait, app_wait, app_wait_needed, \
app_is_aliased, app_is_free, app_is_bound, app_alias_of, alias_of, app_bind, \
- app_unify, W_Var, W_Future, all_mms as variable_mms
+ app_unify, W_Var, W_CVar, W_Future, app_domain, all_mms as variable_mms
+
+from pypy.objspace.cclp.types import app_domain_of
all_mms.update(variable_mms)
#-- CONSTRAINTS ----------------------------------------------
## #------ domains ------------------
-## from pypy.objspace.constraint import domain
-## all_mms.update(domain.all_mms)
+from pypy.objspace.constraint import domain
+all_mms.update(domain.all_mms)
-## W_FiniteDomain = domain.W_FiniteDomain
+W_FiniteDomain = domain.W_FiniteDomain
## #-------- computationspace --------
## from pypy.objspace.constraint import computationspace
@@ -192,8 +194,9 @@
# multimethods hack
space.model.typeorder[W_Var] = [(W_Var, None), (W_Root, None)] # None means no conversion
space.model.typeorder[W_Future] = [(W_Future, None), (W_Var, None)]
+ space.model.typeorder[W_CVar] = [(W_CVar, None), (W_Var, None)]
space.model.typeorder[W_CSpace] = [(W_CSpace, None), (baseobjspace.Wrappable, None)]
-## space.model.typeorder[W_FiniteDomain] = [(W_FiniteDomain, None), (W_Root, None)]
+ space.model.typeorder[W_FiniteDomain] = [(W_FiniteDomain, None), (W_Root, None)]
for name in all_mms.keys():
@@ -211,13 +214,12 @@
setattr(space, name, boundmethod) # store into 'space' instance
# /multimethods hack
- # XXXprovide a UnificationError exception
- # patching the table in-place?
- #space.ExceptionTable.append('UnificationError')
- #space.ExceptionTable.sort() # hmmm
-
space.setitem(space.builtin.w_dict, space.wrap('newvar'),
space.wrap(app_newvar))
+ space.setitem(space.builtin.w_dict, space.wrap('domain'),
+ space.wrap(app_domain))
+ space.setitem(space.builtin.w_dict, space.wrap('domain_of'),
+ space.wrap(app_domain_of))
space.setitem(space.builtin.w_dict, space.wrap('is_free'),
space.wrap(app_is_free))
space.setitem(space.builtin.w_dict, space.wrap('is_bound'),
@@ -234,10 +236,10 @@
## space.setitem(space.builtin.w_dict, space.wrap('newspace'),
## space.wrap(computationspace.app_newspace))
## #-- domain -------
-## space.setitem(space.builtin.w_dict, space.wrap('FiniteDomain'),
-## space.wrap(domain.app_make_fd))
-## space.setitem(space.builtin.w_dict, space.wrap('intersection'),
-## space.wrap(domain.app_intersection))
+ space.setitem(space.builtin.w_dict, space.wrap('FiniteDomain'),
+ space.wrap(domain.app_make_fd))
+ space.setitem(space.builtin.w_dict, space.wrap('intersection'),
+ space.wrap(domain.app_intersection))
## #-- constraint ----
## space.setitem(space.builtin.w_dict, space.wrap('make_expression'),
## space.wrap(constraint.app_make_expression))
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 Tue Aug 8 15:23:30 2006
@@ -621,6 +621,55 @@
assert len(sched_all()['threads']) == 1
+class AppTest_CompSpace(object):
+
+ def setup_class(cls):
+ cls.space = gettestobjspace('logic', usemodules=("_stackless",))
+
+ def test_cvar(self):
+
+ d = domain([1, 2, 4])
+
+ raises(UnificationError, bind, d, 42)
+ bind(d, 2)
+ assert d == 2
+
+ class Foo(object):
+ pass
+
+ f = Foo()
+ d = domain([Foo(), f, Foo()])
+ raises(UnificationError, bind, d, Foo())
+ bind(d, f)
+ assert d == f
+
+ d1 = domain([1, 2, 3])
+ d2 = domain([2, 3, 4])
+ d3 = domain([5, 6])
+ raises(UnificationError, unify, d1, d3)
+ unify(d1, d2)
+ assert alias_of(d1, d2)
+ assert domain_of(d1) == domain_of(d2) == FiniteDomain([2, 3])
+
+ d1 = domain([1, 2, 3])
+ d4 = domain([3, 4])
+ unify(d1, d4)
+ assert d1 == d4 == 3
+
+ d1 = domain([1, 2])
+ x = newvar()
+ unify(d1, x)
+ assert alias_of(x, d1)
+ raises(UnificationError, unify, x, 42)
+
+ d1 = domain([1, 2])
+ x = newvar()
+ unify(d1, x)
+ assert alias_of(x, d1)
+ unify(x, 2)
+ assert d1 == x == 2
+ #XXX and a bunch of app-level functions
+ #raises(TypeError, domain_of, x)
def test_newspace_ask_wait(self):
@@ -660,19 +709,35 @@
assert X == 2
- def test_ask_choose(self):
+ def test_more_ask_choose(self):
- def chooser(X):
- choice = choose(3)
- unify(X, choice)
+ def chooser(vec, X):
+ for v in vec:
+ choice = choose(v)
+ assert choice == v
+ unify(X, 'done')
def asker(cspace):
- choices = cspace.ask()
- cspace.commit(2)
+ while 1:
+ choices = cspace.ask()
+ if choices == 1: # success !
+ break
+ cspace.commit(choices)
+ # choices >= 1
+ v = range(2, 9)
X = newvar()
-
- s = newspace(chooser, X)
+ s = newspace(chooser, v, X)
stacklet(asker, s)
+
schedule()
- assert X == 2
+
+ assert len(sched_all()['asking']) == 1
+ assert sched_all()['space_accounting'][0][1] == 0
+
+ assert X == 'done'
+ schedule()
+ assert len(sched_all()['threads']) == 1
+
+
+
More information about the Pypy-commit
mailing list