introduce new locations for rule bodies
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()