[pypy-svn] r44087 - in pypy/branch/prolog-bytecode/pypy/lang/prolog: builtin interpreter interpreter/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Jun 7 13:54:45 CEST 2007
Author: cfbolz
Date: Thu Jun 7 13:54:44 2007
New Revision: 44087
Modified:
pypy/branch/prolog-bytecode/pypy/lang/prolog/builtin/control.py
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/test/test_compiler.py
Log:
mostly implement the cut - corner case with call(!) seems not to work yet.
Modified: pypy/branch/prolog-bytecode/pypy/lang/prolog/builtin/control.py
==============================================================================
--- pypy/branch/prolog-bytecode/pypy/lang/prolog/builtin/control.py (original)
+++ pypy/branch/prolog-bytecode/pypy/lang/prolog/builtin/control.py Thu Jun 7 13:54:44 2007
@@ -23,7 +23,6 @@
expose_builtin(impl_repeat, "repeat", unwrap_spec=[], handles_continuation=True)
def impl_cut(engine, continuation):
- py.test.skip("the cut is not working right now")
raise error.CutException(continuation)
expose_builtin(impl_cut, "!", unwrap_spec=[],
handles_continuation=True)
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 13:54:44 2007
@@ -44,6 +44,7 @@
self.functionmap = {}
self.maxlocalvar = 0
self.varmap = {}
+ self.can_contain_cut = False
result = Code()
self.compile_termbuilding(head)
result.opcode_head = self.getbytecode()
@@ -54,6 +55,7 @@
result.term_info = self.term_info
result.functions = self.functions
result.maxlocalvar = len(self.varmap)
+ result.can_contain_cut = self.can_contain_cut
return result
def compile_termbuilding(self, term):
@@ -75,6 +77,7 @@
body = body.dereference(self.engine.heap)
if isinstance(body, Var):
+ self.can_contain_cut = True
self.compile_termbuilding(body)
self.emit_opcode(opcodedesc.DYNAMIC_CALL)
return
@@ -90,6 +93,9 @@
self.emit_opcode(opcodedesc.UNIFY)
elif body.signature == "call/1": #XXX interactions with cuts correct?
self.compile_body(body.args[0])
+ elif body.signature == "!/0":
+ self.can_contain_cut = True
+ self.emit_opcode(opcodedesc.CUT)
elif body.signature in builtins_index:
i = builtins_index[body.signature]
self.compile_termbuilding(body)
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 13:54:44 2007
@@ -1,7 +1,8 @@
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.engine import Continuation
+from pypy.lang.prolog.interpreter.engine import Continuation, \
+ LimitedScopeContinuation
from pypy.lang.prolog.interpreter.prologopcode import unrolling_opcode_descs, \
HAVE_ARGUMENT
@@ -72,11 +73,12 @@
self.stack = None
def run_directly(self, continuation, choice_point=True):
- cont = self.run(self.code.opcode, 0, continuation)
+ if self.code.opcode:
+ continuation = self.run(self.code.opcode, 0, continuation)
if not choice_point:
- return cont
- while cont is not None:
- cont = cont._call(self.engine)
+ return continuation
+ while continuation is not None:
+ continuation = continuation._call(self.engine)
def run(self, bytecode, pc, continuation):
stack = []
@@ -133,7 +135,7 @@
result = self.localvarcache[number] = self.engine.heap.newvar()
stack.append(result)
- def MAKETERM(self, stack, number, *ignored):
+ def MAKETERM(self, stack, number):
name, numargs, signature = self.code.term_info[number]
args = [None] * numargs
i = numargs - 1
@@ -142,17 +144,20 @@
i -= 1
stack.append(Term(name, args, signature))
- def CALL_BUILTIN(self, stack, number, continuation, *ignored):
+ def CALL_BUILTIN(self, stack, number, continuation):
from pypy.lang.prolog.builtin import builtins_list
return builtins_list[number][1].call(self.engine, stack.pop(),
continuation)
+
+ def CUT(self, stack, continuation):
+ raise error.CutException(continuation)
def STATIC_CALL(self, stack, number, continuation):
query = stack.pop()
function = self.code.functions[number]
return self.user_call(function, query, continuation)
- def DYNAMIC_CALL(self, stack, continuation, *ignored):
+ def DYNAMIC_CALL(self, stack, continuation):
query = stack.pop()
assert isinstance(query, Callable)
signature = query.signature
@@ -163,6 +168,12 @@
function = self.engine.lookup_userfunction(signature)
return self.user_call(function, query, continuation)
+ def CLEAR_LOCAL(self, stack, number):
+ self.localvarcache[number] = None
+
+ def UNIFY(self, stack):
+ stack.pop().unify(stack.pop(), self.engine.heap)
+
def user_call(self, function, query, continuation):
rulechain = function.rulechain
if rulechain is None:
@@ -171,20 +182,27 @@
oldstate = self.engine.heap.branch()
while rulechain is not None:
rule = rulechain.rule
- try:
- frame = rule.make_frame(query)
- frame.run_directly(continuation)
- return
- except error.UnificationFailed:
- self.engine.heap.revert(oldstate)
+ if rule.code.can_contain_cut:
+ continuation = LimitedScopeContinuation(continuation)
+ try:
+ frame = rule.make_frame(query)
+ frame.run_directly(continuation)
+ return
+ except error.UnificationFailed:
+ self.engine.heap.revert(oldstate)
+ except error.CutException, e:
+ if continuation.scope_active:
+ return self.engine.continue_after_cut(e.continuation,
+ continuation)
+ raise
+ else:
+ try:
+ frame = rule.make_frame(query)
+ frame.run_directly(continuation)
+ return
+ except error.UnificationFailed:
+ self.engine.heap.revert(oldstate)
rule = rulechain.rule
rulechain = rulechain.next
raise error.UnificationFailed
- def CLEAR_LOCAL(self, stack, number, *ignored):
- self.localvarcache[number] = None
-
- def UNIFY(self, stack, *ignored):
- stack.pop().unify(stack.pop(), self.engine.heap)
-
-
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 13:54:44 2007
@@ -37,6 +37,7 @@
def_op("CONTINUE", 'O')
def_op("DYNAMIC_CALL", 'D', True)
argument_op("STATIC_CALL", 's', True)
+def_op("CUT", 'C', True)
class OpcodeDesc(object):
def __init__(self, name, index):
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 13:54:44 2007
@@ -9,6 +9,7 @@
assert not code.opcode
assert code.opcode_head == "c\x00\x00"
assert code.constants == [foo]
+ assert not code.can_contain_cut
def test_simple_withbody():
e = get_engine("")
@@ -18,6 +19,7 @@
assert code.opcode_head == "c\x00\x00"
assert code.opcode == "c\x00\x01s\x00\x00"
assert code.constants == [foo, bar]
+ assert not code.can_contain_cut
def test_simple_withargs():
e = get_engine("")
@@ -27,6 +29,7 @@
assert code.opcode == "l\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
def test_simple_and():
e = get_engine("")
@@ -36,6 +39,7 @@
assert code.opcode == "l\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
def test_nested_term():
e = get_engine("")
@@ -44,6 +48,7 @@
assert code.opcode_head == "l\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
def test_unify():
e = get_engine("")
@@ -53,6 +58,7 @@
assert code.opcode == "l\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
def test_dynamic_call():
e = get_engine("")
@@ -61,5 +67,15 @@
assert code.opcode_head == "l\x00\x00l\x00\x01t\x00\x00"
assert code.opcode == "l\x00\x00Dl\x00\x01D"
assert code.term_info == [("f", 2, "f/2")]
+ assert code.can_contain_cut
+
+def test_cut():
+ 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.term_info == [("f", 2, "f/2")]
+ assert code.can_contain_cut
More information about the Pypy-commit
mailing list