# HG changeset patch # User Carl Friedrich Bolz-Tereick # Date 1588514963 -7200 # Sun May 03 16:09:23 2020 +0200 # Branch call-site-specialization # Node ID 91b83b614960feaad43e2b2f81946ea963714727 # Parent 902bfbba9ab3a198e4c8b8066ad8213f2ca464ba introduce new locations for rule bodies diff --git a/prolog/interpreter/function.py b/prolog/interpreter/function.py --- a/prolog/interpreter/function.py +++ b/prolog/interpreter/function.py @@ -21,7 +21,7 @@ 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: diff --git a/prolog/interpreter/memo.py b/prolog/interpreter/memo.py --- a/prolog/interpreter/memo.py +++ b/prolog/interpreter/memo.py @@ -2,7 +2,8 @@ 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 = {} diff --git a/prolog/interpreter/term.py b/prolog/interpreter/term.py --- a/prolog/interpreter/term.py +++ b/prolog/interpreter/term.py @@ -445,7 +445,25 @@ 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 @@ 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_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) diff --git a/prolog/interpreter/test/test_unification.py b/prolog/interpreter/test/test_unification.py --- a/prolog/interpreter/test/test_unification.py +++ b/prolog/interpreter/test/test_unification.py @@ -139,6 +139,18 @@ 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()