예제 #1
0
 def __init__(self, stream, annotations=None):
     TreeWalker.__init__(self)
     self.stream = stream
     self.write = self.stream.write
     self.mgr = get_env().formula_manager
     if not annotations:
         self.annotations = Annotations()
     else:
         self.annotations = annotations
예제 #2
0
    def test_annotations(self):
        x = Symbol('x')
        x_next = Symbol('x.next')
        f = Iff(x, Not(x_next))

        ann = Annotations()
        ann.add(x, 'next', x_next.symbol_name())
        ann.add(f, 'trans', 'true')
        ann.add(x, 'init', 'true')

        tree_buf = StringIO()
        dag_buf = StringIO()
        tree_printer = SmtPrinter(tree_buf, annotations=ann)
        dag_printer = SmtDagPrinter(dag_buf, annotations=ann)

        dag_printer.printer(f)
        tree_printer.printer(f)

        self.assertEqual(
            tree_buf.getvalue(),
            "(! (= (! x :next x.next :init true) (not x.next)) :trans true)")
        self.assertEqual(
            dag_buf.getvalue(),
            "(let ((.def_0 (not x.next))) (let ((.def_1 (= (! x :next x.next :init true) .def_0))) (! .def_1 :trans true)))"
        )
예제 #3
0
    def test_basic(self):
        ann = Annotations()
        a = Symbol("a")
        next_a = Symbol("next(a)")
        init_a = Symbol("init(a)")

        ann.add(a, "next", next_a)
        ann.add(a, "init", init_a)
        ann.add(a, "related", next_a)
        ann.add(a, "related", init_a)

        self.assertIn(a, ann)
        self.assertEqual(set([next_a]), ann.annotations(a)["next"])
        self.assertEqual(set([init_a]), ann.annotations(a)["init"])
        self.assertEqual(set([init_a, next_a]), ann.annotations(a)["related"])
        self.assertEqual(set([a]), ann.all_annotated_formulae("next"))
        self.assertEqual(set([a]), ann.all_annotated_formulae("init"))
        self.assertEqual(set([a]), ann.all_annotated_formulae("related"))
        self.assertEqual(set(), ann.all_annotated_formulae("non-existent"))
예제 #4
0
 def __init__(self):
     self.keys = {}
     self.definitions = {}
     self.annotations = Annotations()
예제 #5
0
    def test_remove_value(self):
        ann = Annotations()
        a = Symbol("a")
        next_a = Symbol("next(a)")
        init_a = Symbol("init(a)")

        ann.add(a, "next", next_a)
        ann.add(a, "init", init_a)
        ann.add(a, "related", next_a)
        ann.add(a, "related", init_a)

        self.assertNotEqual(
            ann.annotations(a)["init"],
            ann.annotations(a)["related"])
        ann.remove_value(a, "related", next_a)
        self.assertEqual(
            ann.annotations(a)["related"],
            ann.annotations(a)["init"])
예제 #6
0
    def test_remove_annotation(self):
        ann = Annotations()
        a = Symbol("a")
        next_a = Symbol("next(a)")
        init_a = Symbol("init(a)")

        ann.add(a, "next", next_a)
        ann.add(a, "init", init_a)
        ann.add(a, "related", next_a)
        ann.add(a, "related", init_a)

        ann.remove_annotation(a, "next")

        self.assertNotIn("next", ann.annotations(a))
        self.assertEqual(set([init_a]), ann.annotations(a)["init"])
        self.assertEqual(set([init_a, next_a]), ann.annotations(a)["related"])
        self.assertEqual(set([]), ann.all_annotated_formulae("next"))
        self.assertEqual(set([a]), ann.all_annotated_formulae("init"))
        self.assertEqual(set([a]), ann.all_annotated_formulae("related"))
        self.assertEqual(set(), ann.all_annotated_formulae("non-existent"))
