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@50
|
66 end.
|
adamc@50
|
67
|
adamc@2
|
68 Ltac rewriteHyp :=
|
adamc@2
|
69 match goal with
|
adamc@2
|
70 | [ H : _ |- _ ] => rewrite H
|
adamc@2
|
71 end.
|
adamc@2
|
72
|
adamc@2
|
73 Ltac rewriterP := repeat (rewriteHyp; autorewrite with cpdt in *).
|
adamc@2
|
74
|
adamc@2
|
75 Ltac rewriter := autorewrite with cpdt in *; rewriterP.
|
adamc@2
|
76
|
adamc@2
|
77 Hint Rewrite app_ass : cpdt.
|
adamc@2
|
78
|
adamc@59
|
79 Definition done (T : Type) (x : T) := True.
|
adamc@2
|
80
|
adamc@59
|
81 Ltac inster e trace :=
|
adamc@59
|
82 match type of e with
|
adamc@59
|
83 | forall x : _, _ =>
|
adamc@59
|
84 match goal with
|
adamc@59
|
85 | [ H : _ |- _ ] =>
|
adamc@59
|
86 inster (e H) (trace, H)
|
adamc@59
|
87 | _ => fail 2
|
adamc@59
|
88 end
|
adamc@59
|
89 | _ =>
|
adamc@59
|
90 match trace with
|
adamc@59
|
91 | (_, _) =>
|
adamc@59
|
92 match goal with
|
adamc@59
|
93 | [ H : done (trace, _) |- _ ] => fail 1
|
adamc@59
|
94 | _ =>
|
adamc@59
|
95 let T := type of e in
|
adamc@59
|
96 match type of T with
|
adamc@59
|
97 | Prop =>
|
adamc@59
|
98 generalize e; intro;
|
adamc@59
|
99 assert (done (trace, tt)); [constructor | idtac]
|
adamc@59
|
100 | _ =>
|
adamc@59
|
101 all ltac:(fun X =>
|
adamc@59
|
102 match goal with
|
adamc@59
|
103 | [ H : done (_, X) |- _ ] => fail 1
|
adamc@59
|
104 | _ => idtac
|
adamc@59
|
105 end) trace;
|
adamc@59
|
106 let i := fresh "i" in (pose (i := e);
|
adamc@59
|
107 assert (done (trace, i)); [constructor | idtac])
|
adamc@59
|
108 end
|
adamc@59
|
109 end
|
adamc@59
|
110 end
|
adamc@59
|
111 end.
|
adamc@59
|
112
|
adamc@65
|
113 Ltac un_done :=
|
adamc@65
|
114 repeat match goal with
|
adamc@65
|
115 | [ H : done _ |- _ ] => clear H
|
adamc@65
|
116 end.
|
adamc@65
|
117
|
adamc@88
|
118 Ltac crush' lemmas invOne :=
|
adamc@66
|
119 let sintuition := simpl in *; intuition; try subst; repeat (simplHyp invOne; intuition; try subst); try congruence
|
adamc@59
|
120 in (sintuition; rewriter;
|
adamc@88
|
121 match lemmas with
|
adamc@88
|
122 | false => idtac
|
adamc@88
|
123 | _ => repeat ((app ltac:(fun L => inster L L) lemmas || appHyps ltac:(fun L => inster L L));
|
adamc@86
|
124 repeat (simplHyp invOne; intuition)); un_done
|
adamc@86
|
125 end; sintuition; try omega; try (elimtype False; omega)).
|
adamc@59
|
126
|
adamc@88
|
127 Ltac crush := crush' false fail.
|
adamc@85
|
128
|
adamc@85
|
129 Theorem dep_destruct : forall (T : Type) (T' : T -> Type) x (v : T' x) (P : T' x -> Prop),
|
adamc@85
|
130 (forall x' (v' : T' x') (Heq : x' = x), P (match Heq in (_ = x) return (T' x) with
|
adamc@85
|
131 | refl_equal => v'
|
adamc@85
|
132 end))
|
adamc@85
|
133 -> P v.
|
adamc@85
|
134 intros.
|
adamc@85
|
135 generalize (H _ v (refl_equal _)); trivial.
|
adamc@85
|
136 Qed.
|
adamc@85
|
137
|
adamc@85
|
138 Ltac dep_destruct E :=
|
adamc@85
|
139 let doit A :=
|
adamc@85
|
140 let T := type of A in
|
adamc@85
|
141 generalize dependent E;
|
adamc@85
|
142 let e := fresh "e" in
|
adamc@85
|
143 intro e; pattern e;
|
adamc@85
|
144 apply (@dep_destruct T);
|
adamc@85
|
145 let x := fresh "x" with v := fresh "v" in
|
adamc@85
|
146 intros x v; destruct v; crush;
|
adamc@85
|
147 let bestEffort Heq E tac :=
|
adamc@85
|
148 repeat match goal with
|
adamc@85
|
149 | [ H : context[E] |- _ ] =>
|
adamc@85
|
150 match H with
|
adamc@85
|
151 | Heq => fail 1
|
adamc@85
|
152 | _ => generalize dependent H
|
adamc@85
|
153 end
|
adamc@85
|
154 end;
|
adamc@85
|
155 generalize Heq; tac Heq; clear Heq; intro Heq;
|
adamc@85
|
156 rewrite (UIP_refl _ _ Heq); intros in
|
adamc@85
|
157 repeat match goal with
|
adamc@85
|
158 | [ Heq : ?X = ?X |- _ ] =>
|
adamc@85
|
159 generalize (UIP_refl _ _ Heq); intro; subst; clear Heq
|
adamc@85
|
160 | [ Heq : ?E = _ |- _ ] => bestEffort Heq E ltac:(fun E => rewrite E)
|
adamc@85
|
161 | [ Heq : _ = ?E |- _ ] => bestEffort Heq E ltac:(fun E => rewrite <- E)
|
adamc@85
|
162 end
|
adamc@85
|
163 in match type of E with
|
adamc@173
|
164 | _ ?A => doit A
|
adamc@85
|
165 | _ _ ?A => doit A
|
adamc@173
|
166 | _ _ _ ?A => doit A
|
adamc@85
|
167 end.
|
adamc@118
|
168
|
adamc@118
|
169 Ltac clear_all :=
|
adamc@118
|
170 repeat match goal with
|
adamc@118
|
171 | [ H : _ |- _ ] => clear H
|
adamc@118
|
172 end.
|