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) return continuation.call(engine, choice_point=True) except error.UnificationFailed: engine.heap.revert(oldstate) raise error.UnificationFailed() elif isinstance(first, term.Number): num = first.num if num == 0: raise error.UnificationFailed if num < 0: error.throw_domain_error("not_less_than_zero", first) if num > len(second.args): raise error.UnificationFailed() arg = second.args[num - 1] third.unify(arg, engine.heap) else: error.throw_type_error("integer", first) return continuation.call(engine, choice_point=False)
def impl_atom_concat(engine, 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() try: a1.unify(term.Atom(r[:i]), engine.heap) a2.unify(term.Atom(r[i:]), engine.heap) return continuation.call(engine, choice_point=True) except error.UnificationFailed: engine.heap.revert(oldstate) raise error.UnificationFailed() else: s2 = helper.convert_to_str(a2) r = helper.convert_to_str(result) if r.endswith(s2): stop = len(r) - len(s2) assert stop > 0 a1.unify(term.Atom(r[:stop]), 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)
def impl_not(engine, call): try: try: engine.call(call) except error.CutException, e: engine.continue_after_cut(e.continuation) except error.UnificationFailed: return None raise error.UnificationFailed()
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()
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]) else: head = pattern body = None if head.signature in builtins: assert isinstance(head, term.Callable) error.throw_permission_error("modify", "static_procedure", head.get_prolog_signature()) function = engine.signature2function.get(head.signature, None) if function is None: raise error.UnificationFailed #import pdb; pdb.set_trace() rulechain = function.rulechain while rulechain: rule = rulechain.rule oldstate = engine.heap.branch() # standardizing apart try: deleted_body = rule.clone_and_unify_head(engine.heap, head) if body is not None: body.unify(deleted_body, engine.heap) except error.UnificationFailed: engine.heap.revert(oldstate) else: if function.rulechain is rulechain: if rulechain.next is None: del engine.signature2function[head.signature] else: function.rulechain = rulechain.next else: function.remove(rulechain) break rulechain = rulechain.next else: raise error.UnificationFailed()
def _call(self, engine): clone = self.template.getvalue(engine.heap) self.found.append(clone) raise error.UnificationFailed()
def impl_ground(engine, var): if isinstance(var, term.Var): raise error.UnificationFailed() if isinstance(var, term.Term): for arg in var.args: impl_ground(engine, arg)
def impl_nonvar(engine, var): if isinstance(var, term.Var): raise error.UnificationFailed()
def impl_callable(engine, var): if not helper.is_callable(var, engine): raise error.UnificationFailed()
def impl_compound(engine, var): if isinstance(var, term.Var) or not isinstance(var, term.Term): raise error.UnificationFailed()
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) stoplength = startlength + 1 if startlength < 0: startlength = 0 stoplength = len(s) + 1 if isinstance(before, term.Var): startbefore = 0 stopbefore = len(s) + 1 else: startbefore = helper.unwrap_int(before) stopbefore = startbefore + 1 if startbefore < 0: startbefore = 0 stopbefore = len(s) + 1 oldstate = engine.heap.branch() if not isinstance(sub, term.Var): s1 = helper.unwrap_atom(sub) if len(s1) >= stoplength or len(s1) < startlength: raise error.UnificationFailed() start = startbefore while True: try: try: b = s.find(s1, start, stopbefore + len(s1)) # XXX -1? 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) return continuation.call(engine, choice_point=True) except: engine.heap.revert(oldstate) raise except error.UnificationFailed: pass raise error.UnificationFailed() if isinstance(after, term.Var): for b in range(startbefore, stopbefore): for l in range(startlength, stoplength): if l + b > len(s): continue try: 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) return continuation.call(engine, choice_point=True) except: engine.heap.revert(oldstate) raise except error.UnificationFailed: pass else: a = helper.unwrap_int(after) for l in range(startlength, stoplength): b = len(s) - l - a assert b >= 0 if l + b > len(s): continue try: 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) return continuation.call(engine, choice_point=True) return None except: engine.heap.revert(oldstate) raise except error.UnificationFailed: pass raise error.UnificationFailed()
def impl_atom(engine, var): if isinstance(var, term.Var) or not isinstance(var, term.Atom): raise error.UnificationFailed()
def impl_number(engine, var): if (isinstance(var, term.Var) or (not isinstance(var, term.Number) and not isinstance(var, term.Float))): raise error.UnificationFailed()
def impl_float(engine, var): if isinstance(var, term.Var) or not isinstance(var, term.Float): raise error.UnificationFailed()
def impl_integer(engine, var): if isinstance(var, term.Var) or not isinstance(var, term.Number): raise error.UnificationFailed()
def impl_fail(engine): raise error.UnificationFailed()
def impl_atomic(engine, var): if helper.is_atomic(var): return raise error.UnificationFailed()