Пример #1
0
def get_safety() -> List[Expr]:
    prog = syntax.the_program
    safety: List[Expr]
    if utils.args.safety is not None:
        the_inv: Optional[InvariantDecl] = None
        for inv in prog.invs():
            if inv.name == utils.args.safety:
                the_inv = inv
        if the_inv is not None:
            safety = [the_inv.expr]
        else:
            try:
                oldcount = utils.error_count
                e = syntax.close_free_vars(parser.parse_expr(
                    utils.args.safety))
                with prog.scope.n_states(1):
                    typechecker.typecheck_expr(prog.scope, e, syntax.BoolSort)
                assert oldcount == utils.error_count, 'errors in parsing or typechecking'
                safety = [e]
            except Exception as e:
                print(e)
                utils.print_error_and_exit(
                    None, f'--safety received string "{utils.args.safety}", '
                    'which is neither the name of an invariant/safety property '
                    'nor does it parse and typecheck as an expression')
    else:
        safety = [s.expr for s in prog.safeties()]

    return safety
Пример #2
0
def verify(s: Solver) -> None:
    old_count = utils.error_count
    prog = syntax.the_program
    a = prog.the_automaton()
    if a is None:
        if utils.args.automaton == 'only':
            utils.print_error_and_exit(
                None,
                "--automaton='only' requires the file to declare an automaton")
    elif utils.args.automaton != 'no':
        check_automaton_full(s, a)

    if utils.args.automaton != 'only':
        init_res = logic.check_init(s)
        tr_res = logic.check_transitions(s)
        res = init_res or tr_res
        if res is not None and utils.args.json:
            json_cex: Optional[JSON] = json_counterexample(res)
        else:
            json_cex = None

        obj: JSON = {}
        obj['version'] = 1
        obj['subcommand'] = utils.args.subcommand
        obj['is_inductive'] = json_cex is None
        if json_cex is not None:
            obj['counterexample'] = json_cex
        json.dump(obj, sys.stdout, indent=4)

    if utils.error_count == old_count:
        utils.logger.always_print('all ok!')
    else:
        utils.logger.always_print('program has errors.')
Пример #3
0
    def __init__(self, solver: Solver) -> None:
        self.solver = solver
        prog = syntax.the_program

        if utils.args.automaton:
            automaton = prog.the_automaton()
            if automaton is None:
                utils.print_error_and_exit(
                    None, 'updr --automaton requires the file to '
                    'declare an automaton')
        else:
            the_phase = 'the_phase'
            pcs: List[syntax.PhaseComponent] = []
            for t in prog.transitions():
                pcs.append(
                    syntax.PhaseTransitionDecl(None, t.name, None, the_phase))
            for inv in prog.safeties():
                pcs.append(inv)

            automaton = AutomatonDecl(None, [
                syntax.InitPhaseDecl(None, the_phase),
                syntax.PhaseDecl(None, the_phase, pcs)
            ])

            automaton.resolve(prog.scope)

        self.automaton = PhaseAutomaton(automaton)
        self.fs: List[Frame] = []
        self.push_cache: List[Dict[Phase, Set[Expr]]] = []
        self.counter = 0
        self.predicates: List[Expr] = []
        self.state_count = 0
