[pypy-svn] r31207 - in pypy/dist/pypy/objspace: . cclp cclp/constraint test

auc at codespeak.net auc at codespeak.net
Wed Aug 9 17:38:20 CEST 2006


Author: auc
Date: Wed Aug  9 17:38:15 2006
New Revision: 31207

Added:
   pypy/dist/pypy/objspace/cclp/constraint/
   pypy/dist/pypy/objspace/cclp/constraint/__init__.py
   pypy/dist/pypy/objspace/cclp/constraint/constraint.py
   pypy/dist/pypy/objspace/cclp/constraint/domain.py
Modified:
   pypy/dist/pypy/objspace/cclp/misc.py
   pypy/dist/pypy/objspace/cclp/scheduler.py
   pypy/dist/pypy/objspace/cclp/space.py
   pypy/dist/pypy/objspace/cclp/thunk.py
   pypy/dist/pypy/objspace/cclp/types.py
   pypy/dist/pypy/objspace/cclp/variable.py
   pypy/dist/pypy/objspace/logic.py
   pypy/dist/pypy/objspace/test/test_logicobjspace.py
Log:
tell (to declare cosntraints)


Added: pypy/dist/pypy/objspace/cclp/constraint/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/cclp/constraint/__init__.py	Wed Aug  9 17:38:15 2006
@@ -0,0 +1 @@
+# pass

