Commits

Carl Friedrich Bolz committed a01b048

don't stick the heap into the engine, but explicitly pass it around.

  • Participants
  • Parent commits 08bfe14

Comments (0)

Files changed (14)

File prolog/builtin/allsolution.py

         self.found.append(clone)
         raise error.UnificationFailed()
 
-def impl_findall(engine, template, goal, bag):
-    oldstate = engine.heap.branch()
+@expose_builtin("findall", unwrap_spec=['raw', 'callable', 'raw'])
+def impl_findall(engine, heap, template, goal, bag):
+    oldstate = heap.branch()
     collector = FindallContinuation(template)
     try:
         engine.call(goal, collector)
     except error.UnificationFailed:
-        engine.heap.revert_and_discard(oldstate)
+        heap.revert_and_discard(oldstate)
     else:
         assert 0, "unreachable"
     result = term.Atom.newatom("[]")
     for i in range(len(collector.found) - 1, -1, -1):
         copy = collector.found[i]
         d = {}
-        copy = copy.copy(engine.heap, d)
+        copy = copy.copy(heap, d)
         result = term.Term(".", [copy, result])
-    bag.unify(result, engine.heap)
-expose_builtin(impl_findall, "findall", unwrap_spec=['raw', 'callable', 'raw'])
+    bag.unify(result, heap)

File prolog/builtin/arithmeticbuiltin.py

 import py
-from prolog.interpreter import engine, helper, term, error
+from prolog.interpreter import helper, term, error
 from prolog.builtin.register import expose_builtin
 
 # ___________________________________________________________________
 # arithmetic
 
 
-def impl_between(engine, lower, upper, varorint, continuation):
+@expose_builtin("between", unwrap_spec=["int", "int", "obj"],
+                handles_continuation=True)
+def impl_between(engine, heap, lower, upper, varorint, continuation):
     if isinstance(varorint, term.Var):
         for i in range(lower, upper):
-            oldstate = engine.heap.branch()
+            oldstate = heap.branch()
             try:
-                varorint.unify(term.Number(i), engine.heap)
+                varorint.unify(term.Number(i), heap)
                 result = continuation.call(engine, choice_point=True)
-                engine.heap.discard(oldstate)
+                heap.discard(oldstate)
                 return result
             except error.UnificationFailed:
-                engine.heap.revert(oldstate)
-        varorint.unify(term.Number(upper), engine.heap)
+                heap.revert(oldstate)
+        varorint.unify(term.Number(upper), heap)
         return continuation.call(engine, choice_point=False)
     else:
         integer = helper.unwrap_int(varorint)
         if not (lower <= integer <= upper):
             raise error.UnificationFailed
     return continuation.call(engine, choice_point=False)
-expose_builtin(impl_between, "between", unwrap_spec=["int", "int", "obj"],
-               handles_continuation=True)
 
-def impl_is(engine, var, num):
-    var.unify(num, engine.heap)
-expose_builtin(impl_is, "is", unwrap_spec=["raw", "arithmetic"])
+@expose_builtin("is", unwrap_spec=["raw", "arithmetic"])
+def impl_is(engine, heap, var, num):
+    var.unify(num, heap)
 
 for ext, prolog, python in [("eq", "=:=", "=="),
                             ("ne", "=\\=", "!="),
                             ("gt", ">", ">"),
                             ("ge", ">=", ">=")]:
     exec py.code.Source("""
-def impl_arith_%s(engine, num1, num2):
+@expose_builtin(prolog, unwrap_spec=["arithmetic", "arithmetic"])
+def impl_arith_%s(engine, heap, num1, num2):
     eq = False
     if isinstance(num1, term.Number):
         if isinstance(num2, term.Number):
     eq = n1 %s n2
     if not eq:
         raise error.UnificationFailed()""" % (ext, python, python)).compile()
-    expose_builtin(globals()["impl_arith_%s" % (ext, )], prolog,
-                   unwrap_spec=["arithmetic", "arithmetic"])
  

File prolog/builtin/atomconstruction.py

 # ___________________________________________________________________
 # analysing and construction atoms
 
-def impl_atom_concat(engine, a1, a2, result, continuation):
+@expose_builtin("atom_concat", unwrap_spec=["obj", "obj", "obj"],
+                handles_continuation=True)
+def impl_atom_concat(engine, heap, a1, a2, result, continuation):
     if isinstance(a1, term.Var):
         if isinstance(a2, term.Var):
             # nondeterministic splitting of result
             r = helper.convert_to_str(result)
             for i in range(len(r) + 1):