예제 #7
0
    def test_remove_value(self):
        ann = Annotations()
        a = Symbol("a")
        next_a = Symbol("next(a)")
        init_a = Symbol("init(a)")

        ann.add(a, "next", next_a)
        ann.add(a, "init", init_a)
        ann.add(a, "related", next_a)
        ann.add(a, "related", init_a)

        self.assertNotEqual(ann.annotations(a)["init"], ann.annotations(a)["related"])
        ann.remove_value(a, "related", next_a)
        self.assertEqual(ann.annotations(a)["related"], ann.annotations(a)["init"])
예제 #8
0
    def test_remove(self):
        ann = Annotations()
        a = Symbol("a")
        next_a = Symbol("next(a)")
        init_a = Symbol("init(a)")

        ann.add(a, "next", next_a)
        ann.add(a, "init", init_a)
        ann.add(a, "related", next_a)
        ann.add(a, "related", init_a)

        self.assertIn(a, ann)
        ann.remove(a)
        self.assertNotIn(a, ann)

        self.assertEqual(None, ann.annotations(a))
        self.assertEqual(set([]), ann.all_annotated_formulae("next"))
        self.assertEqual(set([]), ann.all_annotated_formulae("init"))
        self.assertEqual(set([]), ann.all_annotated_formulae("related"))
        self.assertEqual(set(), ann.all_annotated_formulae("non-existent"))