Added: pypy/dist/pypy/objspace/cclp/constraint/constraint.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py	Wed Aug  9 17:38:15 2006
@@ -0,0 +1,214 @@
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter import baseobjspace, typedef, gateway
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.function import Function
+
+from pypy.objspace.std.listobject import W_ListObject
+from pypy.objspace.std.stringobject import W_StringObject
+
+from pypy.objspace.constraint.computationspace import W_ComputationSpace
+
+from pypy.objspace.cclp.types import W_Constraint, W_CVar as W_Variable
+
+from pypy.objspace.std.model import StdObjSpaceMultiMethod
+
+from pypy.objspace.constraint.btree import BTree
+from pypy.objspace.constraint.util import sort, reverse
+
+import operator
+
+all_mms = {}
+
+
+#-- Exceptions ---------------------------------------
+
+class ConsistencyFailure(Exception):
+    """The repository is not in a consistent state"""
+    pass
+
+class DomainlessVariables(Exception):
+    """A constraint can't be defined on variables
+       without a domain"""
+    pass
+
+#-- Constraints ------------------------------------------
+
+class W_AbstractConstraint(W_Constraint):
+    
+    def __init__(self, object_space, w_variables):
+        """variables is a list of variables which appear in the formula"""
+        W_Constraint.__init__(self, object_space)
+        assert isinstance(w_variables, W_ListObject)
+        assert self._space.is_true(self._space.ge(self._space.len(w_variables),
+                                                  self._space.newint(1)))
+        self._names_to_vars = {}
+        for var in w_variables.wrappeditems:
+            self._names_to_vars[var.name_w()] = var
+        self._variables = w_variables.wrappeditems #unwrap once ...
+
+    def w_affected_variables(self):
+        """ Return a list of all variables affected by this constraint """
+        return self._space.newlist(self._variables)
+
+    def affected_variables(self):
+        return self._variables
+
+    def w_knows_var(self, w_variable):
+        assert isinstance(w_variable, W_Variable)
+        return self._space.newbool(w_variable in self._variables)
+
+    def w_revise(self):
+        return self._space.newbool(self.space.revise())
+    
+
+##     def __eq__(self, other): #FIXME and parent
+##         if not isinstance(other, self.__class__): return False
+##         return self._variables == other._variables
+    
+W_AbstractConstraint.typedef = typedef.TypeDef(
+    "W_AbstractConstraint",
+    W_Constraint.typedef,                                           
+    affected_variables = interp2app(W_AbstractConstraint.w_affected_variables),
+    knows_var = interp2app(W_AbstractConstraint.w_knows_var),
+    revise = interp2app(W_AbstractConstraint.w_revise)) 
+
+
+
+from pypy.module.__builtin__.compiling import eval as ev
+def make_filter__List_String(object_space, w_variables, w_formula):
+    """NOT RPYTHON"""
+    assert isinstance(w_variables, W_ListObject)
+    assert isinstance(w_formula, W_StringObject)
+    items = object_space.unpackiterable(w_variables)
+    for it in items:
+        assert isinstance(it, W_Variable)
+    var_ids = ','.join([var.name_w()
+                        for var in items]) 
+    func_head = 'lambda ' + var_ids + ':'
+    expr = func_head + object_space.str_w(w_formula)
+    func_obj = ev(object_space, object_space.wrap(expr), object_space.newdict([]),
+                                 object_space.newdict([]))
+    assert isinstance(func_obj, Function)
+    return func_obj
+
+make_filter_mm = StdObjSpaceMultiMethod('make_filter', 2)
+make_filter_mm.register(make_filter__List_String, W_ListObject, W_StringObject)
+all_mms['make_filter'] = make_filter_mm
+
+class W_Expression(W_AbstractConstraint):
+    """A constraint represented as a python expression."""
+
+    def __init__(self, object_space, w_variables, w_formula):
+        """variables is a list of variables which appear in the formula
+        formula is a python expression that will be evaluated as a boolean"""
+        W_AbstractConstraint.__init__(self, object_space, w_variables)
+        self.formula = self._space.str_w(w_formula)
+        # self.filter_func is a function taking keyword arguments and returning a boolean
+        self.filter_func = self._space.make_filter(w_variables, w_formula)
+
+    def test_solution(self, sol_dict):
+        """test a solution against this constraint 
+        accept a mapping of variable names to value"""
+        args = []
+        for var in self._variables:
+            assert isinstance(var, W_Variable)
+            args.append(sol_dict[var.w_name()])
+        return self.filter_func(*args)
+
+    def _init_result_cache(self):
+        """key = (variable,value), value = [has_success,has_failure]"""
+        result_cache = self._space.newdict([])
+        for var in self._variables:
+            assert isinstance(var, W_Variable)
+            result_cache.content[var.w_name()] = self._space.newdict([])
+        return result_cache
+
+    def _assign_values(self):
+        variables = []
+        kwargs = self._space.newdict([])
+        for variable in self._variables:
+            assert isinstance(variable, W_Variable)
+            domain = variable.w_dom
+            values = domain.w_get_values()
+            variables.append((domain.size(),
+                              [variable, values, self._space.newint(0),
+                               self._space.len(values)]))
+            kwargs.content[variable.w_name()] = values.wrappeditems[0]
+        # sort variables to instanciate those with fewer possible values first
+        sort(variables)
+        res_kwargs = []
+        go_on = 1
+        while go_on:
+#            res_kwargs.append( kwargs)
+            yield kwargs
+            # try to instanciate the next variable
+            
+            for size, curr in variables:
+                assert isinstance(curr[0], W_Variable)
+                w_name = curr[0].w_name()
+                assert isinstance(w_name, W_StringObject)
+                if self._space.int_w(curr[2]) + 1 < self._space.int_w(curr[-1]):
+                    curr[2] = self._space.add(curr[2], self._space.newint(1))
+                    kwargs.content[w_name] = curr[1].wrappeditems[self._space.int_w(curr[2])]
+                    break
+                else:
+                    curr[2] = self._space.newint(0)
+                    kwargs.content[w_name] = curr[1].wrappeditems[0]
+            else:
+                # it's over
+                go_on = 0
+#                return res_kwargs
+
+    def revise(self):
+        """generic propagation algorithm for n-ary expressions"""
+        maybe_entailed = True
+        ffunc = self.filter_func
+        result_cache = self._init_result_cache()
+        for kwargs in self._assign_values():
+            if maybe_entailed:
+                for varname, val in kwargs.content.iteritems():
+                    if val not in result_cache.content[varname].content:
+                        break
+                else:
+                    continue
+            if self._space.is_true(self._space.call(self._space.wrap(ffunc),
+                                                    self._space.newlist([]), kwargs)):
+                for var, val in kwargs.content.items():
+                    result_cache.content[var].content[val] = self._space.w_True
+            else:
+                maybe_entailed = False
+
+        try:
+            for varname, keep in result_cache.content.items():
+                domain = self._names_to_vars[self._space.str_w(varname)].w_dom
+                domain.w_remove_values(self._space.newlist([val
+                                                            for val in domain._values.content.keys()
+                                                            if val not in keep.content]))
+
+        except ConsistencyFailure:
+            raise ConsistencyFailure('Inconsistency while applying %s' % \
+                                     repr(self))
+        except KeyError:
+            # There are no more value in result_cache
+            pass
+
+        return maybe_entailed
+        
+
+    def __repr__(self):
+        return '<%s>' % self.formula
+
+W_Expression.typedef = typedef.TypeDef("W_Expression",
+    W_AbstractConstraint.typedef)
+#    revise = interp2app(W_Expression.w_revise))
+    
+
+
+def make_expression(o_space, w_variables, w_formula):
+    """create a new constraint of type Expression or BinaryExpression
+    The chosen class depends on the number of variables in the constraint"""
+    assert len(w_variables.wrappeditems) > 0
+    return W_Expression(o_space, w_variables, w_formula)
+app_make_expression = gateway.interp2app(make_expression)
+