-                oldstate = engine.heap.branch()
+                oldstate = heap.branch()
                 try:
-                    a1.unify(term.Atom(r[:i]), engine.heap)
-                    a2.unify(term.Atom(r[i:]), engine.heap)
+                    a1.unify(term.Atom(r[:i]), heap)
+                    a2.unify(term.Atom(r[i:]), heap)
                     result = continuation.call(engine, choice_point=True)
-                    engine.heap.discard(oldstate)
+                    heap.discard(oldstate)
                     return result
                 except error.UnificationFailed:
-                    engine.heap.revert(oldstate)
+                    heap.revert(oldstate)
             raise error.UnificationFailed()
         else:
             s2 = helper.convert_to_str(a2)
             if r.endswith(s2):
                 stop = len(r) - len(s2)
                 assert stop > 0
-                a1.unify(term.Atom(r[:stop]), engine.heap)
+                a1.unify(term.Atom(r[:stop]), heap)
             else:
                 raise error.UnificationFailed()
     else:
         if isinstance(a2, term.Var):
             r = helper.convert_to_str(result)
             if r.startswith(s1):
-                a2.unify(term.Atom(r[len(s1):]), engine.heap)
+                a2.unify(term.Atom(r[len(s1):]), heap)
             else:
                 raise error.UnificationFailed()
         else:
             s2 = helper.convert_to_str(a2)
-            result.unify(term.Atom(s1 + s2), engine.heap)
+            result.unify(term.Atom(s1 + s2), heap)
     return continuation.call(engine, choice_point=False)
-expose_builtin(impl_atom_concat, "atom_concat",
-               unwrap_spec=["obj", "obj", "obj"],
-               handles_continuation=True)
 
-def impl_atom_length(engine, s, length):
+@expose_builtin("atom_length", unwrap_spec = ["atom", "obj"])
+def impl_atom_length(engine, heap, s, length):
     if not (isinstance(length, term.Var) or isinstance(length, term.Number)):
         error.throw_type_error("integer", length)
-    term.Number(len(s)).unify(length, engine.heap)
-expose_builtin(impl_atom_length, "atom_length", unwrap_spec = ["atom", "obj"])
+    term.Number(len(s)).unify(length, heap)
 
-def impl_sub_atom(engine, s, before, length, after, sub, continuation):
+@expose_builtin("sub_atom", unwrap_spec=["atom", "obj", "obj", "obj", "obj"],
+                handles_continuation=True)
+def impl_sub_atom(engine, heap, s, before, length, after, sub, continuation):
     # XXX can possibly be optimized
     if isinstance(length, term.Var):
         startlength = 0
             stopbefore = len(s) + 1
         else:
             stopbefore = startbefore + 1
-    oldstate = engine.heap.branch()
+    oldstate = heap.branch()
     if not isinstance(sub, term.Var):
         s1 = helper.unwrap_atom(sub)
         if len(s1) >= stoplength or len(s1) < startlength:
                 if b < 0:
                     break
                 start = b + 1
-                before.unify(term.Number(b), engine.heap)
-                after.unify(term.Number(len(s) - len(s1) - b), engine.heap)
-                length.unify(term.Number(len(s1)), engine.heap)
+                before.unify(term.Number(b), heap)
+                after.unify(term.Number(len(s) - len(s1) - b), heap)
+                length.unify(term.Number(len(s1)), heap)
                 result = continuation.call(engine, choice_point=True)
-                engine.heap.discard(oldstate)
+                heap.discard(oldstate)
                 return result
             except error.UnificationFailed:
-                engine.heap.revert(oldstate)
+                heap.revert(oldstate)
         raise error.UnificationFailed()
     if isinstance(after, term.Var):
         for b in range(startbefore, stopbefore):
                 if l + b > len(s):
                     continue
                 try:
-                    before.unify(term.Number(b), engine.heap)
-                    after.unify(term.Number(len(s) - l - b), engine.heap)
-                    length.unify(term.Number(l), engine.heap)
-                    sub.unify(term.Atom(s[b:b + l]), engine.heap)
+                    before.unify(term.Number(b), heap)
+                    after.unify(term.Number(len(s) - l - b), heap)
+                    length.unify(term.Number(l), heap)
+                    sub.unify(term.Atom(s[b:b + l]), heap)
                     result = continuation.call(engine, choice_point=True)
