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