Added: pypy/dist/pypy/objspace/cclp/constraint/domain.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/cclp/constraint/domain.py	Wed Aug  9 17:38:15 2006
@@ -0,0 +1,124 @@
+from pypy.interpreter.error import OperationError
+
+from pypy.interpreter import typedef, gateway
+from pypy.interpreter.gateway import interp2app
+
+from pypy.objspace.std.listobject import W_ListObject, W_TupleObject
+
+from pypy.objspace.std.model import StdObjSpaceMultiMethod
+
+from pypy.objspace.cclp.types import W_AbstractDomain
+
+all_mms = {}
+
+class ConsistencyFailure(Exception):
+    """The repository is not in a consistent state"""
+    pass
+
+
+class W_FiniteDomain(W_AbstractDomain):
+    """
+    Variable Domain with a finite set of possible values
+    """
+
+    def __init__(self, space, w_values):
+        """values is a list of values in the domain
+        This class uses a dictionnary to make sure that there are
+        no duplicate values"""
+        W_AbstractDomain.__init__(self, space)
+        #XXX a pure dict used to work there (esp. in revise)
+        self._values = space.newdict([])
+        self.set_values(w_values)
+
+    def set_values(self, w_values):
+        """Objects in the value set can't be unwrapped unless we
+        specialize on specific types - this might need speccialization
+        of revise & friends
+        """
+        for w_v in w_values.wrappeditems:
+            self._space.setitem(self._values, w_v, self._space.w_True)
+        
+    def w_remove_value(self, w_value):
+        """Remove value of domain and check for consistency"""
+        self._space.delitem(self._values, w_value)
+        self._value_removed()
+
+    def w_remove_values(self, w_values):
+        """Remove values of domain and check for consistency"""
+        assert isinstance(w_values, W_ListObject)
+        self.remove_values(w_values.wrappeditems)
+
+    def remove_values(self, values):
+        assert isinstance(values, list)
+        try:
+            if len(values) > 0:
+                for w_val in values:
+                    del self._values.content[w_val]
+                self._value_removed()
+        except KeyError:
+            raise OperationError(self._space.w_RuntimeError,
+                                 self._space.wrap("attempt to remove unkown value from domain"))
+
+    def w_size(self):
+        return self._space.newint(self.size())
+
+    def size(self):
+        """computes the size of a finite domain"""
+        return self._space.len(self._values).intval
+    __len__ = size
+    
+    def w_get_values(self):
+        """return all the values in the domain
+           in an indexable sequence"""
+        return self._space.newlist(self.get_values())
+
+    def get_values(self):
+        return [x for x in self._values.content.keys()]
+        
+    def __repr__(self):
+        return '<FD %s>' % str(self.w_get_values())
+
+    def __eq__(self, w_other):
+        if not isinstance(w_other, W_FiniteDomain):
+            return self._space.newbool(False)
+        return self._space.newbool(self._space.eq_w(self._values, w_other._values))
+            
+    def __ne__(self, w_other):
+        return not self == w_other
+
+
+# function bolted into the space to serve as constructor
+def make_fd(space, w_values):
+    assert isinstance(w_values, W_ListObject)
+    return space.wrap(W_FiniteDomain(space, w_values))
+app_make_fd = gateway.interp2app(make_fd)
+
+
+def intersection(space, w_fd1, w_fd2):
+    assert isinstance(w_fd1, W_FiniteDomain)
+    assert isinstance(w_fd2, W_FiniteDomain)
+    return space.intersection(w_fd1, w_fd2)
+app_intersection = gateway.interp2app(intersection)
+
+
+def intersection__FiniteDomain_FiniteDomain(space, w_fd1, w_fd2):
+    w_v1 = w_fd1._values.content
+    res = [w_v for w_v in w_fd2._values.content
+             if w_v in w_v1]
+    return make_fd(space, space.newlist(res))
+
+intersection_mm = StdObjSpaceMultiMethod('intersection', 2)
+intersection_mm.register(intersection__FiniteDomain_FiniteDomain,
+                         W_FiniteDomain, W_FiniteDomain)
+all_mms['intersection'] = intersection_mm
+
+W_FiniteDomain.typedef = typedef.TypeDef(
+    "W_FiniteDomain",
+    W_AbstractDomain.typedef,
+    remove_value = interp2app(W_FiniteDomain.w_remove_value),
+    remove_values = interp2app(W_FiniteDomain.w_remove_values),
+    get_values = interp2app(W_FiniteDomain.w_get_values),
+    __eq__ = interp2app(W_FiniteDomain.__eq__),
+    __ne__ = interp2app(W_FiniteDomain.__ne__),
+    size = interp2app(W_FiniteDomain.w_size))
+

