def build(term_name, args=None, signature=None, heap=None, cache=True): if args is None: args = [] if heap is not None: # perform variable shunting: # remove variables that are not needed because they are bound # already and cannot be backtracked for i in range(len(args)): arg = args[i] if (isinstance(arg, Var) and arg.getbinding() is not None and arg.created_after_choice_point is heap): args[i] = arg.getbinding() if len(args) == 0: if cache: return Atom.newatom(term_name, signature) return Atom(term_name, signature) else: if signature is None: if cache: signature = Signature.getsignature(term_name, len(args)) else: signature = Signature(term_name, len(args)) else: assert signature.numargs == len(args) assert isinstance(signature, Signature) cls = Callable._find_specialized_class(term_name, len(args)) if cls is not None: return cls(term_name, args, signature) cls = Callable._find_specialized_class('Term', len(args)) if cls is not None: return cls(term_name, args, signature) return Term(term_name, args, signature)
def test_eq(): sig1 = Signature("a", 0) assert sig1.eq(sig1) sig2 = Signature("a", 0) assert sig1.eq(sig2) sig3 = Signature("a", 1) assert not sig1.eq(sig3) sig4 = Signature("b", 0) assert not sig1.eq(sig4)
def get_rules_from_fact(engine, rule, rule_dist, query, heap, rules = None): module = engine.modulewrapper.current_module rule = rule.split('/') name = rule[0] nargs = int(rule[1]) sig = Signature.getsignature(name, nargs) function = module.lookup(sig) simchain = [] if (function.rulechain is None): return None #handle by UnificationFailed if rules is None: rules = [] #engine._print_rulechain(function.rulechain) #print('\n') startrulechain = jit.hint(function.rulechain, promote = True) if startrulechain is not None: rulechain, simchain = startrulechain.find_applicable_rule(query, heap, engine.similarity, simchain, module, nargs) # TODO similarity while rulechain is not None: rules.append(jit.hint(rulechain, promote = True)) rulechain, simchain = rulechain.find_next_applicable_rule(query, heap, engine.similarity, simchain, module, nargs) #print(rules) return rules
def test_traceback_in_if(): e = get_engine(""" h(y). g(a). g(_) :- throw(foo). f(X, Y) :- (g(X) -> X = 1 ; X = 2), h(Y). """) error = get_uncaught_error("f(1, Y).", e) sig_g = Signature.getsignature("g", 1) sig_f = Signature.getsignature("f", 2) m = e.modulewrapper rule_f = m.user_module.lookup(sig_f).rulechain rule_g = m.user_module.lookup(sig_g).rulechain.next tb = error.traceback assert tb.rule is rule_f assert tb.next.rule is rule_g
def generate_class(cname, fname, n_args): from rpython.rlib.unroll import unrolling_iterable arg_iter = unrolling_iterable(range(n_args)) parent = callables['Abstract', n_args] assert parent is not None signature = Signature.getsignature(fname, n_args) class specific_class(parent): if n_args == 0: TYPE_STANDARD_ORDER = Atom.TYPE_STANDARD_ORDER else: TYPE_STANDARD_ORDER = Term.TYPE_STANDARD_ORDER def __init__(self, term_name, args, signature): parent._init_values(self, args) assert self.name() == term_name assert args is None or len(args) == n_args def name(self): return fname def signature(self): return signature def _make_new(self, name, signature): cls = specific_class return cls(name, None, signature) specific_class.__name__ = cname return specific_class
def test_traceback_in_if(): e = get_engine(""" h(y). g(a). g(_) :- throw(foo). f(X, Y) :- (g(X) -> X = 1 ; X = 2), h(Y). """) error = get_uncaught_error("f(1, Y).", e) sig_g = Signature.getsignature("g", 1) sig_f = Signature.getsignature("f", 2) m = e.modulewrapper rule_f = m.user_module.lookup(sig_f).rulechain rule_g = m.user_module.lookup(sig_g).rulechain.next tb = error.traceback assert tb.rule is rule_f assert tb.next.rule is rule_g
def isFactInKB(factPredicate, factArgs, factQuery, prolog, predicateDict): sig = Signature.getsignature(str(factPredicate), len(factArgs)) isBuiltin = prolog.get_builtin(sig) assert (not isBuiltin), 'we should have already checked this' factInKB = False query = '{0}({1}).'.format( factPredicate, ','.join(['X_{0}'.format(i) for i in range(len(factArgs))])) if prologPath == '/testnet' or prologPath == '/proofspyrolog': proof = collect_all(prolog, query, [], [], [], []) elif prologPath == '/spyrolog': proof = collect_all(prolog, query, [], [], []) for vGrounding in proof: groundings = vGrounding[0] args = set() for variable, grounding in groundings.iteritems(): if hasattr(grounding, 'name'): args.add(grounding.name()) elif hasattr(grounding, 'num'): args.add(grounding.num) else: print 'dir:', dir(grounding) raise AttributeError if not set(factArgs).difference(args): factInKB = True break return factInKB
def build(term_name, args=None, signature=None, heap=None, cache=True): if args is None: args = [] if heap is not None: # perform variable shunting: # remove variables that are not needed because they are bound # already and cannot be backtracked for i in range(len(args)): arg = args[i] if (isinstance(arg, Var) and arg.getbinding() is not None and arg.created_after_choice_point is heap): args[i] = arg.getbinding() if len(args) == 0: if cache: return Atom.newatom(term_name, signature) return Atom(term_name, signature) else: if signature is None: if cache: signature = Signature.getsignature(term_name, len(args)) else: signature = Signature(term_name, len(args)) else: assert signature.numargs == len(args) assert isinstance(signature, Signature) cls = Callable._find_specialized_class(term_name, len(args)) if cls is not None: return cls(term_name, args, signature) cls = Callable._find_specialized_class('Term', len(args)) if cls is not None: return cls(term_name, args, signature) return Term(term_name, args, signature)
def test_numeral(): from prolog.interpreter.term import Callable, Atom, BindingVar from prolog.interpreter.continuation import Engine t = parse_file(""" numeral(null). % end of line comment numeral(succ(X)) :- numeral(X). % another one add_numeral(X, null, X). add_numeral(X, succ(Y), Z) :- add_numeral(succ(X), Y, Z). greater_than(succ(null), null). greater_than(succ(X), null) :- greater_than(X, null). greater_than(succ(X), succ(Y)) :- greater_than(X, Y). """) builder = TermBuilder() facts = builder.build(t) e = Engine() m = e.modulewrapper for fact in facts: print fact e.add_rule(fact) assert m.modules["user"].lookup(Signature.getsignature("add_numeral", 3)).rulechain.head.argument_at(1).name() == "null" four = Callable.build("succ", [Callable.build("succ", [Callable.build("succ", [Callable.build("succ", [Callable.build("null")])])])]) e.run_query_in_current(parse_query_term("numeral(succ(succ(null))).")) term = parse_query_term( """add_numeral(succ(succ(null)), succ(succ(null)), X).""") e.run_query_in_current(term) hp = Heap() var = BindingVar().dereference(hp) # does not raise var.unify(four, hp) term = parse_query_term( """greater_than(succ(succ(succ(null))), succ(succ(null))).""") e.run_query_in_current(term)
def newatom(name, signature=None): if signature is None: signature = Signature.getsignature(name, 0) result = Atom.cache.get(signature, None) if result is not None: return result Atom.cache[signature] = result = Atom(name, signature) return result
def add_module(self, name, exports = []): mod = Module(name) for export in exports: mod.exports.append(Signature.getsignature( *unwrap_predicate_indicator(export))) self.current_module = mod self.modules[name] = mod self.version = VersionTag()
def newatom(name, signature=None): if signature is None: signature = Signature.getsignature(name, 0) result = Atom.cache.get(signature, None) if result is not None: return result Atom.cache[signature] = result = Atom(name, signature) return result
def add_module(self, name, exports=[]): mod = Module(name) for export in exports: mod.exports.append( Signature.getsignature(*unwrap_predicate_indicator(export))) self.current_module = mod self.modules[name] = mod self.version = VersionTag()
def test_module_exports(): e = get_engine(""" :- module(m, [g/2]). g(a, b). f(c, d, e). """) exports = e.modulewrapper.modules["m"].exports assert len(exports) == 1 and exports[0].eq(Signature("g", 2))
def impl_use_module_with_importlist(engine, heap, module, path, imports): importlist = [] for sigatom in imports: importlist.append( Signature.getsignature(*unwrap_predicate_indicator(sigatom))) if isinstance(path, Atom): handle_use_module(engine, heap, module, path, importlist) else: handle_use_module_with_library(engine, heap, module, path, importlist)
def impl_use_module_with_importlist(engine, heap, module, path, imports): importlist = [] for sigatom in imports: importlist.append(Signature.getsignature( *unwrap_predicate_indicator(sigatom))) if isinstance(path, Atom): handle_use_module(engine, heap, module, path, importlist) else: handle_use_module_with_library(engine, heap, module, path, importlist)
def test_lookup(): e = get_engine(""" :- use_module(m). f(a) :- g(a, b). """, m = """ :- module(m, [g/2]). g(a, b). h(w). """) f_sig = Signature.getsignature("f", 1) g_sig = Signature.getsignature("g", 2) h_sig = Signature.getsignature("h", 1) user = e.modulewrapper.modules["user"] m = e.modulewrapper.modules["m"] assert user.lookup(g_sig) == m.functions[g_sig] assert user.lookup(h_sig).rulechain is None assert m.lookup(g_sig) == m.functions[g_sig] assert m.lookup(f_sig).rulechain is None assert m.lookup(h_sig) == m.functions[h_sig]
def test_lookup(): e = get_engine(""" :- use_module(m). f(a) :- g(a, b). """, m=""" :- module(m, [g/2]). g(a, b). h(w). """) f_sig = Signature.getsignature("f", 1) g_sig = Signature.getsignature("g", 2) h_sig = Signature.getsignature("h", 1) user = e.modulewrapper.modules["user"] m = e.modulewrapper.modules["m"] assert user.lookup(g_sig) == m.functions[g_sig] assert user.lookup(h_sig).rulechain is None assert m.lookup(g_sig) == m.functions[g_sig] assert m.lookup(f_sig).rulechain is None assert m.lookup(h_sig) == m.functions[h_sig]
def test_discard_useless_env_suffix(): e = get_engine(""" f(h(A), A, B, C) :- g(B), h(D), h1(D), h(E). """) # classes of variables: # just in head: A (needs index at the end of env) # both: B (needs index at the beginning of env) # singletons head: C (-1) # singletons body: E (-1, XXX currently not optimized) # just in body: D (needs index at end of env, appended after matching head) func = e.modulewrapper.current_module.lookup(Signature.getsignature( "f", 4))
def test_source_range(): e = get_engine(""" f(a) :- a. f(b) :- b. a. b. """) func = e.modulewrapper.current_module.lookup(Signature.getsignature("f", 1)) assert func.rulechain.line_range == [1, 2] assert func.rulechain.next.line_range == [2, 4] assert func.rulechain.file_name == "<unknown>" assert func.rulechain.source == "f(a) :- a." assert func.rulechain.next.source == "f(b) :-\n b."
def test_source_range(): e = get_engine(""" f(a) :- a. f(b) :- b. a. b. """) func = e.modulewrapper.current_module.lookup(Signature.getsignature( "f", 1)) assert func.rulechain.line_range == [1, 2] assert func.rulechain.next.line_range == [2, 4] assert func.rulechain.file_name == "<unknown>" assert func.rulechain.source == "f(a) :- a." assert func.rulechain.next.source == "f(b) :-\n b."
def impl_abolish(engine, heap, module, predicate): modname = None if predicate.signature().eq(prefixsig): modname, predicate = unpack_modname_and_predicate(predicate) name, arity = helper.unwrap_predicate_indicator(predicate) if arity < 0: error.throw_domain_error("not_less_than_zero", term.Number(arity)) signature = Signature.getsignature(name, arity) if signature.get_extra("builtin"): error.throw_permission_error("modify", "static_procedure", predicate) if modname is not None: module = engine.modulewrapper.get_module(modname, predicate) try: del module.functions[signature] except KeyError: pass
def impl_abolish(engine, heap, module, predicate): modname = None if predicate.signature().eq(prefixsig): modname, predicate = unpack_modname_and_predicate(predicate) name, arity = helper.unwrap_predicate_indicator(predicate) if arity < 0: error.throw_domain_error("not_less_than_zero", term.Number(arity)) signature = Signature.getsignature(name, arity) if signature.get_extra("builtin"): error.throw_permission_error("modify", "static_procedure", predicate) if modname is not None: module = engine.modulewrapper.get_module(modname, predicate) try: del module.functions[signature] except KeyError: pass
def find_applicable_rule(self, query, heap=None, similarity=None, simchain=[], module=None, nargs=0): # This method should do some quick filtering on the rules to filter out # those that cannot match query. Here is where e.g. indexing should # occur. while ((self is not None) or (simchain != [])): #print "Entering loop", self, "simchain", simchain # if self is None go to next rule in simchain if (self == None): #print("Moving to next rulechain in simchain...") name = simchain[0] simchain = simchain[1:] signature = Signature.getsignature(name, nargs) function = module.lookup(signature) self = function.rulechain if (self == None): continue #print(self.scores[0] * heap.predicate_score) #print(similarity.threshold) if (self.scores[0] * heap.predicate_score >= similarity.threshold): if self.headargs is not None: if (len(self.headargs) != query.argument_count()): self = self.next continue assert isinstance(query, Callable) for i in range(len(self.headargs)): arg2 = self.headargs[i] arg1 = query.argument_at(i) if not arg2.quick_unify_check(arg1, similarity=similarity): break else: return self, simchain else: return self, simchain self = self.next return None, []
def generate_class(cname, fname, n_args, immutable=True): from rpython.rlib.unroll import unrolling_iterable arg_iter = unrolling_iterable(range(n_args)) parent = callables['Abstract', n_args] if not immutable: parent = parent.mutable_version assert parent is not None signature = Signature.getsignature(fname, n_args) class specific_class(parent): if n_args == 0: TYPE_STANDARD_ORDER = Atom.TYPE_STANDARD_ORDER else: TYPE_STANDARD_ORDER = Term.TYPE_STANDARD_ORDER def __init__(self, term_name, args, signature): parent._init_values(self, args) assert self.name() == term_name assert args is None or len(args) == n_args def name(self): return fname def signature(self): return signature def _make_new(self, name, signature): cls = specific_class return cls(name, None, signature) if immutable: def _make_new_mutable(self, name, signature): cls = mutable_version return cls(name, None, signature) else: _make_new_mutable = _make_new if immutable: mutable_version = specific_class.mutable_version = generate_class( cname, fname, n_args, False) specific_class.__name__ = cname + "Mutable" * (not immutable) return specific_class
def test_numeral(): from prolog.interpreter.term import Callable, Atom, BindingVar from prolog.interpreter.continuation import Engine t = parse_file(""" numeral(null). % end of line comment numeral(succ(X)) :- numeral(X). % another one add_numeral(X, null, X). add_numeral(X, succ(Y), Z) :- add_numeral(succ(X), Y, Z). greater_than(succ(null), null). greater_than(succ(X), null) :- greater_than(X, null). greater_than(succ(X), succ(Y)) :- greater_than(X, Y). """) builder = TermBuilder() facts = builder.build(t) e = Engine() m = e.modulewrapper for fact in facts: print fact e.add_rule(fact) assert m.modules["user"].lookup(Signature.getsignature( "add_numeral", 3)).rulechain.head.argument_at(1).name() == "null" four = Callable.build("succ", [ Callable.build("succ", [ Callable.build("succ", [Callable.build("succ", [Callable.build("null")])]) ]) ]) e.run_query_in_current(parse_query_term("numeral(succ(succ(null))).")) term = parse_query_term( """add_numeral(succ(succ(null)), succ(succ(null)), X).""") e.run_query_in_current(term) hp = Heap() var = BindingVar().dereference(hp) # does not raise var.unify(four, hp) term = parse_query_term( """greater_than(succ(succ(succ(null))), succ(succ(null))).""") e.run_query_in_current(term)
def find_next_applicable_rule(self, query, heap=None, similarity=None, simchain=[], module=None, nargs=0): self = self.next if self is None: while (simchain != []): #print("Moving to next rulechain in simchain...") name = simchain[0] simchain = simchain[1:] signature = Signature.getsignature(name, nargs) function = module.lookup(signature) self = function.rulechain if (self is not None): return self.find_applicable_rule(query, heap, similarity, simchain, module, nargs) return None, [] return self.find_applicable_rule(query, heap, similarity, simchain, module, nargs)
def test_exception_knows_builtin_signature(): e = get_engine(""" f(X, Y) :- atom_length(X, Y). """) error = get_uncaught_error("f(1, Y).", e) assert error.sig_context == Signature.getsignature("atom_length", 2)
def __init__(self, name, signature=None): if signature is None: signature = Signature(name, 0) Callable.__init__(self) self._signature = signature
import py from prolog.interpreter.parsing import TermBuilder from prolog.interpreter import helper, term, error from prolog.interpreter.signature import Signature from prolog.interpreter.arithmetic import eval_arithmetic from rpython.rlib.objectmodel import we_are_translated from rpython.rlib import jit import inspect Signature.register_extr_attr("builtin") jit_modules = ["control"] class Builtin(object): _immutable_ = True def __init__(self, function, name, numargs, signature): self.function = function self.name = name self.numargs = numargs self.signature = signature def call(self, engine, query, rule, scont, fcont, heap): try: return self.function(engine, query, rule, scont, fcont, heap) except error.CatchableError as e: e.sig_context = self.signature raise
from prolog.builtin.register import expose_builtin from prolog.interpreter import continuation from prolog.interpreter.term import AttVar, Var, Callable, Atom from prolog.interpreter.error import UnificationFailed,\ throw_representation_error, throw_instantiation_error from prolog.interpreter.helper import wrap_list, is_term, unwrap_list from prolog.interpreter.signature import Signature from prolog.builtin.term_variables import term_variables conssig = Signature.getsignature(".", 2) @expose_builtin("attvar", unwrap_spec=["obj"]) def impl_attvar(engine, heap, obj): if not isinstance(obj, AttVar): raise UnificationFailed() if obj.is_empty(): raise UnificationFailed() @expose_builtin("put_attr", unwrap_spec=["obj", "atom", "obj"]) def impl_put_attr(engine, heap, var, attr, value): if isinstance(var, AttVar): old_value, _ = var.get_attribute(attr) var.add_attribute(attr, value) _, index = var.get_attribute(attr) heap.trail_new_attr(var, index, old_value) elif isinstance(var, Var): attvar = heap.new_attvar() attvar.add_attribute(attr, value) var.unify(attvar, heap) else: throw_representation_error("put_attr/3",
import py from prolog.interpreter import helper, term, error from prolog.interpreter.signature import Signature from prolog.builtin.register import expose_builtin # ___________________________________________________________________ # database prefixsig = Signature.getsignature(":", 2) implsig = Signature.getsignature(":-", 2) def unpack_modname_and_predicate(rule): if helper.is_numeric(rule.argument_at(0)): error.throw_domain_error("atom", rule.argument_at(0)) assert 0, "unreachable" mod = rule.argument_at(0) indicator = rule.argument_at(1) if not isinstance(mod, term.Atom): raise error.UnificationFailed() assert 0, "unreachable" return mod.name(), indicator @expose_builtin("abolish", unwrap_spec=["callable"], needs_module=True) def impl_abolish(engine, heap, module, predicate): modname = None if predicate.signature().eq(prefixsig): modname, predicate = unpack_modname_and_predicate(predicate) name, arity = helper.unwrap_predicate_indicator(predicate) if arity < 0: error.throw_domain_error("not_less_than_zero", term.Number(arity)) signature = Signature.getsignature(name, arity)
def getDependencyTupleTraverse(analyzedStatement, namedEntities, prolog): def removeRepeats(lst): seen = set() seen_add = seen.add noRepeats = [x for x in lst if not (x in seen or seen_add(x))] return noRepeats predicate = '' arguments = [] statementObj = list(analyzedStatement.sents)[0] rootToken = statementObj.root if rootToken.pos_ == 'VERB': predicate = rootToken.lemma_.lower() hasVerb = 0 iterateArgs = ['', '', '', '', '', ''] for token in analyzedStatement: if token.pos_ == 'VERB': hasVerb = 1 if predicate == '': if token.pos_ == 'VERB' and token.dep_ != 'aux': predicate = token.lemma_.lower() if 'obj' in token.dep_: if iterateArgs[1] == '': iterateArgs[1] = token.text.lower() else: if token.dep_ == 'dobj': iterateArgs[1] = token.text.lower() elif 'subj' in token.dep_: iterateArgs[0] = token.text.lower() elif 'comp' in token.dep_: iterateArgs[2] = token.text.lower() elif 'mod' in token.dep_: iterateArgs[3] = token.text.lower() elif 'conj' in token.dep_: iterateArgs[4] = token.text.lower() elif 'oprd' in token.dep_: iterateArgs[5] = token.text.lower() if predicate == '': for token in analyzedStatement: if hasVerb and token.pos_ == 'VERB': predicate = token.lemma_.lower() break elif (not hasVerb) and token.dep_ == 'ROOT': predicate = token.text.lower() break for child in rootToken.children: if child.pos_ != 'PART' and child.pos_ not in ['PUNC', 'SPACE']: ctext = child.text.lower() arguments.append(ctext) else: pass spacyArguments = [] for chunk in analyzedStatement.noun_chunks: np = chunk.text.lower().replace(' ', '_') if chunk.root.head.text.lower() != predicate and \ chunk.root.head.pos_ != 'VERB' and \ chunk.root.head.text.lower() not in np: np = chunk.root.head.text.lower().replace(' ', '_') + '_' + np spacyArguments.append(np) for arg in iterateArgs: if arg != predicate and not any( [arg in sargs for sargs in spacyArguments]): spacyArguments.append(arg) spacyArguments = removeRepeats(spacyArguments) for ne in namedEntities: used = 0 for ind, arg in enumerate(spacyArguments): if arg in ne[0] or ne[0] in arg: used = 1 break if used == 0 and ne[0] not in spacyArguments: spacyArguments.append(ne[0].replace(' ', '_')) spacyArguments = removeRepeats(spacyArguments) if VERBOSE: print('spacyArguments: {0}'.format(spacyArguments)) logging.debug('spacyArguments: {0}'.format(spacyArguments)) sig = Signature.getsignature(str(predicate), len(spacyArguments)) isBuiltin = prolog.get_builtin(sig) if isBuiltin or str(predicate) == 'close' or str(predicate) == 'open': predicate = predicate + '_new' statementTupleSpacy = '{0}({1})'.format(predicate, ','.join(spacyArguments)) if VERBOSE: print 'statementTupleSpacy:', statementTupleSpacy statementTuple = '{0}({1})'.format(predicate, ','.join(arguments)) if predicate == '': logging.error('predicate name cannot be empty, debugging needed') assert predicate, 'predicate name cannot be empty, debugging needed' return [statementTupleSpacy, predicate, spacyArguments]
""" Helper functions for dealing with prolog terms""" from prolog.interpreter import term from prolog.interpreter import error from prolog.interpreter.signature import Signature from rpython.rlib import jit from prolog.interpreter.stream import PrologOutputStream, PrologInputStream,\ PrologStream conssig = Signature.getsignature(".", 2) nilsig = Signature.getsignature("[]", 0) emptylist = term.Callable.build("[]") def wrap_list(python_list): curr = emptylist for i in range(len(python_list) - 1, -1, -1): curr = term.Callable.build(".", [python_list[i], curr]) return curr @jit.unroll_safe def unwrap_list(prolog_list): # Grrr, stupid JIT result = [None] used = 0 curr = prolog_list while isinstance(curr, term.Callable) and curr.signature().eq(conssig): if used == len(result): nresult = [None] * (used * 2)
from subprocess import call from rpython.rlib import jit from rpython.rlib.objectmodel import we_are_translated, specialize from prolog.interpreter import error from prolog.interpreter import helper from prolog.interpreter.term import Term, Atom, BindingVar, Callable, Var from prolog.interpreter.function import Function, Rule from prolog.interpreter.heap import Heap from prolog.interpreter.signature import Signature from prolog.interpreter.module import Module, ModuleWrapper from prolog.interpreter.helper import unwrap_predicate_indicator from prolog.interpreter.stream import StreamWrapper from prolog.interpreter.small_list import inline_small_list from prolog.interpreter.similarity import Similarity Signature.register_extr_attr("function", engine=True) # ___________________________________________________________________ # JIT stuff def get_printable_location(rule, sconttype): if rule: s = rule.signature.string() else: s = "No rule" return "%s %s" % (s, sconttype) def get_jitcell_at(where, rule): # XXX can be vastly simplified
import py import math from prolog.interpreter.parsing import TermBuilder from prolog.interpreter import helper, term, error from prolog.interpreter.signature import Signature from prolog.interpreter.error import UnificationFailed from rpython.rlib.rarithmetic import intmask, ovfcheck_float_to_int from rpython.rlib.unroll import unrolling_iterable from rpython.rlib import jit, rarithmetic from rpython.rlib.rbigint import rbigint Signature.register_extr_attr("arithmetic") def eval_arithmetic(engine, obj): result = obj.eval_arithmetic(engine) return make_int(result) class CodeCollector(object): def __init__(self): self.code = [] self.blocks = [] def emit(self, line): for line in line.split("\n"): self.code.append(" " * (4 * len(self.blocks)) + line) def start_block(self, blockstarter): assert blockstarter.endswith(":") self.emit(blockstarter) self.blocks.append(blockstarter)
import py from prolog.builtin.register import expose_builtin from prolog.interpreter.term import Atom, Callable, Var, Term, Number from prolog.interpreter import error from prolog.builtin.sourcehelper import get_source from prolog.interpreter import continuation from prolog.interpreter.helper import is_term, unwrap_predicate_indicator from prolog.interpreter.signature import Signature meta_args = list("0123456789:?+-") libsig = Signature.getsignature("library", 1) andsig = Signature.getsignature(",", 2) @expose_builtin("module", unwrap_spec=["atom", "list"]) def impl_module(engine, heap, name, exports): engine.modulewrapper.add_module(name, exports) def handle_use_module_with_library(engine, heap, module, path, imports=None): import os import os.path from prolog.builtin.sourcehelper import get_filehandle newpath = None if path.signature().eq(libsig): arg = path.argument_at(0) if isinstance(arg, Var) or not isinstance(arg, Atom): # XXX throw different errors error.throw_instantiation_error() modulename = arg.name() assert modulename is not None for libpath in engine.modulewrapper.libs: temppath = os.path.join(libpath, modulename) try:
from prolog.interpreter import helper, term, error, continuation from prolog.builtin.register import expose_builtin from prolog.interpreter.signature import Signature ifsig = Signature.getsignature("->", 2) cutsig = Signature.getsignature("!", 0) FAILATOM = term.Callable.build("fail") TRUEATOM = term.Callable.build("true") # ___________________________________________________________________ # control predicates @expose_builtin("fail", unwrap_spec=[]) def impl_fail(engine, heap): raise error.UnificationFailed() @expose_builtin("true", unwrap_spec=[]) def impl_true(engine, heap): return @expose_builtin("repeat", unwrap_spec=[], handles_continuation=True) def impl_repeat(engine, heap, scont, fcont): return scont, RepeatContinuation(engine, scont, fcont, heap), heap.branch() class RepeatContinuation(continuation.FailureContinuation): def fail(self, heap): heap = heap.revert_upto(self.undoheap) return self.nextcont, self, heap @expose_builtin("!", unwrap_spec=[], handles_continuation=True) def impl_cut(engine, heap, scont, fcont):
import py from prolog.interpreter import helper, term, error from prolog.interpreter.signature import Signature from prolog.builtin.register import expose_builtin # ___________________________________________________________________ # database prefixsig = Signature.getsignature(":", 2) implsig = Signature.getsignature(":-", 2) def unpack_modname_and_predicate(rule): if helper.is_numeric(rule.argument_at(0)): error.throw_domain_error("atom", rule.argument_at(0)) assert 0, "unreachable" mod = rule.argument_at(0) indicator = rule.argument_at(1) if not isinstance(mod, term.Atom): raise error.UnificationFailed() assert 0, "unreachable" return mod.name(), indicator @expose_builtin("abolish", unwrap_spec=["callable"], needs_module=True) def impl_abolish(engine, heap, module, predicate): modname = None if predicate.signature().eq(prefixsig): modname, predicate = unpack_modname_and_predicate(predicate) name, arity = helper.unwrap_predicate_indicator(predicate) if arity < 0:
import py from prolog.interpreter.parsing import TermBuilder from prolog.interpreter import helper, term, error from prolog.interpreter.signature import Signature from prolog.interpreter.arithmetic import eval_arithmetic from rpython.rlib.objectmodel import we_are_translated from rpython.rlib import jit import inspect Signature.register_extr_attr("builtin") jit_modules = ["control"] class Builtin(object): _immutable_ = True def __init__(self, function, name, numargs, signature): self.function = function self.name = name self.numargs = numargs self.signature = signature def call(self, engine, query, rule, scont, fcont, heap): try: return self.function(engine, query, rule, scont, fcont, heap) except error.CatchableError as e: e.sig_context = self.signature raise def _freeze_(self):
from prolog.interpreter.term import Callable, Atom, Var from prolog.interpreter.memo import EnumerationMemo from prolog.interpreter.signature import Signature from rpython.rlib import jit, objectmodel, unroll from prolog.interpreter.helper import is_callable # XXX needs tests cutsig = Signature.getsignature("!", 0) prefixsig = Signature.getsignature(":", 2) class Rule(object): _immutable_ = True _immutable_fields_ = ["headargs[*]", "groundargs[*]"] _attrs_ = [ 'next', 'head', 'headargs', 'groundargs', 'contains_cut', 'body', 'env_size_shared', 'env_size_body', 'env_size_head', 'signature', 'module', 'file_name', 'line_range', 'source' ] unrolling_attrs = unroll.unrolling_iterable(_attrs_) def __init__(self, head, body, module, next=None): from prolog.interpreter import helper head = head.dereference(None) assert isinstance(head, Callable) memo = EnumerationMemo() self.head = h = head.enumerate_vars(memo) memo.in_head = False if h.argument_count() > 0: self.headargs = h.arguments() # an argument is ground if enumeration left it unchanged, because
import os import string from prolog.interpreter.term import Float, Number, Var, Atom, Callable, AttVar from prolog.interpreter import error, helper, parsing from prolog.builtin.register import expose_builtin from prolog.interpreter.signature import Signature from prolog.interpreter.stream import PrologStream conssig = Signature.getsignature(".", 2) nilsig = Signature.getsignature("[]", 0) tuplesig = Signature.getsignature(",", 2) class TermFormatter(object): def __init__(self, engine, quoted=False, max_depth=0, ignore_ops=False): self.engine = engine self.quoted = quoted self.max_depth = max_depth self.ignore_ops = ignore_ops self.curr_depth = 0 self._make_reverse_op_mapping() self.var_to_number = {} def from_option_list(engine, options): # XXX add numbervars support quoted = False max_depth = 0 ignore_ops = False number_vars = False
def test_exception_knows_builtin_signature(): e = get_engine(""" f(X, Y) :- atom_length(X, Y). """) error = get_uncaught_error("f(1, Y).", e) assert error.sig_context == Signature.getsignature("atom_length", 2)
def signature(self): return Signature(self.name(), 123)
import py import time from rpython.rlib import jit from rpython.rlib.objectmodel import we_are_translated, specialize from prolog.interpreter import error from prolog.interpreter import helper from prolog.interpreter.term import Term, Atom, BindingVar, Callable, Var from prolog.interpreter.function import Function, Rule from prolog.interpreter.heap import Heap from prolog.interpreter.signature import Signature from prolog.interpreter.module import Module, ModuleWrapper from prolog.interpreter.helper import unwrap_predicate_indicator from prolog.interpreter.stream import StreamWrapper Signature.register_extr_attr("function", engine=True) # ___________________________________________________________________ # JIT stuff def get_printable_location(rule, sconttype): if rule: s = rule.signature.string() else: s = "No rule" return "%s %s" % (s, sconttype) def get_jitcell_at(where, rule): # XXX can be vastly simplified return rule.jit_cells.get(where, None) def set_jitcell_at(newcell, where, rule):
""" Helper functions for dealing with prolog terms""" from prolog.interpreter import term from prolog.interpreter import error from prolog.interpreter.signature import Signature from rpython.rlib import jit from prolog.interpreter.stream import PrologOutputStream, PrologInputStream,\ PrologStream conssig = Signature.getsignature(".", 2) nilsig = Signature.getsignature("[]", 0) emptylist = term.Callable.build("[]") def wrap_list(python_list): curr = emptylist for i in range(len(python_list) - 1, -1, -1): curr = term.Callable.build(".", [python_list[i], curr]) return curr @jit.unroll_safe def unwrap_list(prolog_list): # Grrr, stupid JIT result = [None] used = 0 curr = prolog_list while isinstance(curr, term.Callable) and curr.signature().eq(conssig): if used == len(result): nresult = [None] * (used * 2) for i in range(used): nresult[i] = result[i]
def make_wrapper(func, name, unwrap_spec=[], handles_continuation=False, translatable=True, needs_module=False, needs_rule=False): numargs = len(unwrap_spec) if isinstance(name, list): expose_as = name name = name[0] else: expose_as = [name] if not name.isalnum(): name = func.func_name orig_funcargs = inspect.getargs(func.func_code)[0] funcname = "wrap_%s_%s" % (name, numargs) code = ["def %s(engine, query, rule, scont, fcont, heap):" % (funcname, )] code.append(" module = rule.module") if not translatable: code.append(" if we_are_translated():") code.append(" raise error.UncatchableError('%s does not work in translated version')" % (name, )) subargs = ["engine", "heap"] assert orig_funcargs[0] == "engine" assert orig_funcargs[1] == "heap" code.append(" assert isinstance(query, term.Callable)") for i, spec in enumerate(unwrap_spec): varname = "var%s" % (i, ) subargs.append(varname) if spec in ("obj", "callable", "int", "atom", "arithmetic", "instream", "outstream", "stream", "list"): code.append(" %s = query.argument_at(%s).dereference(heap)" % (varname, i)) if spec in ("int", "atom", "arithmetic", "list", "instream", "outstream", "stream"): code.append( " if isinstance(%s, term.Var):" % (varname,)) code.append( " error.throw_instantiation_error()") if spec == "obj": pass elif spec == "callable": code.append( " if not isinstance(%s, term.Callable):" % (varname,)) code.append( " if isinstance(%s, term.Var):" % (varname,)) code.append( " error.throw_instantiation_error()") code.append( " error.throw_type_error('callable', %s)" % (varname,)) elif spec == "raw": code.append(" %s = query.argument_at(%s)" % (varname, i)) elif spec == "int": code.append(" %s = helper.unwrap_int(%s)" % (varname, varname)) elif spec == "atom": code.append(" %s = helper.unwrap_atom(%s)" % (varname, varname)) elif spec == "arithmetic": code.append(" %s = eval_arithmetic(engine, %s)" % (varname, varname)) elif spec == "list": code.append(" %s = helper.unwrap_list(%s)" % (varname, varname)) elif spec == "stream": code.append(" %s = helper.unwrap_stream(engine, %s)" % (varname, varname)) elif spec == "instream": code.append(" %s = helper.unwrap_instream(engine, %s)" % (varname, varname)) elif spec == "outstream": code.append(" %s = helper.unwrap_outstream(engine, %s)" % (varname, varname)) else: assert 0, "not implemented " + spec if needs_module: subargs.insert(2, "module") assert orig_funcargs[2] == "module" if needs_rule: subargs.insert(2, "rule") assert orig_funcargs[2] == "rule" if handles_continuation: subargs.append("scont") subargs.append("fcont") assert orig_funcargs[subargs.index("scont")] == "scont" assert orig_funcargs[subargs.index("fcont")] == "fcont" call = " result = %s(%s)" % (func.func_name, ", ".join(subargs)) code.append(call) if not handles_continuation: code.append(" return scont, fcont, heap") else: code.append(" return result") used_globals = ["helper", "error", "term", "eval_arithmetic"] miniglobals = {key: globals()[key] for key in used_globals} miniglobals[func.func_name] = func exec py.code.Source("\n".join(code)).compile() in miniglobals for name in expose_as: signature = Signature.getsignature(name, numargs) b = Builtin(miniglobals[funcname], funcname, numargs, signature) signature.set_extra("builtin", b) return func
def make_wrapper(func, name, unwrap_spec=[], handles_continuation=False, translatable=True, needs_module=False, needs_rule=False): numargs = len(unwrap_spec) if isinstance(name, list): expose_as = name name = name[0] else: expose_as = [name] if not name.isalnum(): name = func.func_name orig_funcargs = inspect.getargs(func.func_code)[0] funcname = "wrap_%s_%s" % (name, numargs) code = ["def %s(engine, query, rule, scont, fcont, heap):" % (funcname, )] code.append(" module = rule.module") if not translatable: code.append(" if we_are_translated():") code.append( " raise error.UncatchableError('%s does not work in translated version')" % (name, )) subargs = ["engine", "heap"] assert orig_funcargs[0] == "engine" assert orig_funcargs[1] == "heap" code.append(" assert isinstance(query, term.Callable)") for i, spec in enumerate(unwrap_spec): varname = "var%s" % (i, ) subargs.append(varname) if spec in ("obj", "callable", "int", "atom", "arithmetic", "instream", "outstream", "stream", "list"): code.append(" %s = query.argument_at(%s).dereference(heap)" % (varname, i)) if spec in ("int", "atom", "arithmetic", "list", "instream", "outstream", "stream"): code.append(" if isinstance(%s, term.Var):" % (varname, )) code.append(" error.throw_instantiation_error()") if spec == "obj": pass elif spec == "callable": code.append(" if not isinstance(%s, term.Callable):" % (varname, )) code.append(" if isinstance(%s, term.Var):" % (varname, )) code.append(" error.throw_instantiation_error()") code.append(" error.throw_type_error('callable', %s)" % (varname, )) elif spec == "raw": code.append(" %s = query.argument_at(%s)" % (varname, i)) elif spec == "int": code.append(" %s = helper.unwrap_int(%s)" % (varname, varname)) elif spec == "atom": code.append(" %s = helper.unwrap_atom(%s)" % (varname, varname)) elif spec == "arithmetic": code.append(" %s = eval_arithmetic(engine, %s)" % (varname, varname)) elif spec == "list": code.append(" %s = helper.unwrap_list(%s)" % (varname, varname)) elif spec == "stream": code.append(" %s = helper.unwrap_stream(engine, %s)" % (varname, varname)) elif spec == "instream": code.append(" %s = helper.unwrap_instream(engine, %s)" % (varname, varname)) elif spec == "outstream": code.append(" %s = helper.unwrap_outstream(engine, %s)" % (varname, varname)) else: assert 0, "not implemented " + spec if needs_module: subargs.insert(2, "module") assert orig_funcargs[2] == "module" if needs_rule: subargs.insert(2, "rule") assert orig_funcargs[2] == "rule" if handles_continuation: subargs.append("scont") subargs.append("fcont") assert orig_funcargs[subargs.index("scont")] == "scont" assert orig_funcargs[subargs.index("fcont")] == "fcont" call = " result = %s(%s)" % (func.func_name, ", ".join(subargs)) code.append(call) if not handles_continuation: code.append(" return scont, fcont, heap") else: code.append(" return result") used_globals = ["helper", "error", "term", "eval_arithmetic"] miniglobals = {key: globals()[key] for key in used_globals} miniglobals[func.func_name] = func exec py.code.Source("\n".join(code)).compile() in miniglobals for name in expose_as: signature = Signature.getsignature(name, numargs) b = Builtin(miniglobals[funcname], funcname, numargs, signature) signature.set_extra("builtin", b) return func