def visit_Compound(self, node: Compound):
        node.env = Environment(merge_with=node.env)

        for i, d in node.children():
            d.env = node.env
            d.global_env = node.global_env
            self.visit(d)
Exemple #2
0
def clause_simpagation(env, p):
    name = Compound(env.getatom(p[0].getstr(), 0), [])
    keep = unbox(p[2])
    drop = unbox(p[4])
    guard = unbox(p[5])
    goal = unbox(p[7])
    return Box(Compound(env.getatom('constraint_rule', 5),
        [name, keep, drop, guard, goal]))
Exemple #3
0
def chr_add_constraint(goal, mach, program):
    assert isinstance(goal, Compound)
    chrid = mach.next_chrid
    mach.next_chrid += 1
    mach.chr_add_constraint(chrid, goal)
    deep_freeze(mach, goal, Compound(CHR_REVISE, [wrap(chrid)]))
    #print 'start resolution:    %d %s' % (chrid, goal.stringify())
    # Without locking the database, we'd lose track
    # of constraints added and removed and
    # the constraint resolution step would fail.
    assert not mach.chr_lock
    mach.chr_lock = True
    constraint_resolution(goal.fsym, chrid, mach, program)
    mach.chr_lock = False
Exemple #4
0
def load(code, varno=100, debug=False):
    defs = {}
    chrs = []
    constraints = {}
    occurrenceno = 0
    for clause in reversed(as_list(code)):
        assert isinstance(clause, Compound)
        if clause.fsym is CLAUSE:
            head = clause.args[0]
            assert isinstance(head, Compound)
            if head.fsym in defs:
                rest = defs[head.fsym]
            else:
                rest = Compound(NIL, [])
            defs[head.fsym] = Compound(CONS, [clause, rest])
        elif clause.fsym is CONSTRAINT_RULE:
            name = clause.args[0]
            assert isinstance(name, Compound)
            name = name.fsym.name
            keep = as_list(clause.args[1])
            drop = as_list(clause.args[2])
            guard = clause.args[3]
            goal = clause.args[4]
            this = CHR(name, keep + drop, len(keep), guard, goal)
            chrs.append(this)
            index = 0
            for k in this.pattern:
                assert isinstance(k, Compound)
                if k.fsym in constraints:
                    constraints[k.fsym].insert(0, (this, index))
                else:
                    constraints[k.fsym] = [(this, index)]
                index += 1
        else:
            raise ValueError("machine.load received a non-program")

    return Program(defs, constraints)
Exemple #5
0
def constraint_resolution(fsym, chrid, mach, program, start=0):
    constraints = program.constraints.get(fsym, [])
    for rule, pivot in constraints[start:]:
        #print 'checking rule %s:%d' % (rule.name, pivot)
        memo = execute_rule(rule, pivot, chrid, mach, program)
        if memo is not None:
            goal = mach.variant(rule.goal, memo)
            #print 'success: ' + goal.stringify()
            if rule.keep <= pivot:  # The constraint did not survive.
                return mach.state.expand([goal])
            if start + 1 >= len(constraints):
                return mach.state.expand([goal])
            return mach.state.expand(
                [goal,
                 Compound(CHR_RESUME,
                          [wrap(chrid), wrap(start + 1)])])
        start += 1
Exemple #6
0
def main(argv):
    if len(argv) <= 1:
        return 1

    fd = rfile.create_file(argv[1], 'rb')
    try:
        source = fd.read()
    finally:
        fd.close()

    code, next_varno = parser.parse(source)
    program = machine.load(code)
    succ = machine.Success()
    try:
        program.solve(succ, Compound(MAIN, []), next_varno)
    except machine.Exiting as exit:
        return exit.status
    return 0