Modified: pypy/dist/pypy/objspace/cclp/misc.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/misc.py	(original)
+++ pypy/dist/pypy/objspace/cclp/misc.py	Wed Aug  9 17:38:15 2006
@@ -29,4 +29,3 @@
     NO_DEBUG_INFO[0] = not NO_DEBUG_INFO[0]
 app_switch_debug_info = gateway.interp2app(switch_debug_info)
 
-

Modified: pypy/dist/pypy/objspace/cclp/scheduler.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/scheduler.py	(original)
+++ pypy/dist/pypy/objspace/cclp/scheduler.py	Wed Aug  9 17:38:15 2006
@@ -76,7 +76,10 @@
         assert isinstance(thread, ClonableCoroutine)
         w(".. REMOVING", str(id(thread)))
         assert thread not in self._blocked
-        del self._traced[thread]
+        try:
+            del self._traced[thread]
+        except KeyError:
+            w(".. removing non-traced thread")
         l = thread._prev
         r = thread._next
         l._next = r

Modified: pypy/dist/pypy/objspace/cclp/space.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/space.py	(original)
+++ pypy/dist/pypy/objspace/cclp/space.py	Wed Aug  9 17:38:15 2006
@@ -5,7 +5,7 @@
 from pypy.objspace.std.intobject import W_IntObject
 
 from pypy.objspace.cclp.misc import ClonableCoroutine, w
-from pypy.objspace.cclp.thunk import CSpaceThunk
+from pypy.objspace.cclp.thunk import CSpaceThunk, PropagatorThunk
 from pypy.objspace.cclp.global_state import scheduler
 from pypy.objspace.cclp.variable import newvar
 
@@ -42,6 +42,13 @@
 app_choose = gateway.interp2app(choose)
 
 
+from pypy.objspace.cclp.constraint import constraint
+
+def tell(space, w_constraint):
+    assert isinstance(w_constraint, constraint.W_AbstractConstraint)
+    ClonableCoroutine.w_getcurrent(space)._cspace.tell(w_constraint)
+app_tell = gateway.interp2app(tell)
+
 
 class W_CSpace(baseobjspace.Wrappable):
 
@@ -54,8 +61,8 @@
         # choice mgmt
         self._choice = newvar(space)
         self._committed = newvar(space)
-        # constraint store ...
-        
+        # merging
+        self._merged = newvar(space)
 
     def w_ask(self):
         scheduler[0].wait_stable(self)
@@ -82,24 +89,23 @@
 
 
     def tell(self, w_constraint):