-                    engine.heap.discard(oldstate)
+                    heap.discard(oldstate)
                     return result
                 except error.UnificationFailed:
-                    engine.heap.revert(oldstate)
+                    heap.revert(oldstate)
     else:
         a = helper.unwrap_int(after)
         for l in range(startlength, stoplength):
             if l + b > len(s):
                 continue
             try:
-                before.unify(term.Number(b), engine.heap)
-                after.unify(term.Number(a), engine.heap)
-                length.unify(term.Number(l), engine.heap)
-                sub.unify(term.Atom(s[b:b + l]), engine.heap)
+                before.unify(term.Number(b), heap)
+                after.unify(term.Number(a), heap)
+                length.unify(term.Number(l), heap)
+                sub.unify(term.Atom(s[b:b + l]), heap)
                 result = continuation.call(engine, choice_point=True)
-                engine.heap.discard(oldstate)
+                heap.discard(oldstate)
                 return result
             except error.UnificationFailed:
-                engine.heap.revert(oldstate)
+                heap.revert(oldstate)
     raise error.UnificationFailed()
-expose_builtin(impl_sub_atom, "sub_atom",
-               unwrap_spec=["atom", "obj", "obj", "obj", "obj"],
-               handles_continuation=True)
 

File prolog/builtin/control.py

 # ___________________________________________________________________
 # control predicates
 
-def impl_fail(engine):
+@expose_builtin("fail", unwrap_spec=[])
+def impl_fail(engine, heap):
     raise error.UnificationFailed()
-expose_builtin(impl_fail, "fail", unwrap_spec=[])
 
-def impl_true(engine):
+@expose_builtin("true", unwrap_spec=[])
+def impl_true(engine, heap):
     return
-expose_builtin(impl_true, "true", unwrap_spec=[])
 
-def impl_repeat(engine, continuation):
+@expose_builtin("repeat", unwrap_spec=[], handles_continuation=True)
+def impl_repeat(engine, heap, continuation):
     while 1:
         try:
             return continuation.call(engine, choice_point=True)
         except error.UnificationFailed:
             pass
-expose_builtin(impl_repeat, "repeat", unwrap_spec=[], handles_continuation=True)
 
-def impl_cut(engine, continuation):
+@expose_builtin("!", unwrap_spec=[], handles_continuation=True)
+def impl_cut(engine, heap, continuation):
     raise error.CutException(continuation)
-expose_builtin(impl_cut, "!", unwrap_spec=[],
-               handles_continuation=True)
 
 class AndContinuation(engine.Continuation):
     def __init__(self, next_call, continuation):
         next_call = helper.ensure_callable(next_call)
         return engine.call(next_call, self.continuation, choice_point=False)
 
-def impl_and(engine, call1, call2, continuation):
+@expose_builtin(",", unwrap_spec=["callable", "raw"], handles_continuation=True)
+def impl_and(engine, heap, call1, call2, continuation):
     if not isinstance(call2, term.Var) and not isinstance(call2, term.Callable):
         error.throw_type_error('callable', call2)
     and_continuation = AndContinuation(call2, continuation)
     return engine.call(call1, and_continuation, choice_point=False)
-expose_builtin(impl_and, ",", unwrap_spec=["callable", "raw"],
-               handles_continuation=True)
 
-def impl_or(engine, call1, call2, continuation):
-    oldstate = engine.heap.branch()
+@expose_builtin(";", unwrap_spec=["callable", "callable"],
+                handles_continuation=True)
+def impl_or(engine, heap, call1, call2, continuation):
+    oldstate = heap.branch()
     try:
         return engine.call(call1, continuation, choice_point=True)
     except error.UnificationFailed:
-        engine.heap.revert_and_discard(oldstate)
+        heap.revert_and_discard(oldstate)
     return engine.call(call2, continuation, choice_point=False)
 
-expose_builtin(impl_or, ";", unwrap_spec=["callable", "callable"],
-               handles_continuation=True)
-
-def impl_not(engine, call):
+@expose_builtin(["not", "\\+"], unwrap_spec=["callable"])
+def impl_not(engine, heap, call):
     try:
         try:
             engine.call(call)
     except error.UnificationFailed:
         return None
     raise error.UnificationFailed()
-expose_builtin(impl_not, ["not", "\\+"], unwrap_spec=["callable"])
 