예제 #9
0
class SmtPrinter(TreeWalker):
    def __init__(self, stream, annotations=None):
        TreeWalker.__init__(self)
        self.stream = stream
        self.write = self.stream.write
        self.mgr = get_env().formula_manager
        if not annotations:
            self.annotations = Annotations()
        else:
            self.annotations = annotations

    def printer(self, f):
        self.walk(f)

    def walk_threshold(self, formula):
        """This is a complete printer"""
        raise NotImplementedError

    def walk_nary(self, formula, operator):
        self.write("(%s" % operator)
        for s in formula.args():
            self.write(" ")
            yield s
        self.write(")")

    def walk_and(self, formula):
        return self.walk_nary(formula, "and")

    def walk_or(self, formula):
        return self.walk_nary(formula, "or")

    def walk_not(self, formula):
        return self.walk_nary(formula, "not")

    def walk_implies(self, formula):
        return self.walk_nary(formula, "=>")

    def walk_iff(self, formula):
        return self.walk_nary(formula, "=")

    def walk_plus(self, formula):
        return self.walk_nary(formula, "+")

    def walk_minus(self, formula):
        return self.walk_nary(formula, "-")

    def walk_times(self, formula):
        return self.walk_nary(formula, "*")

    def walk_equals(self, formula):
        return self.walk_nary(formula, "=")

    def walk_le(self, formula):
        return self.walk_nary(formula, "<=")

    def walk_lt(self, formula):
        return self.walk_nary(formula, "<")

    def walk_ite(self, formula):
        return self.walk_nary(formula, "ite")

    def walk_toreal(self, formula):
        return self.walk_nary(formula, "to_real")

    def walk_realtoint(self, formula):
        return self.walk_nary(formula, "to_int")

    def walk_div(self, formula):
        return self.walk_nary(formula, "/")

    def walk_int_div(self, formula):
        return self.walk_nary(formula, "div")

    def walk_mod(self, formula):
        return self.walk_nary(formula, "mod")

    def walk_pow(self, formula):
        return self.walk_nary(formula, "pow")

    def walk_bv_and(self, formula):
        return self.walk_nary(formula, "bvand")

    def walk_bv_or(self, formula):
        return self.walk_nary(formula, "bvor")

    def walk_bv_not(self, formula):
        return self.walk_nary(formula, "bvnot")

    def walk_bv_xor(self, formula):
        return self.walk_nary(formula, "bvxor")

    def walk_bv_add(self, formula):
        return self.walk_nary(formula, "bvadd")

    def walk_bv_sub(self, formula):
        return self.walk_nary(formula, "bvsub")

    def walk_bv_neg(self, formula):
        return self.walk_nary(formula, "bvneg")

    def walk_bv_mul(self, formula):
        return self.walk_nary(formula, "bvmul")

    def walk_bv_udiv(self, formula):
        return self.walk_nary(formula, "bvudiv")

    def walk_bv_urem(self, formula):
        return self.walk_nary(formula, "bvurem")

    def walk_bv_lshl(self, formula):
        return self.walk_nary(formula, "bvshl")

    def walk_bv_lshr(self, formula):
        return self.walk_nary(formula, "bvlshr")

    def walk_bv_ult(self, formula):
        return self.walk_nary(formula, "bvult")

    def walk_bv_ule(self, formula):
        return self.walk_nary(formula, "bvule")

    def walk_bv_slt(self, formula):
        return self.walk_nary(formula, "bvslt")

    def walk_bv_sle(self, formula):
        return self.walk_nary(formula, "bvsle")

    def walk_bv_concat(self, formula):
        return self.walk_nary(formula, "concat")

    def walk_bv_comp(self, formula):
        return self.walk_nary(formula, "bvcomp")

    def walk_bv_ashr(self, formula):
        return self.walk_nary(formula, "bvashr")

    def walk_bv_sdiv(self, formula):
        return self.walk_nary(formula, "bvsdiv")

    def walk_bv_srem(self, formula):
        return self.walk_nary(formula, "bvsrem")

    def walk_bv_tonatural(self, formula):
        return self.walk_nary(formula, "bv2nat")

    #def walk_int_to_bv(self, formula): return self.walk_nary(formula, "int2bv")
    def walk_array_select(self, formula):
        return self.walk_nary(formula, "select")

    def walk_array_store(self, formula):
        return self.walk_nary(formula, "store")

    def walk_symbol(self, formula):
        self.write(quote(formula.symbol_name()))

    def walk_function(self, formula):
        return self.walk_nary(formula,
                              quote(formula.function_name().symbol_name()))

    def walk_int_constant(self, formula):
        if formula.constant_value() < 0:
            self.write("(- " + str(-formula.constant_value()) + ")")
        else:
            self.write(str(formula.constant_value()))

    def walk_real_constant(self, formula):
        if formula.constant_value() < 0:
            template = "(- %s)"
        else:
            template = "%s"

        (n,d) = abs(formula.constant_value().numerator), \
                    formula.constant_value().denominator
        if d != 1:
            res = template % ("(/ " + str(n) + " " + str(d) + ")")
        else:
            res = template % (str(n) + ".0")

        self.write(res)

    def walk_bool_constant(self, formula):
        if formula.constant_value():
            self.write("true")
        else:
            self.write("false")

    def walk_bv_constant(self, formula):
        self.write("#b" + formula.bv_bin_str())

    def walk_str_constant(self, formula):
        self.write('"' + formula.constant_value().replace('"', '""') + '"')

    def walk_forall(self, formula):
        return self._walk_quantifier("forall", formula)

    def walk_exists(self, formula):
        return self._walk_quantifier("exists", formula)

    def _walk_quantifier(self, operator, formula):
        assert len(formula.quantifier_vars()) > 0
        self.write("(%s (" % operator)

        for s in formula.quantifier_vars():
            self.write("(")
            yield s
            self.write(" %s)" % s.symbol_type().as_smtlib(False))

        self.write(") ")

        body = formula.arg(0)

        pats = formula.quantifier_patterns()
        nopats = formula.quantifier_nopatterns()
        if self.annotations.has_annotation(body, "qid"):
            qids = self.annotations[body]["qid"]
        else:
            qids = set()

        some_annotation = len(pats) + len(nopats) + len(qids) > 0

        if len(qids) == 0:
            qid = None
        else:
            qid = next(iter(qids))

        if some_annotation:
            self.write("(! ")

        yield body

        def gen_pat(pat):
            for term_num, term in enumerate(pat):
                yield term
                if term_num < len(pat) - 1:
                    self.write(" ")

        def gen_pats(lbl, ps):
            for pat_num, pat in enumerate(ps):
                self.write(" :%s (" % lbl)
                yield from gen_pat(pat)
                self.write(")")

        def gen_nopats(lbl, ns):
            for nopat in ns:
                self.write(" :%s " % lbl)
                yield nopat

        if len(pats) > 0:
            yield from gen_pats("pattern", pats)

        if len(nopats) > 0:
            yield from gen_nopats("no-pattern", nopats)

        if qid:
            self.write(" :qid %s" % qid)

        # Closing the (! ... :pattern (...) )
        #                                   ^
        if some_annotation:
            self.write(" )")

        self.write(")")

    def walk_bv_extract(self, formula):
        self.write("((_ extract %d %d) " %
                   (formula.bv_extract_end(), formula.bv_extract_start()))
        yield formula.arg(0)
        self.write(")")

    @handles(op.INT_TO_BV)
    def walk_int_to_bv(self, formula):
        self.write("((_ int2bv %d) " % formula._content.payload)
        yield formula.arg(0)
        self.write(")")

    @handles(op.BV_ROR, op.BV_ROL)
    def walk_bv_rotate(self, formula):
        if formula.is_bv_ror():
            rotate_type = "rotate_right"
        else:
            assert formula.is_bv_rol()
            rotate_type = "rotate_left"
        rot_step = formula.bv_rotation_step()
        if is_python_integer(rot_step):
            self.write("((_ %s %d) " % (rotate_type, rot_step))
            yield formula.arg(0)
        else:
            self.write("(ext_%s " % rotate_type)
            yield formula.arg(0)
            self.write(" ")
            yield rot_step
        self.write(")")

    @handles(op.BV_ZEXT, op.BV_SEXT)
    def walk_bv_extend(self, formula):
        if formula.is_bv_zext():
            extend_type = "zero_extend"
        else:
            assert formula.is_bv_sext()
            extend_type = "sign_extend"
        self.write("((_ %s %d) " % (extend_type, formula.bv_extend_step()))
        yield formula.arg(0)
        self.write(")")

    def walk_str_length(self, formula):
        self.write("(str.len ")
        self.walk(formula.arg(0))
        self.write(")")

    def walk_str_charat(self, formula, **kwargs):
        self.write("( str.at ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(")")

    def walk_str_concat(self, formula, **kwargs):
        self.write("( str.++ ")
        for arg in formula.args():
            self.walk(arg)
            self.write(" ")
        self.write(")")

    def walk_str_contains(self, formula, **kwargs):
        self.write("( str.contains ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(")")

    def walk_str_indexof(self, formula, **kwargs):
        self.write("( str.indexof ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(" ")
        self.walk(formula.arg(2))
        self.write(")")

    def walk_str_replace(self, formula, **kwargs):
        self.write("( str.replace ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(" ")
        self.walk(formula.arg(2))
        self.write(")")

    def walk_str_substr(self, formula, **kwargs):
        self.write("( str.substr ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(" ")
        self.walk(formula.arg(2))
        self.write(")")

    def walk_str_prefixof(self, formula, **kwargs):
        self.write("( str.prefixof ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(")")

    def walk_str_suffixof(self, formula, **kwargs):
        self.write("( str.suffixof ")
        self.walk(formula.arg(0))
        self.write(" ")
        self.walk(formula.arg(1))
        self.write(")")

    def walk_str_to_int(self, formula, **kwargs):
        self.write("( str.to.int ")
        self.walk(formula.arg(0))
        self.write(")")

    def walk_int_to_str(self, formula, **kwargs):
        self.write("( int.to.str ")
        self.walk(formula.arg(0))
        self.write(")")

    def walk_array_value(self, formula):
        assign = formula.array_value_assigned_values_map()
        for _ in xrange(len(assign)):
            self.write("(store ")

        self.write("((as const %s) " % formula.get_type().as_smtlib(False))
        yield formula.array_value_default()
        self.write(")")

        for k in sorted(assign, key=str):
            self.write(" ")
            yield k
            self.write(" ")
            yield assign[k]
            self.write(")")