Пример #4
0
def bmc_trace(prog: syntax.Program,
              trace: syntax.TraceDecl,
              s: Solver,
              sat_checker: Callable[[Solver, List[str]],
                                    Optional[logic.Trace]],
              log: bool = False) -> Optional[logic.Trace]:
    n_states = len(list(trace.transitions())) + 1
    if log:
        print('%s states' % (n_states, ))

    keys = ['state%2d' % i for i in range(n_states)]

    for k in keys:
        s.get_translator(
            k)  # initialize all the keys before pushing a solver stack frame

    with s:
        lator = s.get_translator(keys[0])
        if len(trace.components) > 0 and not isinstance(
                trace.components[0], syntax.AssertDecl):
            for init in prog.inits():
                s.add(lator.translate_expr(init.expr))

        i = 0
        for c in trace.components:
            if isinstance(c, syntax.AssertDecl):
                if c.expr is None:
                    if i != 0:
                        utils.print_error_and_exit(
                            c.tok,
                            'assert init is only allowed in the first state')
                    for init in prog.inits():
                        s.add(
                            s.get_translator(keys[i]).translate_expr(
                                init.expr))
                else:
                    s.add(s.get_translator(keys[i]).translate_expr(c.expr))
            else:
                te: syntax.TransitionExpr = c.transition
                if isinstance(te, syntax.AnyTransition):
                    logic.assert_any_transition(s,
                                                str(i),
                                                keys[i + 1],
                                                keys[i],
                                                allow_stutter=True)
                else:
                    l = []
                    for call in te.calls:
                        tid = z3.Bool(
                            logic.get_transition_indicator(
                                str(i), call.target))
                        l.append(tid)
                        s.add(tid == translate_transition_call(
                            s, keys[i + 1], keys[i], call))
                    s.add(z3.Or(*l))

                i += 1

        return sat_checker(s, keys)
Пример #5
0
def bmc_trace(prog: syntax.Program,
              trace: syntax.TraceDecl,
              s: Solver,
              sat_checker: Callable[[Solver, int], Optional[logic.Trace]],
              log: bool = False) -> Optional[logic.Trace]:
    n_states = len(list(trace.transitions())) + 1
    if log:
        print('%s states' % (n_states, ))

    lator = s.get_translator(n_states)

    with s.new_frame():
        if len(trace.components) > 0 and not isinstance(
                trace.components[0], syntax.AssertDecl):
            for init in prog.inits():
                s.add(lator.translate_expr(init.expr))

        i = 0
        for c in trace.components:
            if isinstance(c, syntax.AssertDecl):
                if c.expr is None:
                    if i != 0:
                        utils.print_error_and_exit(
                            c.span,
                            'assert init is only allowed in the first state')
                    for init in prog.inits():
                        assert i == 0
                        s.add(lator.translate_expr(init.expr))
                else:
                    s.add(lator.translate_expr(New(c.expr, i)))
            else:
                te: syntax.TransitionExpr = c.transition
                if isinstance(te, syntax.AnyTransition):
                    logic.assert_any_transition(s,
                                                lator,
                                                i,
                                                allow_stutter=True)
                else:
                    l = []
                    for call in te.calls:
                        tid = z3.Bool(
                            logic.get_transition_indicator(
                                str(i), call.target))
                        l.append(tid)
                        s.add(
                            z3.Implies(
                                tid,
                                translate_transition_call(s, lator, i, call)))
                    s.add(z3.Or(*l))

                i += 1

        return sat_checker(s, n_states)
Пример #6
0
def trace(s: Solver) -> None:
    prog = syntax.the_program
    if len(list(prog.traces())) > 0:
        utils.logger.always_print('finding traces:')

    for trace in prog.traces():
        n_states = len(list(trace.transitions())) + 1
        print('%s states' % (n_states,))

        keys = ['state%2d' % i for i in range(n_states)]

        for k in keys:
            s.get_translator(k)  # initialize all the keys before pushing a solver stack frame

        with s:
            lator = s.get_translator(keys[0])
            if len(trace.components) > 0 and not isinstance(trace.components[0], syntax.AssertDecl):
                for init in prog.inits():
                    s.add(lator.translate_expr(init.expr))

            i = 0
            for c in trace.components:
                if isinstance(c, syntax.AssertDecl):
                    if c.expr is None:
                        if i != 0:
                            utils.print_error_and_exit(c.tok, 'assert init is only allowed in the first state')
                        for init in prog.inits():
                            s.add(s.get_translator(keys[i]).translate_expr(init.expr))
                    else:
                        s.add(s.get_translator(keys[i]).translate_expr(c.expr))
                else:
                    te: syntax.TransitionExpr = c.transition
                    if isinstance(te, syntax.AnyTransition):
                        logic.assert_any_transition(s, str(i), keys[i + 1], keys[i], allow_stutter=True)
                    else:
                        l = []
                        for call in te.calls:
                            tid = z3.Bool(logic.get_transition_indicator(str(i), call.target))
                            l.append(tid)
                            s.add(tid == translate_transition_call(s, keys[i + 1], keys[i], call))
                        s.add(z3.Or(*l))

                    i += 1

            res = logic.check_unsat([], s, keys)
            if (res == z3.sat) != trace.sat:
                utils.print_error(trace.tok, 'trace declared %s but was %s!' % ('sat' if trace.sat else 'unsat', res))