-def impl_if(engine, if_clause, then_clause, continuation):
-    oldstate = engine.heap.branch()
+@expose_builtin("->", unwrap_spec=["callable", "raw"],
+                handles_continuation=True)
+def impl_if(engine, heap, if_clause, then_clause, continuation):
+    oldstate = heap.branch()
     try:
         engine.call(if_clause)
     except error.UnificationFailed:
-        engine.heap.revert_and_discard(oldstate)
+        heap.revert_and_discard(oldstate)
         raise
     return engine.call(helper.ensure_callable(then_clause), continuation,
                        choice_point=False)
-expose_builtin(impl_if, "->", unwrap_spec=["callable", "raw"],
-               handles_continuation=True)
 

File prolog/builtin/database.py

 # ___________________________________________________________________
 # database
 
-def impl_abolish(engine, predicate):
+@expose_builtin("abolish", unwrap_spec=["obj"])
+def impl_abolish(engine, heap, predicate):
     from prolog.builtin import builtins
     name, arity = helper.unwrap_predicate_indicator(predicate)
     if arity < 0:
                                      predicate)
     if signature in engine.signature2function:
         del engine.signature2function[signature]
-expose_builtin(impl_abolish, "abolish", unwrap_spec=["obj"])
 
-def impl_assert(engine, rule):
-    engine.add_rule(rule.getvalue(engine.heap))
-expose_builtin(impl_assert, ["assert", "assertz"], unwrap_spec=["callable"])
+@expose_builtin(["assert", "assertz"], unwrap_spec=["callable"])
+def impl_assert(engine, heap, rule):
+    engine.add_rule(rule.getvalue(heap))
 
-def impl_asserta(engine, rule):
-    engine.add_rule(rule.getvalue(engine.heap), end=False)
-expose_builtin(impl_asserta, "asserta", unwrap_spec=["callable"])
+@expose_builtin("asserta", unwrap_spec=["callable"])
+def impl_asserta(engine, heap, rule):
+    engine.add_rule(rule.getvalue(heap), end=False)
 
 
-def impl_retract(engine, pattern):
+@expose_builtin("retract", unwrap_spec=["callable"])
+def impl_retract(engine, heap, pattern):
     from prolog.builtin import builtins
     if isinstance(pattern, term.Term) and pattern.name == ":-":
         head = helper.ensure_callable(pattern.args[0])
         raise error.UnificationFailed
     #import pdb; pdb.set_trace()
     rulechain = function.rulechain
-    oldstate = engine.heap.branch()
+    oldstate = heap.branch()
     while rulechain:
         rule = rulechain.rule
         # standardizing apart
         try:
-            deleted_body = rule.clone_and_unify_head(engine.heap, head)
+            deleted_body = rule.clone_and_unify_head(heap, head)
             if body is not None:
-                body.unify(deleted_body, engine.heap)
+                body.unify(deleted_body, heap)
         except error.UnificationFailed:
-            engine.heap.revert(oldstate)
+            heap.revert(oldstate)
         else:
             if function.rulechain is rulechain:
                 if rulechain.next is None:
         rulechain = rulechain.next
     else:
         raise error.UnificationFailed()
-    engine.heap.discard(oldstate)
+    heap.discard(oldstate)
 
-expose_builtin(impl_retract, "retract", unwrap_spec=["callable"])
 
 

File prolog/builtin/exception.py

 # ___________________________________________________________________
 # exception handling
 
-def impl_catch(engine, goal, catcher, recover, continuation):
+@expose_builtin("catch", unwrap_spec=["callable", "obj", "callable"],
+                handles_continuation=True)
+def impl_catch(engine, heap, goal, catcher, recover, continuation):
     catching_continuation = enginemod.LimitedScopeContinuation(continuation)
-    old_state = engine.heap.branch()
+    old_state = heap.branch()
     try:
         result = engine.call(goal, catching_continuation)
-        engine.heap.discard(old_state)
+        heap.discard(old_state)
         return result
     except error.CatchableError, e:
         if not catching_continuation.scope_active:
             raise
-        exc_term = e.term.getvalue(engine.heap)
-        engine.heap.revert_and_discard(old_state)
+        exc_term = e.term.getvalue(heap)
+        heap.revert_and_discard(old_state)
         d = {}
-        exc_term = exc_term.copy(engine.heap, d)
+        exc_term = exc_term.copy(heap, d)
         try:
-            impl_ground(engine, exc_term)
+            impl_ground(engine, heap, exc_term)
         except error.UnificationFailed:
             raise error.UncatchableError(
                 "not implemented: catching of non-ground terms")
         try:
