result.append(child) result.append(")") else: result.append(child) curr_index += 1 assert curr_index == len(term.args) return (prec, "".join(result)) def _make_reverse_op_mapping(self): m = {} for prec, allops in self.engine.getoperations(): for form, ops in allops: for op in ops: m[len(form) - 1, op] = (form, prec) self.op_mapping = m def impl_write_term(engine, 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"]) 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"])
from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # loading prolog source files def impl_consult(engine, var): import os if isinstance(var, term.Atom): try: fd = os.open(var.name, os.O_RDONLY, 0777) except OSError, e: error.throw_existence_error("source_sink", var) assert 0, "unreachable" # make the flow space happy try: content = [] while 1: s = os.read(fd, 4096) if not s: break content.append(s) file_content = "".join(content) finally: os.close(fd) engine.runstring(file_content) expose_builtin(impl_consult, "consult", unwrap_spec=["obj"])
impl_ground(engine, exc_term) except error.UnificationFailed: raise error.UncatchableError( "not implemented: catching of non-ground terms") try: catcher.unify(exc_term, engine.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): try: impl_ground(engine, 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"])
if isinstance(varorint, term.Var): for i in range(lower, upper): oldstate = engine.heap.branch() try: varorint.unify(term.Number(i), engine.heap) return continuation.call(engine, choice_point=True) except error.UnificationFailed: engine.heap.revert(oldstate) varorint.unify(term.Number(upper), engine.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) impl_is._look_inside_me_ = True expose_builtin(impl_is, "is", unwrap_spec=["raw", "arithmetic"]) for ext, prolog, python in [("eq", "=:=", "=="), ("ne", "=\\=", "!="), ("lt", "<", "<"), ("le", "=<", "<="), ("gt", ">", ">"), ("ge", ">=", ">=")]: exec py.code.Source(""" def impl_arith_%s(engine, num1, num2): eq = False
elif isinstance(t, term.Var): if isinstance(functor, term.Var): error.throw_instantiation_error() a = helper.unwrap_int(arity) if a < 0: error.throw_domain_error("not_less_than_zero", arity) else: functor = helper.ensure_atomic(functor) if a == 0: t.unify(helper.ensure_atomic(functor), engine.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"]) def impl_arg(engine, first, second, third, continuation): if isinstance(second, term.Var): error.throw_instantiation_error() if isinstance(second, term.Atom): raise error.UnificationFailed() if not isinstance(second, term.Term): error.throw_type_error("compound", second) if isinstance(first, term.Var): for i in range(len(second.args)): arg = second.args[i] oldstate = engine.heap.branch() try: third.unify(arg, engine.heap) first.unify(term.Number(i + 1), engine.heap)
# ___________________________________________________________________ # database def impl_abolish(engine, predicate): from pypy.lang.prolog.builtin import builtins name, arity = helper.unwrap_predicate_indicator(predicate) if arity < 0: error.throw_domain_error("not_less_than_zero", term.Number(arity)) signature = name + "/" + str(arity) if signature in builtins: error.throw_permission_error("modify", "static_procedure", 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"]) def impl_asserta(engine, rule): engine.add_rule(rule.getvalue(engine.heap), end=False) expose_builtin(impl_asserta, "asserta", unwrap_spec=["callable"]) def impl_retract(engine, pattern): from pypy.lang.prolog.builtin import builtins if isinstance(pattern, term.Term) and pattern.name == ":-": head = helper.ensure_callable(pattern.args[0]) body = helper.ensure_callable(pattern.args[1])
import py from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # type verifications def impl_nonvar(engine, var): if isinstance(var, term.Var): raise error.UnificationFailed() expose_builtin(impl_nonvar, "nonvar", unwrap_spec=["obj"]) def impl_var(engine, var): if not isinstance(var, term.Var): raise error.UnificationFailed() expose_builtin(impl_var, "var", unwrap_spec=["obj"]) def impl_integer(engine, 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_current_op(engine, precedence, typ, name, continuation): for prec, allops in engine.getoperations(): for form, ops in allops: for op in ops: oldstate = engine.heap.branch() try: precedence.unify(term.Number(prec), engine.heap) typ.unify(term.Atom.newatom(form), engine.heap) name.unify(term.Atom(op), engine.heap) return continuation.call(engine, choice_point=True) except error.UnificationFailed: engine.heap.revert(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): from pypy.lang.prolog.interpreter import parsing if engine.operations is None: engine.operations = parsing.make_default_operations() operations = engine.operations precedence_to_ops = {} for prec, allops in operations: precedence_to_ops[prec] = allops for form, ops in allops: try: index = ops.index(name) del ops[index]
exc_term = e.term.getvalue(engine.heap) engine.heap.revert(old_state) d = {} exc_term = exc_term.copy(engine.heap, d) try: impl_ground(engine, exc_term) except error.UnificationFailed: raise error.UncatchableError( "not implemented: catching of non-ground terms") try: catcher.unify(exc_term, engine.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): try: impl_ground(engine, 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"])
import py from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # control predicates def impl_fail(engine): raise error.UnificationFailed() expose_builtin(impl_fail, "fail", unwrap_spec=[]) def impl_true(engine): return expose_builtin(impl_true, "true", unwrap_spec=[]) def impl_repeat(engine, 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): raise error.CutException(continuation) expose_builtin(impl_cut, "!", unwrap_spec=[], handles_continuation=True) class AndContinuation(engine.Continuation): def __init__(self, next_call, continuation):
if isinstance(functor, term.Var): error.throw_instantiation_error() a = helper.unwrap_int(arity) if a < 0: error.throw_domain_error("not_less_than_zero", arity) else: functor = helper.ensure_atomic(functor) if a == 0: t.unify(helper.ensure_atomic(functor), engine.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"]) def impl_arg(engine, first, second, third, continuation): if isinstance(second, term.Var): error.throw_instantiation_error() if isinstance(second, term.Atom): raise error.UnificationFailed() if not isinstance(second, term.Term): error.throw_type_error("compound", second) if isinstance(first, term.Var): for i in range(len(second.args)): arg = second.args[i] oldstate = engine.heap.branch() try: third.unify(arg, engine.heap)
else: raise error.UnificationFailed() else: s1 = helper.convert_to_str(a1) if isinstance(a2, term.Var): r = helper.convert_to_str(result) if r.startswith(s1): a2.unify(term.Atom(r[len(s1):]), engine.heap) else: raise error.UnificationFailed() else: s2 = helper.convert_to_str(a2) result.unify(term.Atom(s1 + s2), engine.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): 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"]) def impl_sub_atom(engine, s, before, length, after, sub, continuation): # XXX can possibly be optimized if isinstance(length, term.Var): startlength = 0 stoplength = len(s) + 1 else: startlength = helper.unwrap_int(length)
import py from pypy.lang.prolog.interpreter import arithmetic from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # comparison and unification of terms def impl_unify(engine, obj1, obj2): obj1.unify(obj2, engine.heap) expose_builtin(impl_unify, "=", unwrap_spec=["raw", "raw"]) 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"]) def impl_does_not_unify(engine, obj1, obj2): try: branch = engine.heap.branch() try: obj1.unify(obj2, engine.heap)
from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # finding all solutions to a goal class FindallContinuation(engine.Continuation): def __init__(self, template): self.found = [] self.template = template def _call(self, engine): clone = self.template.getvalue(engine.heap) self.found.append(clone) raise error.UnificationFailed() def impl_findall(engine, template, goal, bag): oldstate = engine.heap.branch() collector = FindallContinuation(template) try: engine.call(goal, collector) except error.UnificationFailed: engine.heap.revert(oldstate) 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) result = term.Term(".", [copy, result]) bag.unify(result, engine.heap) expose_builtin(impl_findall, "findall", unwrap_spec=['raw', 'callable', 'raw'])
def _make_reverse_op_mapping(self): m = {} for prec, allops in self.engine.getoperations(): for form, ops in allops: for op in ops: m[len(form) - 1, op] = (form, prec) self.op_mapping = m def impl_write_term(engine, 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"]) 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"])
# database def impl_abolish(engine, predicate): from pypy.lang.prolog.builtin import builtins name, arity = helper.unwrap_predicate_indicator(predicate) if arity < 0: error.throw_domain_error("not_less_than_zero", term.Number(arity)) signature = name + "/" + str(arity) if signature in builtins: error.throw_permission_error("modify", "static_procedure", 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"]) def impl_asserta(engine, rule): engine.add_rule(rule.getvalue(engine.heap), end=False) expose_builtin(impl_asserta, "asserta", unwrap_spec=["callable"])
import py from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # meta-call predicates def impl_call(engine, 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): engine.call(clause) return continuation.call(engine, choice_point=False) expose_builtin(impl_once, "once", unwrap_spec=["callable"], handles_continuation=True)
try: varorint.unify(term.Number(i), engine.heap) return continuation.call(engine, choice_point=True) except error.UnificationFailed: engine.heap.revert(oldstate) varorint.unify(term.Number(upper), engine.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) impl_is._look_inside_me_ = True expose_builtin(impl_is, "is", unwrap_spec=["raw", "arithmetic"]) for ext, prolog, python in [("eq", "=:=", "=="), ("ne", "=\\=", "!="), ("lt", "<", "<"), ("le", "=<", "<="), ("gt", ">", ">"), ("ge", ">=", ">=")]: exec py.code.Source(""" def impl_arith_%s(engine, num1, num2):
import py from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # type verifications def impl_nonvar(engine, var): if isinstance(var, term.Var): raise error.UnificationFailed() expose_builtin(impl_nonvar, "nonvar", unwrap_spec=["obj"]) def impl_var(engine, var): if not isinstance(var, term.Var): raise error.UnificationFailed() expose_builtin(impl_var, "var", unwrap_spec=["obj"]) def impl_integer(engine, 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): 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): if (isinstance(var, term.Var) or (not isinstance(var, term.Number) and not isinstance(var, term.Float))):
import py from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # control predicates def impl_fail(engine): raise error.UnificationFailed() expose_builtin(impl_fail, "fail", unwrap_spec=[]) def impl_true(engine): return expose_builtin(impl_true, "true", unwrap_spec=[]) def impl_repeat(engine, continuation): while 1: try: return continuation.call(engine, choice_point=True) except error.UnificationFailed: pass
import py from pypy.lang.prolog.interpreter import arithmetic from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin.register import expose_builtin # ___________________________________________________________________ # comparison and unification of terms def impl_unify(engine, obj1, obj2): obj1.unify(obj2, engine.heap) expose_builtin(impl_unify, "=", unwrap_spec=["raw", "raw"]) 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"]) def impl_does_not_unify(engine, obj1, obj2): try: branch = engine.heap.branch() try: obj1.unify(obj2, engine.heap) finally: engine.heap.revert(branch) except error.UnificationFailed: return raise error.UnificationFailed() expose_builtin(impl_does_not_unify, "\\=", unwrap_spec=["raw", "raw"])