adamc@2
|
1 (* Copyright (c) 2008, Adam Chlipala
|
adamc@2
|
2 *
|
adamc@2
|
3 * This work is licensed under a
|
adamc@2
|
4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0
|
adamc@2
|
5 * Unported License.
|
adamc@2
|
6 * The license text is available at:
|
adamc@2
|
7 * http://creativecommons.org/licenses/by-nc-nd/3.0/
|
adamc@2
|
8 *)
|
adamc@2
|
9
|
adamc@85
|
10 Require Import Eqdep List.
|
adamc@2
|
11
|
adamc@38
|
12 Require Omega.
|
adamc@38
|
13
|
adamc@59
|
14 Set Implicit Arguments.
|
adamc@59
|
15
|
adamc@2
|
16
|
adamc@66
|
17 Ltac inject H := injection H; clear H; intros; try subst.
|
adamc@51
|
18
|
adamc@59
|
19 Ltac appHyps f :=
|
adamc@50
|
20 match goal with
|
adamc@59
|
21 | [ H : _ |- _ ] => f H
|
adamc@59
|
22 end.
|
adamc@59
|
23
|
adamc@59
|
24 Ltac inList x ls :=
|
adamc@59
|
25 match ls with
|
adamc@59
|
26 | x => idtac
|
adamc@84
|
27 | (_, x) => idtac
|
adamc@59
|
28 | (?LS, _) => inList x LS
|
adamc@59
|
29 end.
|
adamc@59
|
30
|
adamc@59
|
31 Ltac app f ls :=
|
adamc@59
|
32 match ls with
|
adamc@59
|
33 | (?LS, ?X) => f X || app f LS || fail 1
|
adamc@59
|
34 | _ => f ls
|
adamc@59
|
35 end.
|
adamc@59
|
36
|
adamc@59
|
37 Ltac all f ls :=
|
adamc@59
|
38 match ls with
|
adamc@59
|
39 | (?LS, ?X) => f X; all f LS
|
adamc@59
|
40 | (_, _) => fail 1
|
adamc@59
|
41 | _ => f ls
|
adamc@59
|
42 end.
|
adamc@59
|
43
|
adamc@59
|
44 Ltac simplHyp invOne :=
|
adamc@99
|
45 let invert H F :=
|
adamc@99
|
46 inList F invOne; (inversion H; fail)
|
adamc@99
|
47 || (inversion H; [idtac]; clear H; try subst) in
|
adamc@59
|
48 match goal with
|
adamc@59
|
49 | [ H : ex _ |- _ ] => destruct H
|
adamc@59
|
50
|
adamc@160
|
51 | [ H : ?F ?X = ?F ?Y |- _ ] => injection H;
|
adamc@51
|
52 match goal with
|
adamc@160
|
53 | [ |- F X = F Y -> _ ] => fail 1
|
adamc@85
|
54 | [ |- _ = _ -> _ ] => try clear H; intros; try subst
|
adamc@51
|
55 end
|
adamc@51
|
56 | [ H : ?F _ _ = ?F _ _ |- _ ] => injection H;
|
adamc@51
|
57 match goal with
|
adamc@85
|
58 | [ |- _ = _ -> _ = _ -> _ ] => try clear H; intros; try subst
|
adamc@51
|
59 end
|
adamc@59
|
60
|
adamc@99
|
61 | [ H : ?F _ |- _ ] => invert H F
|
adamc@99
|
62 | [ H : ?F _ _ |- _ ] => invert H F
|
adamc@99
|
63 | [ H : ?F _ _ _ |- _ ] => invert H F
|
adamc@99
|
64 | [ H : ?F _ _ _ _ |- _ ] => invert H F
|
adamc@99
|
65 | [ H : ?F _ _ _ _ _ |- _ ] => invert H F
|
adamc@176
|
66
|
adamc@176
|
67 | [ H : existT _ ?T _ = existT _ ?T _ |- _ ] => generalize (inj_pair2 _ _ _ _ _ H); clear H
|
adamc@176
|
68 | [ H : existT _ _ _ = existT _ _ _ |- _ ] => inversion H; clear H
|
adamc@50
|
69 end.
|
adamc@50
|
70
|
adamc@2
|
71 Ltac rewriteHyp :=
|
adamc@2
|
72 match goal with
|
adamc@2
|
73 | [ H : _ |- _ ] => rewrite H
|
adamc@2
|
74 end.
|
adamc@2
|
75
|
adamc@2
|
76 Ltac rewriterP := repeat (rewriteHyp; autorewrite with cpdt in *).
|
adamc@2
|
77
|
adamc@2
|
78 Ltac rewriter := autorewrite with cpdt in *; rewriterP.
|
adamc@2
|
79
|
adamc@2
|
80 Hint Rewrite app_ass : cpdt.
|
adamc@2
|
81
|
adamc@59
|
82 Definition done (T : Type) (x : T) := True.
|
adamc@2
|
83
|
adamc@59
|
84 Ltac inster e trace :=
|
adamc@59
|
85 match type of e with
|
adamc@59
|
86 | forall x : _, _ =>
|
adamc@59
|
87 match goal with
|
adamc@59
|
88 | [ H : _ |- _ ] =>
|
adamc@59
|
89 inster (e H) (trace, H)
|
adamc@59
|
90 | _ => fail 2
|
adamc@59
|
91 end
|
adamc@59
|
92 | _ =>
|
adamc@59
|
93 match trace with
|
adamc@59
|
94 | (_, _) =>
|
adamc@59
|
95 match goal with
|
adamc@59
|
96 | [ H : done (trace, _) |- _ ] => fail 1
|
adamc@59
|
97 | _ =>
|
adamc@59
|
98 let T := type of e in
|
adamc@59
|
99 match type of T with
|
adamc@59
|
100 | Prop =>
|
adamc@59
|
101 generalize e; intro;
|
adamc@59
|
102 assert (done (trace, tt)); [constructor | idtac]
|
adamc@59
|
103 | _ =>
|
adamc@59
|
104 all ltac:(fun X =>
|
adamc@59
|
105 match goal with
|
adamc@59
|
106 | [ H : done (_, X) |- _ ] => fail 1
|
adamc@59
|
107 | _ => idtac
|
adamc@59
|
108 end) trace;
|
adamc@59
|
109 let i := fresh "i" in (pose (i := e);
|
adamc@59
|
110 assert (done (trace, i)); [constructor | idtac])
|
adamc@59
|
111 end
|
adamc@59
|
112 end
|
adamc@59
|
113 end
|
adamc@59
|
114 end.
|
adamc@59
|
115
|
adamc@65
|
116 Ltac un_done :=
|
adamc@65
|
117 repeat match goal with
|
adamc@65
|
118 | [ H : done _ |- _ ] => clear H
|
adamc@65
|
119 end.
|
adamc@65
|
120
|
adamc@88
|
121 Ltac crush' lemmas invOne :=
|
adamc@66
|
122 let sintuition := simpl in *; intuition; try subst; repeat (simplHyp invOne; intuition; try subst); try congruence
|
adamc@59
|
123 in (sintuition; rewriter;
|
adamc@88
|
124 match lemmas with
|
adamc@88
|
125 | false => idtac
|
adamc@88
|
126 | _ => repeat ((app ltac:(fun L => inster L L) lemmas || appHyps ltac:(fun L => inster L L));
|
adamc@86
|
127 repeat (simplHyp invOne; intuition)); un_done
|
adamc@86
|
128 end; sintuition; try omega; try (elimtype False; omega)).
|
adamc@59
|
129
|
adamc@88
|
130 Ltac crush := crush' false fail.
|
adamc@85
|
131
|
adamc@85
|
132 Theorem dep_destruct : forall (T : Type) (T' : T -> Type) x (v : T' x) (P : T' x -> Prop),
|
adamc@85
|
133 (forall x' (v' : T' x') (Heq : x' = x), P (match Heq in (_ = x) return (T' x) with
|
adamc@85
|
134 | refl_equal => v'
|
adamc@85
|
135 end))
|
adamc@85
|
136 -> P v.
|
adamc@85
|
137 intros.
|
adamc@85
|
138 generalize (H _ v (refl_equal _)); trivial.
|
adamc@85
|
139 Qed.
|
adamc@85
|
140
|
adamc@85
|
141 Ltac dep_destruct E :=
|
adamc@85
|
142 let doit A :=
|
adamc@85
|
143 let T := type of A in
|
adamc@85
|
144 generalize dependent E;
|
adamc@85
|
145 let e := fresh "e" in
|
adamc@85
|
146 intro e; pattern e;
|
adamc@85
|
147 apply (@dep_destruct T);
|
adamc@85
|
148 let x := fresh "x" with v := fresh "v" in
|
adamc@85
|
149 intros x v; destruct v; crush;
|
adamc@85
|
150 let bestEffort Heq E tac :=
|
adamc@85
|
151 repeat match goal with
|
adamc@85
|
152 | [ H : context[E] |- _ ] =>
|
adamc@85
|
153 match H with
|
adamc@85
|
154 | Heq => fail 1
|
adamc@85
|
155 | _ => generalize dependent H
|
adamc@85
|
156 end
|
adamc@85
|
157 end;
|
adamc@85
|
158 generalize Heq; tac Heq; clear Heq; intro Heq;
|
adamc@85
|
159 rewrite (UIP_refl _ _ Heq); intros in
|
adamc@85
|
160 repeat match goal with
|
adamc@85
|
161 | [ Heq : ?X = ?X |- _ ] =>
|
adamc@85
|
162 generalize (UIP_refl _ _ Heq); intro; subst; clear Heq
|
adamc@85
|
163 | [ Heq : ?E = _ |- _ ] => bestEffort Heq E ltac:(fun E => rewrite E)
|
adamc@85
|
164 | [ Heq : _ = ?E |- _ ] => bestEffort Heq E ltac:(fun E => rewrite <- E)
|
adamc@85
|
165 end
|
adamc@85
|
166 in match type of E with
|
adamc@173
|
167 | _ ?A => doit A
|
adamc@85
|
168 | _ _ ?A => doit A
|
adamc@173
|
169 | _ _ _ ?A => doit A
|
adamc@85
|
170 end.
|
adamc@118
|
171
|
adamc@118
|
172 Ltac clear_all :=
|
adamc@118
|
173 repeat match goal with
|
adamc@118
|
174 | [ H : _ |- _ ] => clear H
|
adamc@118
|
175 end.
|