-        pass
-
-W_CSpace.typedef = typedef.TypeDef("W_CSpace",
-    ask = gateway.interp2app(W_CSpace.w_ask),
-    commit = gateway.interp2app(W_CSpace.w_commit))
-
+        space = self.space
+        w_coro = ClonableCoroutine(space)
+        thunk = PropagatorThunk(space, w_constraint, w_coro, self._merged)
+        w_coro.bind(thunk)
+        if not we_are_translated():
+            w("PROPAGATOR, thread", str(id(w_coro)))
+        w_coro._cspace = self
+        scheduler[0].add_new_thread(w_coro)
+        scheduler[0].schedule()
 
+    def w_merge(self):
+        self.space.bind(self._merged, self.space.w_True)
 
 
 
-##     def clone(self):
-##         if self.is_top_level():
-##             raise OperationError(self.space.w_RuntimeError,
-##                                  self.space.wrap("Clone"+forbidden_boilerplate))
-##         new = CSpace(self.distributor.clone(), parent=self)
-##         new.distributor.cspace = new
-##         for thread in self.threads:
-##             tclone = thread.clone()
-##             tclone.cspace = new
-##             new.threads[tclone] = True
 
+W_CSpace.typedef = typedef.TypeDef("W_CSpace",
+    ask = gateway.interp2app(W_CSpace.w_ask),
+    commit = gateway.interp2app(W_CSpace.w_commit),
+    merge = gateway.interp2app(W_CSpace.w_merge))

Modified: pypy/dist/pypy/objspace/cclp/thunk.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/thunk.py	(original)
+++ pypy/dist/pypy/objspace/cclp/thunk.py	Wed Aug  9 17:38:15 2006
@@ -1,10 +1,23 @@
 from pypy.module._stackless.coroutine import _AppThunk
-from pypy.objspace.cclp.misc import w 
+from pypy.objspace.cclp.misc import w
 from pypy.objspace.cclp.global_state import scheduler
 from pypy.objspace.cclp.types import W_Var, W_Future, W_FailedValue
 
+
+def logic_args(args):
+    "returns logic vars found in unpacked normalized args"
+    assert isinstance(args, tuple)
+    pos = args[0]
+    kwa = args[1]
+    pos_l = [arg for arg in pos
+             if isinstance(arg, W_Var)]
+    kwa_l = [arg for arg in kwa.keys()
+             if isinstance(arg, W_Var)]
+    return pos_l + kwa_l
+
 #-- Thunk -----------------------------------------
 
+
 class ProcedureThunk(_AppThunk):
     def __init__(self, space, w_callable, args, coro):
         _AppThunk.__init__(self, space, coro.costate, w_callable, args)
@@ -82,16 +95,30 @@
             scheduler[0].schedule()
 
 
+from pypy.interpreter.argument import Arguments
+from pypy.module._stackless.interp_coroutine import AbstractThunk
 
+class PropagatorThunk(AbstractThunk):
+    def __init__(self, space, w_constraint, coro, Merged):
+        self.space = space
+        self.coro = coro
+        self.const = w_constraint
+        self.Merged = Merged
 
-def logic_args(args):
-    "returns logic vars found in unpacked normalized args"
-    assert isinstance(args, tuple)
-    pos = args[0]
-    kwa = args[1]
-    pos_l = [arg for arg in pos
-             if isinstance(arg, W_Var)]
-    kwa_l = [arg for arg in kwa.keys()
-             if isinstance(arg, W_Var)]
-    return pos_l + kwa_l
+    def call(self):
+        try:
+            while 1:
+                entailed = self.const.revise()
+                if entailed:
+                    break
+                Obs = W_Var(self.space)
+                self.space.entail(self.Merged, Obs)
+                for Sync in [var.w_dom.give_synchronizer()
+                             for var in self.const._variables]:
+                    self.space.entail(Sync, Obs)
+                self.space.wait(Obs)
+        finally:
+            self.coro._dead = True
+            scheduler[0].remove_thread(self.coro)
+            scheduler[0].schedule()
 

Modified: pypy/dist/pypy/objspace/cclp/types.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/types.py	(original)
+++ pypy/dist/pypy/objspace/cclp/types.py	Wed Aug  9 17:38:15 2006
@@ -1,7 +1,6 @@
 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
 
