Beispiel #1
0
    def __init__(self, rule, args, prevs=None, th=None):
        typecheck.checkinstance('ProofTerm', rule, str)

        self.rule = rule
        if prevs is None:
            prevs = []
        prev_ths = [prev.th for prev in prevs]
        if rule == 'atom':
            assert th is not None, "ProofTerm: must provide th for atom."
            self.th = th
        elif rule == 'sorry':
            assert th is not None, "ProofTerm: must provide th for sorry."
            self.th = th
        elif rule == 'variable':
            nm, T = args
            self.th = Thm.mk_VAR(Var(nm, T))
        elif rule == 'theorem':
            self.th = theory.get_theorem(args)
        elif rule in primitive_deriv:
            rule_fun, _ = primitive_deriv[rule]
            self.th = rule_fun(*prev_ths) if args is None else rule_fun(args, *prev_ths)
        else:
            macro = theory.get_macro(rule)
            if th is None:
                self.th = macro.eval(args, prev_ths)
            else:
                self.th = th
        self.args = args
        self.prevs = prevs
        if self.rule == 'sorry':
            self.gaps = [self.th]
        else:
            self.gaps = list(set(sum([prev.gaps for prev in self.prevs], [])))
Beispiel #2
0
    def _check_proof_item(self, prf, seq, rpt, no_gaps, compute_only,
                          check_level):
        """Check a single proof item.

        prf -- proof to be checked.
        seq -- proof item to be checked.
        rpt -- report for proof-checking. Modified by the function.
        no_gaps -- disable gaps.
        compute_only -- only executes rule if theorem is not present.
        check_level -- trust level for proof checking. Trust all macros
            with macro.level <= self.check_level.
        
        """
        if seq.rule == "":
            # Empty line in the proof
            return None

        if seq.rule == "sorry":
            # Gap in the proof
            assert seq.th is not None, "sorry must have explicit statement."
            if no_gaps:
                raise CheckProofException("gaps are not allowed")
            if rpt is not None:
                rpt.add_gap(seq.th)
            return None

        if compute_only and seq.th is not None:
            # In compute_only mode, skip when a theorem exists. However,
            # subproofs still need to be checked.
            if seq.rule == "subproof":
                for s in seq.subproof.items:
                    self._check_proof_item(prf, s, rpt, no_gaps, compute_only,
                                           check_level)
            return None

        if seq.rule == "theorem":
            # Copies an existing theorem in the theory into the proof.
            try:
                res_th = self.get_theorem(seq.args)
                if rpt is not None:
                    rpt.apply_theorem(seq.args)
            except TheoryException:
                raise CheckProofException("theorem not found")
        elif seq.rule == "variable":
            # Declares a variable. Skip check.
            nm, T = seq.args
            res_th = Thm.mk_VAR(Var(nm, T))
        elif seq.rule == "subproof":
            for s in seq.subproof.items:
                self._check_proof_item(prf, s, rpt, no_gaps, compute_only,
                                       check_level)
            res_th = seq.subproof.items[-1].th
        else:
            # Otherwise, apply one of the proof methods. First, we
            # obtain list of previous sequents used by the proof method:
            prev_ths = []
            assert isinstance(seq.prevs, list), "prevs should be a list"
            for prev in seq.prevs:
                if not seq.id.can_depend_on(prev):
                    raise CheckProofException("id %s cannot depend on %s" %
                                              (seq.id, prev))
                try:
                    prev_ths.append(prf.find_item(prev).th)
                except ProofStateException:
                    raise CheckProofException("previous item not found")

            for prev, prev_th in zip(seq.prevs, prev_ths):
                if prev_th is None:
                    raise CheckProofException("previous theorem %s is None" %
                                              prev)

            if seq.rule in primitive_deriv:
                # If the method is one of the primitive derivations, obtain and
                # apply that primitive derivation.
                rule_fun, _ = primitive_deriv[seq.rule]
                try:
                    res_th = rule_fun(
                        *prev_ths) if seq.args is None else rule_fun(
                            seq.args, *prev_ths)
                    if rpt is not None:
                        rpt.apply_primitive_deriv()
                except InvalidDerivationException:
                    raise CheckProofException("invalid derivation")
                except TypeError:
                    raise CheckProofException("invalid input to derivation " +
                                              seq.rule)

            elif has_macro(seq.rule):
                # Otherwise, the proof method corresponds to a macro. If
                # the level of the macro is less than or equal to the current
                # trust level, simply evaluate the macro to check that results
                # match. Otherwise, expand the macro and check all of the steps.
                macro = get_macro(seq.rule)
                assert macro.level is None or (isinstance(macro.level, int) and macro.level >= 0), \
                    ("check_proof: invalid macro level " + str(macro.level))
                if macro.level is not None and macro.level <= check_level:
                    res_th = macro.eval(seq.args, prev_ths)
                    if rpt is not None:
                        rpt.eval_macro(seq.rule)
                else:
                    seq.subproof = macro.expand(seq.id, seq.args,
                                                list(zip(seq.prevs, prev_ths)))
                    if rpt is not None:
                        rpt.expand_macro(seq.rule)
                    for s in seq.subproof.items:
                        self._check_proof_item(prf, s, rpt, no_gaps,
                                               compute_only, check_level)
                    res_th = seq.subproof.items[-1].th
                    seq.subproof = None
            else:
                raise CheckProofException("proof method not found: " +
                                          seq.rule)

        if seq.th is None:
            # No expected theorem is provided
            seq.th = res_th
        elif not res_th.can_prove(seq.th):
            # Resulting res_th is OK as long as the conclusion is the same,
            # and the assumptions is a subset of that of seq.th.
            raise CheckProofException("output does not match\n" + str(seq.th) +
                                      "\n vs.\n" + str(res_th))

        # Check the current statement is correctly typed.
        try:
            seq.th.check_thm_type()
        except TypeCheckException:
            raise CheckProofException("typing error")

        return None