def pred_reverse(rules, term, env): if term.arity != 2: return False left_term = terms.expand(term.args[0], env) right_term = terms.expand(term.args[1], env) if terms.is_bound(left_term) and terms.is_bound(right_term): if not terms.is_list(left_term): return False left_list = list(left_term) left_list.reverse() left_term = tuple(left_list) return left_term == right_term if terms.is_bound(left_term): if not terms.is_list(left_term): return False left_list = list(left_term) left_list.reverse() left_term = tuple(left_list) return terms.unify(left_term, {}, right_term, env) if terms.is_bound(right_term): if not terms.is_list(right_term): return False right_list = list(right_term) right_list.reverse() right_term = tuple(right_list) return terms.unify(right_term, {}, left_term, env) return False
def pred_extract(rules, term, env): if term.arity != 3: return False left = terms.expand(term.args[0], env) middle = terms.expand(term.args[1], env) right = terms.expand(term.args[2], env) if terms.is_unbound(middle): return False if not terms.is_list(middle): return False if terms.is_bound(right): # l,m,r const if not terms.is_list(right): return False if terms.is_bound(left): for (i, e) in enumerate(middle): if e == left: rl = middle[0:i] + middle[i + 1:] return rl == right return False # r,m const l variable r = [] for (i, e) in enumerate(middle): env_copy = env.copy() if terms.unify(e, env, left, env_copy): rl = middle[0:i] + middle[i + 1:] if rl == right: r.append(env_copy) return r # right variable if terms.is_unbound(left): # r,l var m const r = [] for (i, e) in enumerate(middle): env_copy = env.copy() if terms.unify(e, env, left, env_copy): rl = middle[0:i] + middle[i + 1:] if terms.unify(rl, env, right, env_copy): r.append(env_copy) return tuple(r) # l,m const r var r = [] for (i, e) in enumerate(middle): if e == left: rl = middle[0:i] + middle[i + 1:] env_copy = env.copy() if terms.unify(rl, env, right, env_copy): r.append(env_copy) return tuple(r)
def pred_is(rules, term, env): if term.arity != 2: return False leftv = rules.evaluate(term.args[0], env) rightv = rules.evaluate(term.args[1], env) if terms.is_bound(leftv): if terms.is_bound(rightv): return leftv == rightv return terms.unify(leftv, {}, rightv, env) if terms.is_bound(rightv): return terms.unify(rightv, {}, leftv, env) return False
def search_env(self, goal_env, *goals): queue = [ Goal(terms.make_rule(terms.make_term('head'), *goals), None, goal_env, 0) ] while queue: goal = queue.pop() if goal.current >= len(goal.rule.goals): if goal.parent == None: yield goal.env else: parent = goal.parent terms.unify(goal.rule.head, goal.env, parent.rule.goals[parent.current], parent.env) parent.current = parent.current + 1 queue.insert(0, parent) continue term = goal.rule.goals[goal.current] if isinstance(term.pred, str) and term.pred.startswith('@'): builtin = self.predicates.get(term.pred[1:]) if not builtin: continue results = builtin(self, term, goal.env) if results == False: continue goal.current = goal.current + 1 if results == True: queue.insert(0, goal) continue for result in results: queue.insert( 0, Goal(goal.rule, goal.parent, result, goal.current)) continue for rule in self.find_rules(term, goal.env): rule_env = {} if self.unify(term, goal.env, rule.head, rule_env): queue.insert(0, Goal(rule, goal, rule_env, 0))
def pred_meta(engine, term, env): if term.arity != 3: return False t = terms.expand(term.args[0], env) p = terms.expand(term.args[1], env) a = terms.expand(term.args[2], env) if terms.is_unbound(t): if terms.is_unbound(p) or terms.is_unbound(a): return False if not isinstance(p, str) or not terms.is_list(a): return False x = terms.make_term(p, *a) return terms.unify(x, {}, t, env) e = env.copy() if terms.unify(t.pred, {}, p, e) and terms.unify(t.args, {}, a, e): env.update(e) return True return False
def pred_map(rules, term, env): if term.arity < 4: return False var = terms.expand(term.args[0], env) list = terms.expand(term.args[1], env) var2 = terms.expand(term.args[2], env) list2 = terms.expand(term.args[3], env) clauses = [terms.expand(t, env) for t in term.args[4:]] if terms.is_unbound(list) or not terms.is_list(list): return False r = [] for e in list: e2 = {} if not terms.unify(e, {}, var, e2): return False r2 = rules.search_any_env(e2, *clauses) if r2 is None: return False r.append(terms.expand(var2, r2)) return terms.unify(tuple(r), env, list2, env)
def pred_last(rules, term, env): if term.arity != 3: return False left = terms.expand(term.args[0], env) middle = terms.expand(term.args[1], env) right = terms.expand(term.args[2], env) if terms.is_bound(left): if not terms.is_list(left) or not left: return False env_copy = env.copy() if not terms.unify(left[-1], env, middle, env_copy): return False if not terms.unify(left[:-1], env, right, env_copy): return False return [env_copy] if terms.is_unbound(middle) or terms.is_unbound( right) or not terms.is_list(right): return False l2 = right + (middle, ) return terms.unify(l2, env, left, env)
def pred_applies(rules, term, env): if term.arity < 2: return False var = terms.expand(term.args[0], env) list = terms.expand(term.args[1], env) clauses = [terms.expand(t, env) for t in term.args[2:]] if terms.is_unbound(list) or not terms.is_list(list): return False for e in list: e2 = {} if not terms.unify(e, {}, var, e2): return False if rules.search_any_env(e2, *clauses) is None: return False return True
def pred_in(rules, term, env): if term.arity != 2: return False right = terms.expand(term.args[1], env) if terms.is_unbound(right) or not terms.is_list(right): return False left = terms.expand(term.args[0], env) if terms.is_bound(left): return left in right r = [] for e in right: env_copy = env.copy() if terms.unify(e, env, term.args[0], env_copy): r.append(env_copy) return r
def func_filter(rules, term, env): if term.arity < 2: return () var = terms.expand(term.args[0], env) list = terms.expand(term.args[1], env) clauses = [terms.expand(t, env) for t in term.args[2:]] if terms.is_unbound(list) or not terms.is_list(list): return () r = [] for e in list: e2 = {} if not terms.unify(e, {}, var, e2): continue if rules.search_any_env(e2, *clauses) is None: continue r.append(terms.expand(var, e2)) return tuple(r)
def func_extend(rules, term, env): if term.arity < 3: return () var1 = terms.expand(term.args[0], env) list = terms.expand(term.args[1], env) var2 = terms.expand(term.args[2], env) clauses = [terms.expand(t, env) for t in term.args[3:]] if terms.is_unbound(list) or not terms.is_list(list): return () r = [] for e in list: e2 = {} if not terms.unify(e, {}, var1, e2): continue for r2 in rules.search_env(e2, *clauses): r.append(terms.expand(var2, r2)) return tuple(r)
def unify(self, src, src_env, dest, dest_env): return terms.unify(src, src_env, dest, dest_env)