@@ -32,15 +31,19 @@
 
 
 class W_CVar(W_Var):
-    def __init__(w_self, space, w_dom): #, w_name):
-        assert isinstance(w_dom, W_FiniteDomain)
+    def __init__(w_self, space, w_dom, w_name):
+        assert isinstance(w_dom, W_AbstractDomain)
         W_Var.__init__(w_self, space)
         w_self.w_dom = w_dom
-        #w_self.name = space.str_w(w_name)
+        w_self.name = space.str_w(w_name)
+        w_self.w_nam = w_name
 
     def name_w(w_self):
         return w_self.name
 
+    def w_name(w_self):
+        return w_self.w_nam
+
 def domain_of(space, w_v):
     assert isinstance(w_v, W_CVar)
     return w_v.w_dom
@@ -57,12 +60,44 @@
 
 #-- Constraint ---------------------------------------------
 
-## class W_Constraint(baseobjspace.Wrappable):
-##     def __init__(self, object_space):
-##         self._space = object_space
+class W_Constraint(baseobjspace.Wrappable):
+    def __init__(self, object_space):
+        self._space = object_space
+
+W_Constraint.typedef = typedef.TypeDef(
+    "W_Constraint")
+
+class W_AbstractDomain(baseobjspace.Wrappable):
+    """Implements the functionnality related to the changed flag.
+    Can be used as a starting point for concrete domains"""
+
+    def __init__(self, space):
+        self._space = space
+        self.__changed = W_Var(self._space)
+
+    def clear_change(self):
+        #XXX called after revise ?
+        assert self._space.is_true(self._space.is_bound(self.__changed))
+        self.__changed = W_Var(self._space)
+
+    def give_synchronizer(self):
+        return self.__changed
+
+    def _value_removed(self):
+        """The implementation of remove_value should call this method"""
+        self._space.bind(self.__changed, self._space.newbool(True))
+        self.clear_change()
+        
+        if self.size() == 0: #        self._space.eq_w(self.w_size(), self._space.newint(0)):
+            raise  OperationError(self._space.w_RuntimeError,
+                             self._space.wrap('ConsistencyFailure'))
+
+    def w__del__(self):
+        self._space.bind(self.__changed, self._space.newbool(False))
+
+W_AbstractDomain.typedef = typedef.TypeDef("W_AbstractDomain")
+##     has_changed = interp2app(W_AbstractDomain.w_has_changed))
 
-## W_Constraint.typedef = typedef.TypeDef(
-##     "W_Constraint")
 
 
 #-- Misc ---------------------------------------------------

Modified: pypy/dist/pypy/objspace/cclp/variable.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/variable.py	(original)
+++ pypy/dist/pypy/objspace/cclp/variable.py	Wed Aug  9 17:38:15 2006
@@ -9,7 +9,7 @@
 from pypy.objspace.cclp.global_state import scheduler
 from pypy.objspace.cclp.types import deref, W_Var, W_CVar, W_Future, W_FailedValue
 
-from pypy.objspace.constraint.domain import W_FiniteDomain
+from pypy.objspace.cclp.constraint.domain import W_FiniteDomain
 
 W_Root = baseobjspace.W_Root
 all_mms = {}
@@ -20,11 +20,11 @@
     return w_v
 app_newvar = gateway.interp2app(newvar)
 
-def domain(space, w_values):#, w_name):
+def domain(space, w_values, w_name):
     assert isinstance(w_values, W_ListObject)
-    #assert isinstance(w_name, W_StringObject)
+    assert isinstance(w_name, W_StringObject)
     w_dom = W_FiniteDomain(space, w_values)
-    w_var = W_CVar(space, w_dom)#, w_name)
+    w_var = W_CVar(space, w_dom, w_name)
     w("CVAR", str(w_var))
     return w_var
 app_domain = gateway.interp2app(domain)
