Exemplo n.º 1
0
 def unfold(self):
     if self.opr is self.OprType.lnot:
         return Apply(Const('Coq.Init.Logic.not'), self.l)
     elif self.opr is self.OprType.land:
         return Apply(Ind('Coq.Init.Logic.and', 0), self.l, self.r)
     elif self.opr is self.OprType.lor:
         return Apply(Ind('Coq.Init.Logic.or', 0), self.l, self.r)
     else:
         raise Macro.MacroAbuse("invalid logic operator %s" %
                                (str(self.opr)))
Exemplo n.º 2
0
class NatComparison(Macro):

    oprmap = {
        '<=': Ind('Coq.Init.Peano.le', 0),
        '<': Const('Coq.Init.Peano.lt'),
        '=': Apply(Ind('Coq.Init.Logic.eq', 0), NatType())
    }

    @classmethod
    def name(cls):
        return "net_comparison"

    def __init__(self, opr, l, r):
        assert opr in ('<=', '<',
                       '='), "unsupported comparison operator %s" % opr
        self.opr = opr
        self.l = l
        self.r = r

    def check(self, environment=None):
        _, sideff_l = self.l.check(environment)
        _, sideff_r = self.r.check(environment)
        return Sort.mkProp(), set.union(sideff_l, sideff_r)

    def render(self, environment=None, debug=False):
        return "(%s %s %s)" % (
            self.l.render(environment, debug),
            self.opr,
            self.r.render(environment, debug),
        )

    def unfold(self):
        return Apply(self.oprmap[self.opr], self.l, self.r)
Exemplo n.º 3
0
    def unfold(self):
        if self.value == 0:
            return Construct(self.coq_Z, 0, 0)
        else:
            constructor = Construct(self.coq_Z, 0, 1 if self.value > 0 else 2)
            v = abs(self.value)
            bs = bin(v)[3:]

            # since self.value != 0, at least the highest bit is 1
            result = Construct(self.coq_positive, 0, 2)
            for bit in bs:
                result = Apply(
                    Construct(self.coq_positive, 0, 0 if bit == "1" else 1),
                    result)

            result = Apply(constructor, result)
            return result
Exemplo n.º 4
0
def to_ascii(c):
    bits, c = [], ord(c)
    for i in range(8):
        bits.append(false if c % 2 == 0 else true)
        c >>= 1

    assert c == 0, "cannot unfold non-ascii strings"

    return Apply(_coq_ascii, *bits)
Exemplo n.º 5
0
    def run(cls, g):
        gf = g.formula()
        if isinstance(gf, Apply) and isinstance(gf.func, Const):
            new_goal = Goal(
                Apply(g.env().constant(gf.func.name).body, *gf.args), g.env())

            return Proof(new_goal, new_goal)
        else:
            raise cls.TacticFailure
Exemplo n.º 6
0
    def run(cls, g):
        gf = g.formula()
        if isinstance(gf, Apply) and isinstance(gf.func, Lambda):
            new_formula = gf.func.body.rels_subst([gf.args[0]])
            if len(gf.args) > 1:
                new_formula = Apply(new_formula, *gf.args[1:])

            new_goal = Goal(new_formula, g.env())
            return Proof(new_goal, new_goal)
        else:
            raise cls.TacticFailure
Exemplo n.º 7
0
def tuple(*elems) -> 'Term':
    assert len(elems) > 1, "cannot construct an empty or singeleton tuple"

    t = None
    for elem in reversed(elems):
        if t is None:
            t = elem
        else:
            t = Apply(pair, elem, t)

    return t
Exemplo n.º 8
0
def tuple_nth(t: 'Term', n: int, typ: 'Term' = None) -> 'Term':
    """
    this function automatically generates the nth operator based on a set
    of fst/snd operations
    """

    is_tuple = False
    if typ is not None:
        is_tuple = isinstance(typ, Apply) and typ.func == prod
    else:
        is_tuple = isinstance(t, Apply) and t.func == pair

    if is_tuple:
        fst_type, snd_type = (t if typ is None else typ).args[0:2]
        if n == 0:
            # in this case we are obtaining a middle element in the tuple
            return Apply(fst, fst_type, snd_type, t)
        else:
            return tuple_nth(Apply(snd, fst_type, snd_type, t), n - 1,
                             snd_type)
    else:
        assert n == 0, "you can only obtain the 0th element in a non-tuple"
        return t
