[pypy-svn] r44097 - in pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Jun 7 17:24:26 CEST 2007


Author: cfbolz
Date: Thu Jun  7 17:24:26 2007
New Revision: 44097

Modified:
   pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/compiler.py
   pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/interpreter.py
   pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/prologopcode.py
   pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/term.py
   pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/test/test_compiler.py
Log:
prevent trailing for variables in the head again


Modified: pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/compiler.py
==============================================================================
--- pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/compiler.py	(original)
+++ pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/compiler.py	Thu Jun  7 17:24:26 2007
@@ -38,6 +38,7 @@
         self.term_info = [] # tuples of (functor, numargs, signature)
         self.term_info_map = {}
         self.opcode = []
+        self.localactivations = []
         self.constants = [] # list of ground Prolog objects
         self.constant_map = {}
         self.functions = [] # list of Function objects
@@ -49,6 +50,7 @@
         self.compile_termbuilding(head)
         result.opcode_head = self.getbytecode()
         if body is not None:
+            self.add_localactivations()
             self.compile_body(body)
         result.opcode = self.getbytecode()
         result.constants = self.constants
@@ -63,8 +65,7 @@
             num = self.getconstnum(term)
             self.emit_opcode(opcodedesc.PUTCONSTANT, num)
         elif isinstance(term, Var):
-            num = self.getvarnum(term)
-            self.emit_opcode(opcodedesc.PUTLOCALVAR, num)
+            self.compile_localvar(term)
         else:
             assert isinstance(term, Term)
             for arg in term.args:
@@ -99,32 +100,44 @@
             i = builtins_index[body.signature]
             self.compile_termbuilding(body)
             self.emit_opcode(opcodedesc.CALL_BUILTIN, i)
+            self.add_localactivations()
         else:
             self.compile_termbuilding(body)
             num = self.getfunction(body.signature)
             self.emit_opcode(opcodedesc.STATIC_CALL, num)
+            self.add_localactivations()
 
-    def emit_opcode(self, desc, arg=-1):
-        self.opcode.append(desc.index)
+    def compile_localvar(self, var):
+        try:
+            num = self.varmap[var]
+        except KeyError:
+            num = self.varmap[var] = len(self.varmap)
+            self.emit_opcode(opcodedesc.MAKELOCALVAR, num)
+            self.emit_opcode(opcodedesc.ACTIVATE_LOCAL, num, True)
+            return
+        self.emit_opcode(opcodedesc.PUTLOCALVAR, num)
+
+    def add_localactivations(self):
+        self.opcode.extend(self.localactivations)
+        self.localactivations = []
+
+    def emit_opcode(self, desc, arg=-1, to_activations=False):
+        if to_activations:
+            opcode = self.localactivations
+        else:
+            opcode = self.opcode
+        opcode.append(desc.index)
         if desc.hasargument:
             if not 0 <= arg < 65536:
                 raise error.UncatchableError("too many constants or variables!")
-            self.opcode.append(arg >> 8)
-            self.opcode.append(arg & 0xff)
+            opcode.append(arg >> 8)
+            opcode.append(arg & 0xff)
 
     def getbytecode(self):
         bytecodes = [chr(c) for c in self.opcode]
         self.opcode = []
         return "".join(bytecodes)
 
-
-    def getvarnum(self, var):
-        try:
-            return self.varmap[var]
-        except KeyError:
-            result = self.varmap[var] = len(self.varmap)
-            return result
-
     def getsignum(self, term):
         try:
             return self.term_info_map[term.signature]

Modified: pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/interpreter.py
==============================================================================
--- pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/interpreter.py	(original)
+++ pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/interpreter.py	Thu Jun  7 17:24:26 2007
@@ -1,6 +1,7 @@
 from pypy.lang.prolog.interpreter import helper
 from pypy.lang.prolog.interpreter import error
-from pypy.lang.prolog.interpreter.term import Term, Atom, Var, Callable
+from pypy.lang.prolog.interpreter.term import Term, Atom, Var, Callable, \
+    LocalVar
 from pypy.lang.prolog.interpreter.engine import Continuation, \
     LimitedScopeContinuation, DONOTHING
 from pypy.lang.prolog.interpreter.prologopcode import unrolling_opcode_descs, \
@@ -132,12 +133,21 @@
     def PUTCONSTANT(self, stack, number):
         stack.append(self.code.constants[number])
 
+    def MAKELOCALVAR(self, stack, number):
+        result = self.localvarcache[number] = self.engine.heap.newvar()
+        stack.append(result)
+
     def PUTLOCALVAR(self, stack, number):
         result = self.localvarcache[number]
-        if result is None:
-            result = self.localvarcache[number] = self.engine.heap.newvar()
+        assert result is not None
         stack.append(result)
 
+    def ACTIVATE_LOCAL(self, stack, number):
+        var = self.localvarcache[number]
+        if isinstance(var, LocalVar):
+            self.localvarcache[number] = var.dereference(self.heap)
+            var.active = True
+
     def MAKETERM(self, stack, number):
         name, numargs, signature = self.code.term_info[number]
         args = [None] * numargs

Modified: pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/prologopcode.py
==============================================================================
--- pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/prologopcode.py	(original)
+++ pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/prologopcode.py	Thu Jun  7 17:24:26 2007
@@ -28,6 +28,8 @@
 # term construction
 argument_op("PUTCONSTANT", 'c')
 argument_op("PUTLOCALVAR", 'l')
+argument_op("MAKELOCALVAR", 'm')
+argument_op("ACTIVATE_LOCAL", 'a')
 argument_op("MAKETERM", 't')
 
 # running