@@ -202,7 +202,7 @@
 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 [True for elt in w_cvar.w_dom._values.content
         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")
@@ -317,7 +317,7 @@
 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:
+        if not w_val in w_var.w_dom._values.content:
             raise_unification_failure(space, "assignment out of domain")
     w_var.w_bound_to = w_val
 

Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py	(original)
+++ pypy/dist/pypy/objspace/logic.py	Wed Aug  9 17:38:15 2006
@@ -23,7 +23,7 @@
 
 #-- COMP. SPACE --------------------------------------------
 
-from pypy.objspace.cclp.space import app_newspace, app_choose, W_CSpace #app_tell
+from pypy.objspace.cclp.space import app_newspace, app_choose, W_CSpace, app_tell
 
 #-- VARIABLE ------------------------------------------------
 
@@ -37,8 +37,8 @@
 
 #-- CONSTRAINTS ----------------------------------------------
 
-## #------ domains ------------------
-from pypy.objspace.constraint import domain 
+## #------ domains ------------------ 
+from pypy.objspace.cclp.constraint import domain 
 all_mms.update(domain.all_mms)
 
 W_FiniteDomain = domain.W_FiniteDomain
@@ -50,8 +50,8 @@
 ## W_ComputationSpace = computationspace.W_ComputationSpace
 
 ## # ---- constraints ----------------
-## from pypy.objspace.constraint import constraint
-## all_mms.update(constraint.all_mms)
+from pypy.objspace.cclp.constraint import constraint
+all_mms.update(constraint.all_mms)
 
 ## #----- distributors ---------------
 ## from pypy.objspace.constraint import distributor
@@ -246,8 +246,8 @@
     space.setitem(space.builtin.w_dict, space.wrap('intersection'),
                  space.wrap(domain.app_intersection))
 ##     #-- constraints ----
-##     space.setitem(space.builtin.w_dict, space.wrap('make_expression'),
-##                  space.wrap(constraint.app_make_expression))
+    space.setitem(space.builtin.w_dict, space.wrap('make_expression'),
+                  space.wrap(constraint.app_make_expression))
 ##     space.setitem(space.builtin.w_dict, space.wrap('AllDistinct'),
 ##                  space.wrap(constraint.app_make_alldistinct))
 ##     #-- distributor --
@@ -281,8 +281,8 @@
                   space.wrap(app_newspace))
     space.setitem(space.builtin.w_dict, space.wrap('choose'),
                   space.wrap(app_choose))
-##     space.setitem(space.builtin.w_dict, space.wrap('tell'),
-##                   space.wrap(app_tell))
+    space.setitem(space.builtin.w_dict, space.wrap('tell'),
+                  space.wrap(app_tell))
 
     #-- misc -----
     space.setitem(space.builtin.w_dict, space.wrap('interp_id'),

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	Wed Aug  9 17:38:15 2006
@@ -665,7 +665,7 @@
 
     def test_cvar(self):
 
-        d = domain([1, 2, 4])
+        d = domain([1, 2, 4], '')
 
         raises(UnificationError, bind, d, 42)
         bind(d, 2)
@@ -675,31 +675,31 @@
             pass
 
         f = Foo()
-        d = domain([Foo(), 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])
+        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])
+        d1 = domain([1, 2, 3], '')
+        d4 = domain([3, 4], '')
         unify(d1, d4)
         assert d1 == d4 == 3
 
-        d1 = domain([1, 2])
+        d1 = domain([1, 2], '')
         x = newvar()
         unify(d1, x)
         assert alias_of(x, d1)
         raises(UnificationError, unify, x, 42)
 
-        d1 = domain([1, 2])
+        d1 = domain([1, 2], '')
         x = newvar()
         unify(d1, x)
         assert alias_of(x, d1)
@@ -778,26 +778,22 @@
 
     def test_tell(self):
 
-        skip("not finished ...")
-
         def problem():
             X, Y = domain([1, 2], 'X'), domain([1, 2, 3], 'Y')
             tell(make_expression([X, Y], 'X + Y > 4'))
 
-
         def solve(spc, X):
             while 1:
                 status = spc.ask()
                 if status == 1:
                     unify(X, status)
                     break
+            spc.merge()
                 
-        switch_debug_info()
         s = newspace(problem)
         Finished = newvar()
         stacklet(solve, s, Finished)
-
         wait(Finished)
 
-        assert domain_of(X) == FiniteDomain([2])
-        assert domain_of(Y) == FiniteDomain([3])
+        schedule()
+        assert len(sched_all()['threads']) == 1



More information about the Pypy-commit mailing list