Exemple #7
0
def solve(mach, program, debug=False):
    goal = mach.state.next_goal(mach)
    while goal is not None:
        if debug:
            print
            for _, a in mach.state.disj:
                print "   " + a.stringify()
            print "** " + goal.stringify() + "#" + mach.state.conj.stringify()
        if goal.fsym is TRUE:
            pass
        elif goal.fsym is FALSE:
            mach.state.fail()
        elif goal.fsym is AND:
            car = goal.args[0]
            cdr = goal.args[1]
            mach.state.expand([car, cdr])
        elif goal.fsym is OR:
            car = goal.args[0]
            cdr = goal.args[1]
            mach.state.choicepoint(mach, [cdr])
            mach.state.invoke(car)
        elif goal.fsym is SAME:
            car = goal.args[0]
            cdr = goal.args[1]
            if not car.same(cdr):
                mach.state.fail()
        elif goal.fsym is UNIFY:
            left = goal.args[0]
            right = goal.args[1]
            if not mach.unify(left, right):
                mach.state.fail()
        # I wonder if this is still required, or if it should be improved.
        elif goal.fsym is COND2:
            mach.backtrack += 1
            t = mach.note()
            csucc = CondSuccess()
            cgoal = goal.args[0]
            cconj = goal.args[1]
            this_state = mach.state
            mach.state = mach.state.subgoal(cgoal, [], csucc)
            solve(mach, program, debug)
            mach.state = this_state
            mach.backtrack -= 1
            if csucc.success:
                mach.state.invoke(cconj)
            else:
                mach.undo(t)
        elif goal.fsym is GET_ATTS:
            var = goal.args[0]
            spec = goal.args[1]
            assert isinstance(spec, Compound)
            val = var.attr.get(spec.fsym, None)
            if val is None:
                mach.state.fail()
            else:
                if not mach.unify(val, spec):
                    mach.state.fail()
        elif goal.fsym is PUT_ATTS:
            var = goal.args[0]
            spec = goal.args[1]
            assert isinstance(spec, Compound)
            mach.put_atts(var, spec.fsym, spec)
        elif goal.fsym is BIND_HARD:
            var = goal.args[0]
            val = goal.args[1]
            if isinstance(var, Variable) and var.instance is var:
                mach.bind_hard(var, val)
            else:
                if not mach.unify(var, val):
                    mach.state.fail()
        elif goal.fsym is LIST_ATTS:
            var = goal.args[0]
            assert isinstance(var, Variable)
            ret = goal.args[1]
            res = Compound(NIL, [])
            for val in var.attr.itervalues():
                res = Compound(CONS, [val, res])
            if not mach.unify(ret, res):
                mach.state.fail()
        elif goal.fsym is DEF:
            head = goal.args[0]
            clause = goal.args[1]
            assert clause.fsym is CONS
            assert clause.args[0].fsym is CLAUSE
            top = mach.variant(clause.args[0])
            nxt = clause.args[1]
            if nxt.fsym is not NIL:
                mach.state.choicepoint(mach, [Compound(DEF, [head, nxt])])
            mach.state.expand([
                Compound(UNIFY, [head, top.args[0]]),
                #Compound(WRITE, [head]),
                top.args[1]
            ])
        elif goal.fsym in program.defs:
            clauses = program.defs[goal.fsym]
            mach.state.invoke(Compound(DEF, [goal, clauses]))
        elif goal.fsym in program.constraints:
            chr_add_constraint(goal, mach, program)
        elif goal.fsym is CHR_RESUME:
            chrid = goal.args[0]
            assert isinstance(chrid, Integer)
            chrid = chrid.bignum.toint()
            start = goal.args[1]
            assert isinstance(start, Integer)
            start = start.bignum.toint()
            chr_resume(chrid, start, mach, program)
        # Implementation of side effects in logic language
        # are bit of a question.
        # This looks like slightly wrong way to do it.
        elif goal.fsym is EXIT:
            a = goal.args[0].unroll()
            if is_ground(a):
                if isinstance(a, Integer):
                    raise Exiting(a.bignum.toint())
                else:
                    mach.state.fail()
            elif mach.chr_lock:
                mach.state.fail()
            else:
                chr_add_constraint(goal, mach, program)
        elif goal.fsym is WRITE:
            a = goal.args[0].unroll()
            if is_ground(a):
                s = a.stringify()
                os.write(1, s + "\n")
            elif mach.chr_lock:
                mach.state.fail()
            else:
                chr_add_constraint(goal, mach, program)
        elif goal.fsym is CHR_REVISE:
            revise = goal
            a = goal.args[0]
            assert isinstance(a, Integer)
            i = a.bignum.toint()
            goal = mach.chr_by_id.get(i, None)
            if goal is not None:
                assert isinstance(goal, Compound)
                if goal.fsym is WRITE and is_ground(goal.args[0]):
                    s = goal.args[0].stringify()
                    os.write(1, s + "\n")
                elif goal.fsym is EXIT and is_ground(goal.args[0]):
                    if isinstance(a, Integer):
                        raise Exiting(a.bignum.toint())
                    else:
                        mach.state.fail()
                else:
                    deep_freeze(mach, goal, revise, True)
                    chr_resume(i, 0, mach, program)
        elif goal.fsym is CHR_PRINTOUT:
            for chrid, const in mach.chr_by_id.iteritems():
                s = const.stringify()
                os.write(1, "chr%d: %s\n" % (chrid, s))
        else:
            raise ValueError("unknown predicate: %s" % goal.stringify())
        if debug:
            print "=> " + mach.state.conj.stringify()
        goal = mach.state.next_goal(mach)
Exemple #8
0
def clause_axiom(env, p):
    head = unbox(p[0])
    body = Compound(env.getatom('true', 0), [])
    return Box(Compound(env.getatom('<-', 2), [head, body]))
Exemple #9
0
def empty_guard(env, p):
    return Box(Compound(env.getatom('true', 0), []))
Exemple #10
0
def goal_formula(env, p):
    a = unbox(p[0])
    b = unbox(p[1])
    return Box(Compound(env.getatom('and', 2), [a, b]))
Exemple #11
0
 def getcons(self, car, cdr):
     return Compound(self.getatom(":", 2), [car, cdr])
Exemple #12
0
 def getnil(self):
     return Compound(self.getatom("nil", 0), [])
Exemple #13
0
def formula_unify(env, p):
    left  = unbox(p[0])
    right = unbox(p[2])
    atom = env.getatom("=", 2)
    return Box(Compound(atom, [left, right]))
Exemple #14
0
def predicate_compound(env, p):
    seq = as_list(unbox(p[2]))
    atom = env.getatom(p[0].getstr(), len(seq))
    return Box(Compound(atom, seq))
Exemple #15
0
def predicate_atom(env, p):
    return Box(Compound(env.getatom(p[0].getstr(), 0), []))
Exemple #16
0
def clause_rule(env, p):
    head = unbox(p[0])
    body = unbox(p[2])
    return Box(Compound(env.getatom('<-', 2), [head, body]))