Modified: pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/term.py
==============================================================================
--- pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/term.py	(original)
+++ pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/term.py	Thu Jun  7 17:24:26 2007
@@ -165,6 +165,19 @@
         return self.eval_arithmetic(engine)
 
 
+class LocalVar(Var):
+    __slots__ = ("binding", "active")
+
+    def __init__(self):
+        self.binding = None
+        self.active = False
+
+    def setvalue(self, value, heap):
+        if self.active:
+            heap.add_trail(self)
+        self.binding = value
+
+
 class NonVar(PrologObject):
     __slots__ = ()
 

Modified: pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/test/test_compiler.py	(original)
+++ pypy/branch/prolog-bytecode/pypy/lang/prolog/interpreter/test/test_compiler.py	Thu Jun  7 17:24:26 2007
@@ -25,8 +25,8 @@
     e = get_engine("")
     head, body = get_query_and_vars("f(X) :- g(X).")[0].args
     code = compile(head, body, e)
-    assert code.opcode_head == "l\x00\x00t\x00\x00"
-    assert code.opcode == "l\x00\x00t\x00\x01s\x00\x00"
+    assert code.opcode_head == "m\x00\x00t\x00\x00"
+    assert code.opcode == "a\x00\x00l\x00\x00t\x00\x01s\x00\x00"
     assert code.constants == []
     assert code.term_info == [("f", 1, "f/1"), ("g", 1, "g/1")]
     assert not code.can_contain_cut
@@ -35,8 +35,8 @@
     e = get_engine("")
     head, body = get_query_and_vars("f(X, Y) :- g(X), h(Y).")[0].args
     code = compile(head, body, e)
-    assert code.opcode_head == "l\x00\x00l\x00\x01t\x00\x00"
-    assert code.opcode == "l\x00\x00t\x00\x01s\x00\x00l\x00\x01t\x00\x02s\x00\x01"
+    assert code.opcode_head == "m\x00\x00m\x00\x01t\x00\x00"
+    assert code.opcode == "a\x00\x00a\x00\x01l\x00\x00t\x00\x01s\x00\x00l\x00\x01t\x00\x02s\x00\x01"
     assert code.constants == []
     assert code.term_info == [("f", 2, "f/2"), ("g", 1, "g/1"), ("h", 1, "h/1")]
     assert not code.can_contain_cut
@@ -45,7 +45,7 @@
     e = get_engine("")
     head = get_query_and_vars("f(g(X), a).")[0]
     code = compile(head, None, e)
-    assert code.opcode_head == "l\x00\x00t\x00\x00c\x00\x00t\x00\x01"
+    assert code.opcode_head == "m\x00\x00t\x00\x00c\x00\x00t\x00\x01"
     assert code.term_info == [("g", 1, "g/1"), ("f", 2, "f/2")]
     assert code.constants == [Atom("a")]
     assert not code.can_contain_cut
@@ -54,8 +54,8 @@
     e = get_engine("")
     head, body = get_query_and_vars("f(X, Y) :- g(X) = g(Y).")[0].args
     code = compile(head, body, e)
-    assert code.opcode_head == "l\x00\x00l\x00\x01t\x00\x00"
-    assert code.opcode == "l\x00\x00t\x00\x01l\x00\x01t\x00\x01U"
+    assert code.opcode_head == "m\x00\x00m\x00\x01t\x00\x00"
+    assert code.opcode == "a\x00\x00a\x00\x01l\x00\x00t\x00\x01l\x00\x01t\x00\x01U"
     assert code.constants == []
     assert code.term_info == [("f", 2, "f/2"), ("g", 1, "g/1")]
     assert not code.can_contain_cut
@@ -64,8 +64,8 @@
     e = get_engine("")
     head, body = get_query_and_vars("f(X, Y) :- X, call(Y).")[0].args
     code = compile(head, body, e)
-    assert code.opcode_head == "l\x00\x00l\x00\x01t\x00\x00"
-    assert code.opcode.startswith("l\x00\x00Dl\x00\x01t\x00\x01b")
+    assert code.opcode_head == "m\x00\x00m\x00\x01t\x00\x00"
+    assert code.opcode.startswith("a\x00\x00a\x00\x01l\x00\x00Dl\x00\x01t\x00\x01b")
     assert code.term_info == [("f", 2, "f/2"), ("call", 1, "call/1")]
     assert code.can_contain_cut
 
@@ -73,8 +73,8 @@
     e = get_engine("")
     head, body = get_query_and_vars("f(X, Y) :- !.")[0].args
     code = compile(head, body, e)
-    assert code.opcode_head == "l\x00\x00l\x00\x01t\x00\x00"
-    assert code.opcode == "C"
+    assert code.opcode_head == "m\x00\x00m\x00\x01t\x00\x00"
+    assert code.opcode == "a\x00\x00a\x00\x01C"
     assert code.term_info == [("f", 2, "f/2")]
     assert code.can_contain_cut
 
@@ -83,9 +83,10 @@
     e = get_engine("")
     head, body = get_query_and_vars("f(X) :- Y is X - 1, f(Y).")[0].args
     code = compile(head, body, e)
-    assert code.opcode_head == "l\x00\x00t\x00\x00"
+    assert code.opcode_head == "m\x00\x00t\x00\x00"
     assert code.opcode.startswith(
-        "l\x00\x01l\x00\x00c\x00\x00t\x00\x01t\x00\x02b")
+        "a\x00\x00m\x00\x01l\x00\x00c\x00\x00t\x00\x01t\x00\x02b\x00\x02"
+        "a\x00\x01")
     assert code.constants == [Number(1)]
     assert code.term_info == [("f", 1, "f/1"), ("-", 2, "-/2"),
                               ("is", 2, "is/2")]


More information about the pypy-svn mailing list