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)))
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)
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
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)
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
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
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
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
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)
def unfold(self): return Apply(self.oprmap[self.opr], self.l, self.r)
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))
def unfold(self): coqs = _coq_string_empty for c in reversed(self.val): coqs = Apply(_coq_string_cons, to_ascii(c), coqs) return coqs
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