def format_with_ops(self, term): if not helper.is_term(term): return (0, self.format(term)) assert isinstance(term, Callable) if term.signature().eq(conssig): result = ["["] while helper.is_term(term) and isinstance(term, Callable) and term.signature().eq(conssig): first = term.argument_at(0) second = term.argument_at(1).dereference(None) result.append(self.format(first)) result.append(", ") term = second if isinstance(term, Atom) and term.signature().eq(nilsig): result[-1] = "]" else: result[-1] = "|" result.append(self.format(term)) result.append("]") return (0, "".join(result)) if term.signature().eq(tuplesig): result = ["("] while helper.is_term(term) and isinstance(term, Callable) and term.signature().eq(tuplesig): first = term.argument_at(0) second = term.argument_at(1) result.append(self.format(first)) result.append(", ") term = second result.append(self.format(term)) result.append(")") return (0, "".join(result)) if (term.argument_count(), term.name()) not in self.op_mapping: return (0, self.format_term_normally(term)) form, prec = self.op_mapping[(term.argument_count(), term.name())] result = [] assert 0 <= term.argument_count() <= 2 curr_index = 0 for c in form: if c == "f": result.append(self.format_atom(term.name())) else: childprec, child = self.format_with_ops(term.argument_at(curr_index)) parentheses = (c == "x" and childprec >= prec or c == "y" and childprec > prec) if parentheses: result.append("(") result.append(child) result.append(")") else: result.append(child) curr_index += 1 assert curr_index == term.argument_count() return (prec, "".join(result))
def impl_functor(engine, heap, t, functor, arity): if helper.is_atomic(t): functor.unify(t, heap) arity.unify(term.Number(0), heap) elif helper.is_term(t): assert isinstance(t, term.Callable) sig = t.signature() atom = term.Callable.build(t.name(), signature=sig.atom_signature) functor.unify(atom, heap) arity.unify(term.Number(t.argument_count()), heap) elif isinstance(t, term.Var): if isinstance(functor, term.Var): error.throw_instantiation_error() a = helper.unwrap_int(arity) jit.promote(a) if a < 0: error.throw_domain_error("not_less_than_zero", arity) else: functor = helper.ensure_atomic(functor) if a == 0: t.unify(functor, heap) else: jit.promote(functor) name = helper.unwrap_atom(functor) t.unify( term.Callable.build(name, [heap.newvar() for i in range(a)]), heap)
def from_option_list(engine, options): # XXX add numbervars support quoted = False max_depth = 0 ignore_ops = False number_vars = False for option in options: if (not helper.is_term(option) or (isinstance(option, Callable) and option.argument_count() != 1)): error.throw_domain_error('write_option', option) assert isinstance(option, Callable) arg = option.argument_at(0) if option.name()== "max_depth": try: max_depth = helper.unwrap_int(arg) except error.CatchableError: error.throw_domain_error('write_option', option) elif (not isinstance(arg, Atom) or (arg.name()!= "true" and arg.name()!= "false")): error.throw_domain_error('write_option', option) assert 0, "unreachable" elif option.name()== "quoted": quoted = arg.name()== "true" elif option.name()== "ignore_ops": ignore_ops = arg.name()== "true" return TermFormatter(engine, quoted, max_depth, ignore_ops)
def impl_univ(engine, heap, first, second): if not isinstance(first, term.Var): if helper.is_term(first): assert isinstance(first, term.Callable) sig = first.signature().atom_signature l = [term.Callable.build(first.name(), signature=sig)] + first.arguments() else: l = [first] u1 = helper.wrap_list(l) if not isinstance(second, term.Var): u1.unify(second, heap) else: u1.unify(second, heap) else: if isinstance(second, term.Var): error.throw_instantiation_error() else: l = helper.unwrap_list(second) head = l[0].dereference(heap) if not isinstance(head, term.Atom): error.throw_type_error("atom", head) l2 = [None] * (len(l) - 1) for i in range(len(l2)): l2[i] = l[i + 1] name = jit.hint(head.signature(), promote=True).name term.Callable.build(name, l2).unify(first, heap)
def impl_or(engine, heap, rule, call1, call2, scont, fcont): # sucks a bit to have to special-case A -> B ; C here :-( if call1.signature().eq(ifsig): assert helper.is_term(call1) return if_then_else(engine, heap, rule, scont, fcont, call1.argument_at(0), call1.argument_at(1), call2) else: fcont = OrContinuation(engine, rule, scont, fcont, heap, call2) newscont = continuation.BodyContinuation(engine, rule, scont, call1) return newscont, fcont, heap.branch()
def make_rule(self, ruleterm, module): if helper.is_term(ruleterm): assert isinstance(ruleterm, Callable) if ruleterm.signature().eq(predsig): return Rule(ruleterm.argument_at(0), ruleterm.argument_at(1), module) else: return Rule(ruleterm, None, module) elif isinstance(ruleterm, Atom): return Rule(ruleterm, None, module) else: error.throw_type_error("callable", ruleterm)
def test_enumerate_vars_of_bound_var(): from prolog.interpreter.memo import EnumerationMemo h = Heap() X = h.newvar() X.setvalue(Callable.build("a"), h) t1 = Callable.build("f", [X]) memo = EnumerationMemo() t2 = t1.enumerate_vars(memo) assert is_term(t2) assert t2.signature().eq(t1.signature()) assert t1.argument_at(0).dereference(None) is t2.argument_at(0)
def impl_or(engine, heap, rule, call1, call2, scont, fcont): # sucks a bit to have to special-case A -> B ; C here :-( if call1.signature().eq(ifsig): assert helper.is_term(call1) return if_then_else( engine, heap, rule, scont, fcont, call1.argument_at(0), call1.argument_at(1), call2) else: fcont = OrContinuation(engine, rule, scont, fcont, heap, call2) newscont = continuation.BodyContinuation(engine, rule, scont, call1) return newscont, fcont, heap.branch()
def test_enumerate_vars(): from prolog.interpreter.memo import EnumerationMemo X = BindingVar() Y = BindingVar() t1 = Callable.build("f", [X, X, Callable.build("g", [Y, X])]) memo = EnumerationMemo() t2 = t1.enumerate_vars(memo) assert is_term(t2) assert t2.signature().eq(t1.signature()) assert t2.argument_at(0) is t2.argument_at(1) assert t2.argument_at(0).num == 0 assert t2.argument_at(2).argument_at(1).num == 0
def impl_retract(engine, heap, module, pattern): modname = None if pattern.signature().eq(prefixsig): modname, pattern = unpack_modname_and_predicate(pattern) assert isinstance(pattern, term.Callable) if helper.is_term(pattern) and pattern.signature().eq(implsig): head = helper.ensure_callable(pattern.argument_at(0)) body = helper.ensure_callable(pattern.argument_at(1)) else: head = pattern body = None assert isinstance(head, term.Callable) if head.signature().get_extra("builtin"): error.throw_permission_error("modify", "static_procedure", head.get_prolog_signature()) if modname is None: function = module.lookup(head.signature()) else: function = engine.modulewrapper.get_module(modname, pattern).lookup(head.signature()) if function.rulechain is None: raise error.UnificationFailed rulechain = function.rulechain oldstate = heap.branch() while rulechain: rule = rulechain # standardizing apart try: deleted_body = rule.clone_and_unify_head(heap, head) if body is not None: body.unify(deleted_body, heap) except error.UnificationFailed: oldstate.revert_upto(heap) else: if function.rulechain is rulechain: function.rulechain = rulechain.next else: function.remove(rulechain) break rulechain = rulechain.next else: raise error.UnificationFailed()
def impl_retract(engine, heap, module, pattern): modname = None if pattern.signature().eq(prefixsig): modname, pattern = unpack_modname_and_predicate(pattern) assert isinstance(pattern, term.Callable) if helper.is_term(pattern) and pattern.signature().eq(implsig): head = helper.ensure_callable(pattern.argument_at(0)) body = helper.ensure_callable(pattern.argument_at(1)) else: head = pattern body = None assert isinstance(head, term.Callable) if head.signature().get_extra("builtin"): error.throw_permission_error("modify", "static_procedure", head.get_prolog_signature()) if modname is None: function = module.lookup(head.signature()) else: function = engine.modulewrapper.get_module(modname, pattern).lookup( head.signature()) if function.rulechain is None: raise error.UnificationFailed rulechain = function.rulechain oldstate = heap.branch() while rulechain: rule = rulechain # standardizing apart try: deleted_body = rule.clone_and_unify_head(heap, head) if body is not None: body.unify(deleted_body, heap) except error.UnificationFailed: oldstate.revert_upto(heap) else: if function.rulechain is rulechain: function.rulechain = rulechain.next else: function.remove(rulechain) break rulechain = rulechain.next else: raise error.UnificationFailed()
def format(self, term): self.curr_depth += 1 term = term.dereference(None) if self.max_depth > 0 and self.curr_depth > self.max_depth: return "..." if isinstance(term, Atom): return self.format_atom(term.name()) elif isinstance(term, Number): return self.format_number(term) elif isinstance(term, Float): return self.format_float(term) elif helper.is_term(term): assert isinstance(term, Callable) return self.format_term(term) elif isinstance(term, AttVar): return self.format_attvar(term) elif isinstance(term, Var): return self.format_var(term) elif isinstance(term, PrologStream): return self.format_stream(term) else: return '?'
def impl_arg(engine, heap, rule, first, second, third, scont, fcont): if isinstance(second, term.Var): error.throw_instantiation_error() if isinstance(second, term.Atom): raise error.UnificationFailed() error.throw_type_error('compound', second) if not helper.is_term(second): error.throw_type_error("compound", second) assert isinstance(second, term.Callable) if isinstance(first, term.Var): return continue_arg(engine, scont, fcont, heap, first, 0, second, third, rule) 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 > second.argument_count(): raise error.UnificationFailed() arg = second.argument_at(num - 1) third.unify(arg, heap) else: error.throw_type_error("integer", first) return scont, fcont, heap
def impl_compound(engine, heap, var): if isinstance(var, term.Var): raise error.UnificationFailed() if helper.is_term(var): return raise error.UnificationFailed()