-            catcher.unify(exc_term, engine.heap)
+            catcher.unify(exc_term, heap)
         except error.UnificationFailed:
             if isinstance(e, error.UserError):
                 raise error.UserError(exc_term)
             if isinstance(e, error.CatchableError):
                 raise error.CatchableError(exc_term)
         return engine.call(recover, continuation, choice_point=False)
-expose_builtin(impl_catch, "catch", unwrap_spec=["callable", "obj", "callable"],
-               handles_continuation=True)
 
-def impl_throw(engine, exc):
+@expose_builtin("throw", unwrap_spec=["obj"])
+def impl_throw(engine, heap, exc):
     try:
-        impl_ground(engine, exc)
+        impl_ground(engine, heap, exc)
     except error.UnificationFailed:
         raise error.UncatchableError(
             "not implemented: raising of non-ground terms")
     raise error.UserError(exc)
-expose_builtin(impl_throw, "throw", unwrap_spec=["obj"])
 
 

File prolog/builtin/formatting.py

                     m[len(form) - 1, op] = (form, prec)
         self.op_mapping = m
 
-def impl_write_term(engine, term, options):
+@expose_builtin("write_term", unwrap_spec=["concrete", "list"])
+def impl_write_term(engine, heap, term, options):
     f = TermFormatter.from_option_list(engine, options)
     os.write(1, f.format(term)) # XXX use streams
-expose_builtin(impl_write_term, "write_term", unwrap_spec=["concrete", "list"])
 
+@expose_builtin("nl", unwrap_spec=[])
 def impl_nl(engine):
     os.write(1, "\n") # XXX use streams
-expose_builtin(impl_nl, "nl", unwrap_spec=[])
 
-def impl_write(engine, term):
-    impl_write_term(engine, term, [])
-expose_builtin(impl_write, "write", unwrap_spec=["raw"])
+@expose_builtin("write", unwrap_spec=["raw"])
+def impl_write(engine, heap, term):
+    impl_write_term(engine, heap, term, [])
 
 

File prolog/builtin/metacall.py

 # ___________________________________________________________________
 # meta-call predicates
 
-def impl_call(engine, call, continuation):
+@expose_builtin("call", unwrap_spec=["callable"],
+                handles_continuation=True)
+def impl_call(engine, heap, call, continuation):
     try:
         return engine.call(call, continuation)
     except error.CutException, e:
         return e.continuation.call(engine, choice_point=False)
-expose_builtin(impl_call, "call", unwrap_spec=["callable"],
-               handles_continuation=True)
 
-def impl_once(engine, clause, continuation):
+@expose_builtin("once", unwrap_spec=["callable"],
+                handles_continuation=True)
+def impl_once(engine, heap, clause, continuation):
     engine.call(clause)
     return continuation.call(engine, choice_point=False)
-expose_builtin(impl_once, "once", unwrap_spec=["callable"],
-               handles_continuation=True)
 

File prolog/builtin/parseraccess.py

 # ___________________________________________________________________
 # operators
 
-def impl_current_op(engine, precedence, typ, name, continuation):
-    oldstate = engine.heap.branch()
+@expose_builtin("current_op", unwrap_spec=["obj", "obj", "obj"],
+                handles_continuation=True)
+def impl_current_op(engine, heap, precedence, typ, name, continuation):
+    oldstate = heap.branch()
     for prec, allops in engine.getoperations():
         for form, ops in allops:
             for op in ops:
                 try:
-                    precedence.unify(term.Number(prec), engine.heap)
-                    typ.unify(term.Atom.newatom(form), engine.heap)
-                    name.unify(term.Atom(op), engine.heap)
+                    precedence.unify(term.Number(prec), heap)
+                    typ.unify(term.Atom.newatom(form), heap)
+                    name.unify(term.Atom(op), heap)
                     return continuation.call(engine, choice_point=True)
                 except error.UnificationFailed:
-                    engine.heap.revert(oldstate)
-    engine.heap.discard(oldstate)
+                    heap.revert(oldstate)
+    heap.discard(oldstate)
     raise error.UnificationFailed()
-expose_builtin(impl_current_op, "current_op", unwrap_spec=["obj", "obj", "obj"],
-               handles_continuation=True)
 