Exemplo n.º 9
0
class BinaryNumberExpr(Macro):

    oprmap = {
        '+': None,
        '-': None,
        '*': None,
        '/': None,
        '%': None,
        '&': None,
        '|': None,
        '>>': None,
        '<<': None,
        '>': None,
        '>=': None,
        '<=': Const('Coq.ZArith.BinInt.Z.le'),
        '<': Const('Coq.ZArith.BinInt.Z.lt'),
        '=': Apply(Ind('Coq.Init.Logic.eq', 0), BinaryNumberType()),
        '==': None,
        '!=': None,
    }

    def __init__(self, opr, l, r=None):
        assert opr in self.oprmap, "unsupported operator %s" % opr
        self.opr = opr
        self.l = l
        self.r = r

    def type(self, environment=None):
        return Sort.mkProp()

    def check(self, environment=None):
        _, sideff_l = self.l.check(environment)
        _, sideff_r = self.r.check(environment)
        return Sort.mkProp(), set.union(sideff_l, sideff_r)

    def render(self, environment=None, debug=False):
        return "(%s %s %s)" % (
            self.l.render(environment, debug),
            self.opr,
            self.r.render(environment, debug),
        )

    def unfold(self):
        return Apply(self.oprmap[self.opr], self.l, self.r)
Exemplo n.º 10
0
 def unfold(self):
     return Apply(self.oprmap[self.opr], self.l, self.r)
Exemplo n.º 11
0
 def unfold(self):
     if self.val == 0:
         return Construct("Coq.Init.Datatypes.nat", 0, 0)
     else:
         return Apply(Construct("Coq.Init.Datatypes.nat", 0, 1),
                      NatValue(self.val - 1))
Exemplo n.º 12
0
    def unfold(self):
        coqs = _coq_string_empty
        for c in reversed(self.val):
            coqs = Apply(_coq_string_cons, to_ascii(c), coqs)

        return coqs
Exemplo n.º 13
0
    def run(cls, g):
        gf = g.formula()
        env = g.env()

        # TODO apply induction to a prod, instead of a env
        if isinstance(gf, Prod) and isinstance(gf.arg_type, Ind):
            goal_type = gf.body.type(
                ContextEnvironment(Binding(gf.arg_name, type=gf.arg_type),
                                   env))

            assert isinstance(goal_type, Sort), "goal formula is not a sort."

            thm_prefix = None
            if goal_type.is_type():
                thm_prefix = '_rect'
            elif goal_type.is_prop():
                thm_prefix = '_ind'
            elif goal_type.is_set():
                thm_prefix = '_rec'
            else:
                assert False, "unknown sort : %s" % goal_type

            mutind_name = gf.arg_type.mutind_name
            ind_index = gf.arg_type.ind_index

            # when an inductive is not the only one of a mut-inductive, we can only obtain
            # the full name of the mut-inductive, i.e. Coq.Init.Datatypes.nat
            # however, all the induction theorems are declared with the full name of the
            # corresponding inductive, in other words, we have to generate them ourselves
            ind = env.mutind(mutind_name).inds[ind_index]
            ind_full_segs = mutind_name.split('.')[:-1] + [ind.name]
            ind_full_name = '.'.join(ind_full_segs)
            thm_to_apply = Const(ind_full_name + thm_prefix)

            # type of an induction theorem is usually:
            #
            #     Prop with a hole -> Proof on Constructor 0 -> Proof on Constructor 1 -> ... -> Prop to Prove
            #
            # which is we need to find.
            p_hole = Lambda(gf.arg_name, gf.arg_type, gf.body)

            subgoals = []
            for c in ind.constructors:
                # form of a subgoal is usually:
                #
                #     - P c (e.g. c = O)
                #     - forall x : S1, P (c x) (e.g. c : S1 -> S2)
                #     - ...
                ctyp = c.term().type(env)

                inner = Apply(c.term())
                subgoal = Apply(p_hole, inner)

                # we keep this variable in case there is no argument given to inner
                # then we need to replace the `Apply` term in the original subgoal
                # to its func (inner.func)
                original_subgoal = subgoal

                depth = 0
                while isinstance(ctyp, Prod):
                    if ctyp.arg_type != gf.arg_type:
                        inner.args.append(Rel(depth))
                        subgoal = Prod(ctyp.arg_name, ctyp.arg_type, subgoal)
                        depth += 1
                    else:
                        inner.args.append(Rel(depth + 1))
                        subgoal = Prod(
                            ctyp.arg_name if ctyp.arg_name is not None else
                            'x', ctyp.arg_type,
                            Prod(None, Apply(p_hole, Rel(0)), subgoal))
                        depth += 2

                    ctyp = ctyp.body

                if inner.args == []:
                    original_subgoal.args[0] = inner.func

                subgoals.append(Goal(subgoal, env))

            proof = Proof(
                Apply(thm_to_apply, p_hole,
                      *(map(lambda g: g.formula(), subgoals))), *subgoals)

            print(proof.proof_formula)
            return proof
        else:
            raise cls.TacticFailure