Пример #7
0
    def __init__(self, solver: Solver) -> None:
        self.solver = solver
        prog = syntax.the_program

        if utils.args.automaton:
            automaton = prog.the_automaton()
            if automaton is None:
                utils.print_error_and_exit(
                    None, 'updr --automaton requires the file to '
                    'declare an automaton')
        else:
            the_phase = 'the_phase'
            pcs: List[syntax.PhaseComponent] = []
            for t in prog.transitions():
                pcs.append(
                    syntax.PhaseTransitionDecl(None, t.name, None, the_phase))
            for inv in prog.safeties():
                pcs.append(inv)

            automaton = AutomatonDecl(None, [
                syntax.InitPhaseDecl(None, the_phase),
                syntax.PhaseDecl(None, the_phase, pcs)
            ])

            automaton.resolve(prog.scope)

        self.automaton = PhaseAutomaton(automaton)
        self.fs: List[Frame] = []
        self.push_cache: List[Dict[Phase, Set[Expr]]] = []
        self.counter = 0
        self.predicates: List[Expr] = []
        self.state_count = 0

        self.inductive_invariant: Set[int] = set(
        )  # indices into predicates of currently inductive predicates
        self.human_invariant = tuple(
            itertools.chain(*(syntax.as_clauses(inv.expr)
                              for inv in prog.invs()
                              if not inv.is_safety)))  # convert to CNF
        self.human_invariant_to_predicate: Dict[int, int] = dict(
        )  # dict mapping index of human_invariant to index of predicates
        self.human_invariant_proved: Set[int] = set(
        )  # indices into human_invariant that are implied by the current inductive_invariant
        self.human_invariant_implies: Set[int] = set(
        )  # indices into predicates of predicates that are implied by the human invariant

        self._first_frame()
Пример #8
0
def verify(s: Solver) -> None:
    old_count = utils.error_count
    prog = syntax.the_program
    a = prog.the_automaton()
    if a is None:
        if utils.args.automaton == 'only':
            utils.print_error_and_exit(None, "--automaton='only' requires the file to declare an automaton")
    elif utils.args.automaton != 'no':
        check_automaton_full(s, a)

    if utils.args.automaton != 'only':
        logic.check_init(s)
        logic.check_transitions(s)

    if utils.error_count == old_count:
        utils.logger.always_print('all ok!')
    else:
        utils.logger.always_print('program has errors.')
Пример #9
0
         'semi-linear'),
    ]
    for e_str, prop_name in thm_expr_strs:
        e = logic.parse_and_typecheck_expr(e_str, close_free_vars=True)
        th = syntax.TheoremDecl(name=None, expr=e, num_states=0)
        if (m := logic.check_theorem(th, solve, verbose=False)) is not None:
            utils.error_count += 1
            utils.logger.always_print(
                f'warning: relation {order_name} is not {prop_name}')
            utils.logger.always_print(f'info: try adding "axiom {e_str}"')
            utils.logger.always_print('info: see counterexample below')
            sortdecl.annotations = ()
            utils.logger.always_print(str(m))
    if utils.error_count > old_error_count:
        utils.print_error_and_exit(
            None,
            f'ordered_by_printer: relation {order_name} is not a total order. aborting...'
        )
    ordinal = get_ordinal(struct.rel_interps[order], elt)
    return f'{sortdecl.name}{ordinal}'


def set_printer(struct: FirstOrderStructure, s: SortDecl, elt: str,
                args: List[str]) -> str:
    assert len(args) == 1
    member_name = args[0]
    member = get_relation(member_name)

    assert len(member.arity) == 2 and not member.mutable
    set_sort = UninterpretedSort(s.name)
    assert member.arity[1] == set_sort
    item_sort = member.arity[0]