-def impl_op(engine, precedence, typ, name):
+@expose_builtin("op", unwrap_spec=["int", "atom", "atom"])
+def impl_op(engine, heap, precedence, typ, name):
     from prolog.interpreter import parsing
     if engine.operations is None:
         engine.operations = parsing.make_default_operations()
             else:
                 operations.append((precedence, [(typ, [name])]))
     engine.parser = parsing.make_parser_at_runtime(engine.operations)
-expose_builtin(impl_op, "op", unwrap_spec=["int", "atom", "atom"])
 
 

File prolog/builtin/register.py

     def _freeze_(self):
         return True
 
-def expose_builtin(func, name, unwrap_spec=None, handles_continuation=False,
+def expose_builtin(*args, **kwargs):
+    def really_expose(func):
+        return make_wrapper(func, *args, **kwargs)
+    return really_expose
+
+def make_wrapper(func, name, unwrap_spec=None, handles_continuation=False,
                    translatable=True):
     if isinstance(name, list):
         expose_as = name
         name = func.func_name
     funcname = "wrap_%s_%s" % (name, len(unwrap_spec))
     code = ["def %s(engine, query, continuation):" % (funcname, )]
+    code.append("    heap = engine.heap")
     if not translatable:
         code.append("    if we_are_translated():")
         code.append("        raise error.UncatchableError('%s does not work in translated version')" % (name, ))
-    subargs = ["engine"]
+    subargs = ["engine", "heap"]
     if len(unwrap_spec):
         code.append("    assert isinstance(query, term.Term)")
     else:
         varname = "var%s" % (i, )
         subargs.append(varname)
         if spec in ("obj", "callable", "int", "atom", "arithmetic"):
-            code.append("    %s = query.args[%s].dereference(engine.heap)" %
+            code.append("    %s = query.args[%s].dereference(heap)" %
                         (varname, i))
         elif spec in ("concrete", "list"):
-            code.append("    %s = query.args[%s].getvalue(engine.heap)" %
+            code.append("    %s = query.args[%s].getvalue(heap)" %
                         (varname, i))
         if spec in ("int", "atom", "arithmetic", "list"):
             code.append(
         b = Builtin(miniglobals[funcname], funcname, len(unwrap_spec),
                     signature)
         builtins[signature] = b
-        if signature in [",/2", "is/2"]:
-            builtins_list.insert(0, (signature, b))
-        else:
-            builtins_list.append((signature, b))
+        builtins_list.append((signature, b))
+    return func

File prolog/builtin/source.py

 # ___________________________________________________________________
 # loading prolog source files
 
-def impl_consult(engine, var):
+@expose_builtin("consult", unwrap_spec=["obj"])
+def impl_consult(engine, heap, var):
     import os
     if isinstance(var, term.Atom):
         try:
         finally:
             os.close(fd)
         engine.runstring(file_content)
-expose_builtin(impl_consult, "consult", unwrap_spec=["obj"])
 
 

File prolog/builtin/termconstruction.py

 # ___________________________________________________________________
 # analysing and construction terms
 
-def impl_functor(engine, t, functor, arity):
+@expose_builtin("functor", unwrap_spec=["obj", "obj", "obj"])
+def impl_functor(engine, heap, t, functor, arity):
     if helper.is_atomic(t):
-        functor.unify(t, engine.heap)
-        arity.unify(term.Number(0), engine.heap)
+        functor.unify(t, heap)
+        arity.unify(term.Number(0), heap)
     elif isinstance(t, term.Term):
-        functor.unify(term.Atom(t.name), engine.heap)
-        arity.unify(term.Number(len(t.args)), engine.heap)
+        functor.unify(term.Atom(t.name), heap)
+        arity.unify(term.Number(len(t.args)), heap)
     elif isinstance(t, term.Var):
         if isinstance(functor, term.Var):
             error.throw_instantiation_error()
         else:
             functor = helper.ensure_atomic(functor)
             if a == 0:
-                t.unify(helper.ensure_atomic(functor), engine.heap)
+                t.unify(helper.ensure_atomic(functor), heap)
             else:
                 name = helper.unwrap_atom(functor)
                 t.unify(
                     term.Term(name, [term.Var() for i in range(a)]),
-                    engine.heap)
-expose_builtin(impl_functor, "functor", unwrap_spec=["obj", "obj", "obj"])
+                    heap)
 
-def impl_arg(engine, first, second, third, continuation):
+@expose_builtin("arg", unwrap_spec=["obj", "obj", "obj"],
+                handles_continuation=True)
+def impl_arg(engine, heap, first, second, third, continuation):
     if isinstance(second, term.Var):
         error.throw_instantiation_error()
     if isinstance(second, term.Atom):
     if not isinstance(second, term.Term):
         error.throw_type_error("compound", second)
     if isinstance(first, term.Var):
-        oldstate = engine.heap.branch()
+        oldstate = heap.branch()
         for i in range(len(second.args)):
             arg = second.args[i]
             try:
-                third.unify(arg, engine.heap)
-                first.unify(term.Number(i + 1), engine.heap)
+                third.unify(arg, heap)
+                first.unify(term.Number(i + 1), heap)
                 result = continuation.call(engine, choice_point=True)
-                engine.heap.discard(oldstate)
+                heap.discard(oldstate)
                 return result
             except error.UnificationFailed:
-                engine.heap.revert(oldstate)
-        engine.heap.discard(oldstate)
+                heap.revert(oldstate)
+        heap.discard(oldstate)
         raise error.UnificationFailed()
     elif isinstance(first, term.Number):
         num = first.num
         if num > len(second.args):
             raise error.UnificationFailed()
         arg = second.args[num - 1]
-        third.unify(arg, engine.heap)
+        third.unify(arg, heap)
     else:
         error.throw_type_error("integer", first)
     return continuation.call(engine, choice_point=False)
-expose_builtin(impl_arg, "arg", unwrap_spec=["obj", "obj", "obj"],
-               handles_continuation=True)
 
-def impl_univ(engine, first, second):
+@expose_builtin("=..", unwrap_spec=["obj", "obj"])
+def impl_univ(engine, heap, first, second):
     if not isinstance(first, term.Var):
         if isinstance(first, term.Term):
             l = [term.Atom(first.name)] + first.args
             l = [first]
         u1 = helper.wrap_list(l)
         if not isinstance(second, term.Var):
-            u1.unify(second, engine.heap)
+            u1.unify(second, heap)
         else:
-            u1.unify(second, engine.heap)
+            u1.unify(second, heap)
     else:
         if isinstance(second, term.Var):
             error.throw_instantiation_error()
             head = l[0]
             if not isinstance(head, term.Atom):
                 error.throw_type_error("atom", head)
-            term.Term(head.name, l[1:]).unify(first, engine.heap)
-expose_builtin(impl_univ, "=..", unwrap_spec=["obj", "obj"])
+            term.Term(head.name, l[1:]).unify(first, heap)
 
-def impl_copy_term(engine, interm, outterm):
+@expose_builtin("copy_term", unwrap_spec=["obj", "obj"])
+def impl_copy_term(engine, heap, interm, outterm):
     d = {}
-    copy = interm.copy(engine.heap, d)
-    outterm.unify(copy, engine.heap)
-expose_builtin(impl_copy_term, "copy_term", unwrap_spec=["obj", "obj"])
+    copy = interm.copy(heap, d)
+    outterm.unify(copy, heap)
 
 

File prolog/builtin/type.py

 # ___________________________________________________________________
 # type verifications
 
-def impl_nonvar(engine, var):
+@expose_builtin("nonvar", unwrap_spec=["obj"])
+def impl_nonvar(engine, heap, var):
     if isinstance(var, term.Var):
         raise error.UnificationFailed()
-expose_builtin(impl_nonvar, "nonvar", unwrap_spec=["obj"])
 
-def impl_var(engine, var):
+@expose_builtin("var", unwrap_spec=["obj"])
+def impl_var(engine, heap, var):
     if not isinstance(var, term.Var):
         raise error.UnificationFailed()
-expose_builtin(impl_var, "var", unwrap_spec=["obj"])
 
-def impl_integer(engine, var):
+@expose_builtin("integer", unwrap_spec=["obj"])
+def impl_integer(engine, heap, var):
     if isinstance(var, term.Var) or not isinstance(var, term.Number):
         raise error.UnificationFailed()
-expose_builtin(impl_integer, "integer", unwrap_spec=["obj"])
 
-def impl_float(engine, var):
+@expose_builtin("float", unwrap_spec=["obj"])
+def impl_float(engine, heap, var):
     if isinstance(var, term.Var) or not isinstance(var, term.Float):
         raise error.UnificationFailed()
-expose_builtin(impl_float, "float", unwrap_spec=["obj"])
 
-def impl_number(engine, var):
+@expose_builtin("number", unwrap_spec=["obj"])
+def impl_number(engine, heap, var):
     if (isinstance(var, term.Var) or
         (not isinstance(var, term.Number) and not
          isinstance(var, term.Float))):
         raise error.UnificationFailed()
-expose_builtin(impl_number, "number", unwrap_spec=["obj"])
 
-def impl_atom(engine, var):
+@expose_builtin("atom", unwrap_spec=["obj"])
+def impl_atom(engine, heap, var):
     if isinstance(var, term.Var) or not isinstance(var, term.Atom):
         raise error.UnificationFailed()
-expose_builtin(impl_atom, "atom", unwrap_spec=["obj"])
 
-def impl_atomic(engine, var):
+@expose_builtin("atomic", unwrap_spec=["obj"])
+def impl_atomic(engine, heap, var):
     if helper.is_atomic(var):
         return
     raise error.UnificationFailed()
-expose_builtin(impl_atomic, "atomic", unwrap_spec=["obj"])
 
-def impl_compound(engine, var):
+@expose_builtin("compound", unwrap_spec=["obj"])
+def impl_compound(engine, heap, var):
     if isinstance(var, term.Var) or not isinstance(var, term.Term):
         raise error.UnificationFailed()
-expose_builtin(impl_compound, "compound", unwrap_spec=["obj"])
 
-def impl_callable(engine, var):
+@expose_builtin("callable", unwrap_spec=["obj"])
+def impl_callable(engine, heap, var):
     if not helper.is_callable(var, engine):
         raise error.UnificationFailed()
-expose_builtin(impl_callable, "callable", unwrap_spec=["obj"])
 
-def impl_ground(engine, var):
+@expose_builtin("ground", unwrap_spec=["concrete"])
+def impl_ground(engine, heap, var):
     if isinstance(var, term.Var):
         raise error.UnificationFailed()
     if isinstance(var, term.Term):
         for arg in var.args:
-            impl_ground(engine, arg)
-expose_builtin(impl_ground, "ground", unwrap_spec=["concrete"])
+            impl_ground(engine, heap, arg)
 
 

File prolog/builtin/unify.py

 # ___________________________________________________________________
 # comparison and unification of terms
 
-def impl_unify(engine, obj1, obj2):
-    obj1.unify(obj2, engine.heap)
-expose_builtin(impl_unify, "=", unwrap_spec=["raw", "raw"])
+@expose_builtin("=", unwrap_spec=["raw", "raw"])
+def impl_unify(engine, heap, obj1, obj2):
+    obj1.unify(obj2, heap)
 
-def impl_unify_with_occurs_check(engine, obj1, obj2):
-    obj1.unify(obj2, engine.heap, occurs_check=True)
-expose_builtin(impl_unify_with_occurs_check, "unify_with_occurs_check",
-               unwrap_spec=["raw", "raw"])
+@expose_builtin("unify_with_occurs_check",
+                unwrap_spec=["raw", "raw"])
+def impl_unify_with_occurs_check(engine, heap, obj1, obj2):
+    obj1.unify(obj2, heap, occurs_check=True)
 
-def impl_does_not_unify(engine, obj1, obj2):
-    branch = engine.heap.branch()
+@expose_builtin("\\=", unwrap_spec=["raw", "raw"])
+def impl_does_not_unify(engine, heap, obj1, obj2):
+    branch = heap.branch()
     try:
-        obj1.unify(obj2, engine.heap)
+        obj1.unify(obj2, heap)
     except error.UnificationFailed:
-        engine.heap.revert_and_discard(branch)
+        heap.revert_and_discard(branch)
         return
-    engine.heap.discard(branch)
+    heap.discard(branch)
     raise error.UnificationFailed()
-expose_builtin(impl_does_not_unify, "\\=", unwrap_spec=["raw", "raw"])
 
 
 for ext, prolog, python in [("eq", "==", "== 0"),
                             ("gt", "@>", "== 1"),
                             ("ge", "@>=", "!= -1")]:
     exec py.code.Source("""
-def impl_standard_comparison_%s(engine, obj1, obj2):
-    c = term.cmp_standard_order(obj1, obj2, engine.heap)
+@expose_builtin(prolog, unwrap_spec=["obj", "obj"])
+def impl_standard_comparison_%s(engine, heap, obj1, obj2):
+    c = term.cmp_standard_order(obj1, obj2, heap)
     if not c %s:
         raise error.UnificationFailed()""" % (ext, python)).compile()
-    expose_builtin(globals()["impl_standard_comparison_%s" % (ext, )], prolog,
-                   unwrap_spec=["obj", "obj"])