M prolog/interpreter/function.py +1 -1
@@ 21,7 21,7 @@ class Rule(object):
from prolog.interpreter import helper
head = head.dereference(None)
assert isinstance(head, Callable)
- memo = EnumerationMemo()
+ memo = EnumerationMemo(head.name())
self.head = h = head.enumerate_vars(memo)
memo.in_head = False
if h.argument_count() > 0:
M prolog/interpreter/memo.py +2 -1
@@ 2,7 2,8 @@ from prolog.interpreter.term import Numb
class EnumerationMemo(object):
"""A memo object to enumerate the variables in a term"""
- def __init__(self):
+ def __init__(self, rulerepr=None):
+ self.rulerepr = rulerepr
self.mapping = {}
self.numvar_in_head = {}
self.numvar_in_body = {}
M prolog/interpreter/term.py +20 -5
@@ 445,7 445,25 @@ class Callable(NonVar):
return self._copy_term(_term_copy_standardize_apart, heap, env), False
def enumerate_vars(self, memo):
- return self._copy_term(_term_enumerate_vars, None, memo)
+ from prolog.interpreter.signature import Location
+ args = [None] * self.argument_count()
+ newinstance = False
+ i = 0
+ while i < self.argument_count():
+ arg = self.argument_at(i)
+ cloned = arg.enumerate_vars(memo)
+ newinstance = newinstance | (cloned is not arg)
+ args[i] = cloned
+ i += 1
+ if not newinstance:
+ return self
+ location = self.location()
+ if not memo.in_head:
+ repr = None
+ if memo.rulerepr:
+ repr = memo.rulerepr + str(id(self))
+ location = Location(location.signature, repr) # XXX
+ return Callable.build_location(args, location)
@specialize.arg(1)
@jit.unroll_safe
@@ 461,7 479,7 @@ class Callable(NonVar):
i += 1
if newinstance:
# XXX construct the right class directly
- return Callable.build(self.name(), args, self.signature(), heap=heap)
+ return Callable.build_location(args, self.location(), heap=heap)
else:
return self
@@ 762,9 780,6 @@ def _term_copy(obj, i, heap, memo):
def _term_copy_standardize_apart(obj, i, heap, env):
return obj.copy_standardize_apart(heap, env)[0]
-def _term_enumerate_vars(obj, i, _, memo):
- return obj.enumerate_vars(memo)
-
def _term_unify_and_standardize_apart(obj, i, heap, other, memo):
obj.unify_and_standardize_apart(other.argument_at(i), heap, memo)
M prolog/interpreter/test/test_unification.py +12 -0
@@ 139,6 139,18 @@ def test_enumerate_vars_head_body():
assert b3 is b4
assert b3.num == 1
+def test_enumerate_vars_new_locations():
+ from prolog.interpreter.memo import EnumerationMemo
+ memo = EnumerationMemo()
+ memo.in_head = False
+ E = BindingVar()
+ f1 = Callable.build("f", [E])
+ f2 = Callable.build("f", [E])
+ body = Callable.build(",", [f1, f2])
+ bodys = body.enumerate_vars(memo)
+ fs1, fs2 = bodys.arguments()
+ assert fs1.signature() is fs2.signature()
+ assert fs1.location() is not fs2.location()
def test_unify_and_standardize_apart():
heap = Heap()