adamc@175
|
1 (* Copyright (c) 2008, Adam Chlipala
|
adamc@175
|
2 *
|
adamc@175
|
3 * This work is licensed under a
|
adamc@175
|
4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0
|
adamc@175
|
5 * Unported License.
|
adamc@175
|
6 * The license text is available at:
|
adamc@175
|
7 * http://creativecommons.org/licenses/by-nc-nd/3.0/
|
adamc@175
|
8 *)
|
adamc@175
|
9
|
adamc@175
|
10 (* begin hide *)
|
adamc@175
|
11 Require Import String List.
|
adamc@175
|
12
|
adamc@177
|
13 Require Import AxiomsImpred Tactics DepList.
|
adamc@175
|
14
|
adamc@175
|
15 Set Implicit Arguments.
|
adamc@175
|
16 (* end hide *)
|
adamc@175
|
17
|
adamc@175
|
18
|
adamc@175
|
19 (** %\chapter{Certifying Extensional Transformations}% *)
|
adamc@175
|
20
|
adamc@175
|
21 (** TODO: Prose for this chapter *)
|
adamc@175
|
22
|
adamc@175
|
23
|
adamc@175
|
24 (** * Simply-Typed Lambda Calculus *)
|
adamc@175
|
25
|
adamc@175
|
26 Module STLC.
|
adamc@175
|
27 Module Source.
|
adamc@175
|
28 Inductive type : Type :=
|
adamc@175
|
29 | TNat : type
|
adamc@175
|
30 | Arrow : type -> type -> type.
|
adamc@175
|
31
|
adamc@175
|
32 Notation "'Nat'" := TNat : source_scope.
|
adamc@175
|
33 Infix "-->" := Arrow (right associativity, at level 60) : source_scope.
|
adamc@175
|
34
|
adamc@175
|
35 Open Scope source_scope.
|
adamc@175
|
36 Bind Scope source_scope with type.
|
adamc@175
|
37 Delimit Scope source_scope with source.
|
adamc@175
|
38
|
adamc@175
|
39 Section vars.
|
adamc@175
|
40 Variable var : type -> Type.
|
adamc@175
|
41
|
adamc@175
|
42 Inductive exp : type -> Type :=
|
adamc@175
|
43 | Var : forall t,
|
adamc@175
|
44 var t
|
adamc@175
|
45 -> exp t
|
adamc@175
|
46
|
adamc@175
|
47 | Const : nat -> exp Nat
|
adamc@175
|
48 | Plus : exp Nat -> exp Nat -> exp Nat
|
adamc@175
|
49
|
adamc@175
|
50 | App : forall t1 t2,
|
adamc@175
|
51 exp (t1 --> t2)
|
adamc@175
|
52 -> exp t1
|
adamc@175
|
53 -> exp t2
|
adamc@175
|
54 | Abs : forall t1 t2,
|
adamc@175
|
55 (var t1 -> exp t2)
|
adamc@175
|
56 -> exp (t1 --> t2).
|
adamc@175
|
57 End vars.
|
adamc@175
|
58
|
adamc@175
|
59 Definition Exp t := forall var, exp var t.
|
adamc@175
|
60
|
adamc@175
|
61 Implicit Arguments Var [var t].
|
adamc@175
|
62 Implicit Arguments Const [var].
|
adamc@175
|
63 Implicit Arguments Plus [var].
|
adamc@175
|
64 Implicit Arguments App [var t1 t2].
|
adamc@175
|
65 Implicit Arguments Abs [var t1 t2].
|
adamc@175
|
66
|
adamc@175
|
67 Notation "# v" := (Var v) (at level 70) : source_scope.
|
adamc@175
|
68
|
adamc@175
|
69 Notation "^ n" := (Const n) (at level 70) : source_scope.
|
adamc@175
|
70 Infix "+^" := Plus (left associativity, at level 79) : source_scope.
|
adamc@175
|
71
|
adamc@175
|
72 Infix "@" := App (left associativity, at level 77) : source_scope.
|
adamc@175
|
73 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : source_scope.
|
adamc@175
|
74 Notation "\ ! , e" := (Abs (fun _ => e)) (at level 78) : source_scope.
|
adamc@175
|
75
|
adamc@175
|
76 Bind Scope source_scope with exp.
|
adamc@175
|
77
|
adamc@175
|
78 Definition zero : Exp Nat := fun _ => ^0.
|
adamc@175
|
79 Definition one : Exp Nat := fun _ => ^1.
|
adamc@175
|
80 Definition zpo : Exp Nat := fun _ => zero _ +^ one _.
|
adamc@175
|
81 Definition ident : Exp (Nat --> Nat) := fun _ => \x, #x.
|
adamc@175
|
82 Definition app_ident : Exp Nat := fun _ => ident _ @ zpo _.
|
adamc@175
|
83 Definition app : Exp ((Nat --> Nat) --> Nat --> Nat) := fun _ =>
|
adamc@175
|
84 \f, \x, #f @ #x.
|
adamc@175
|
85 Definition app_ident' : Exp Nat := fun _ => app _ @ ident _ @ zpo _.
|
adamc@175
|
86
|
adamc@175
|
87 Fixpoint typeDenote (t : type) : Set :=
|
adamc@175
|
88 match t with
|
adamc@175
|
89 | Nat => nat
|
adamc@175
|
90 | t1 --> t2 => typeDenote t1 -> typeDenote t2
|
adamc@175
|
91 end.
|
adamc@175
|
92
|
adamc@175
|
93 Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t :=
|
adamc@175
|
94 match e in (exp _ t) return (typeDenote t) with
|
adamc@175
|
95 | Var _ v => v
|
adamc@175
|
96
|
adamc@175
|
97 | Const n => n
|
adamc@175
|
98 | Plus e1 e2 => expDenote e1 + expDenote e2
|
adamc@175
|
99
|
adamc@175
|
100 | App _ _ e1 e2 => (expDenote e1) (expDenote e2)
|
adamc@175
|
101 | Abs _ _ e' => fun x => expDenote (e' x)
|
adamc@175
|
102 end.
|
adamc@175
|
103
|
adamc@175
|
104 Definition ExpDenote t (e : Exp t) := expDenote (e _).
|
adamc@176
|
105
|
adamc@180
|
106 (* begin thide *)
|
adamc@176
|
107 Section exp_equiv.
|
adamc@176
|
108 Variables var1 var2 : type -> Type.
|
adamc@176
|
109
|
adamc@176
|
110 Inductive exp_equiv : list { t : type & var1 t * var2 t }%type -> forall t, exp var1 t -> exp var2 t -> Prop :=
|
adamc@176
|
111 | EqEVar : forall G t (v1 : var1 t) v2,
|
adamc@176
|
112 In (existT _ t (v1, v2)) G
|
adamc@176
|
113 -> exp_equiv G (#v1) (#v2)
|
adamc@176
|
114
|
adamc@176
|
115 | EqEConst : forall G n,
|
adamc@176
|
116 exp_equiv G (^n) (^n)
|
adamc@176
|
117 | EqEPlus : forall G x1 y1 x2 y2,
|
adamc@176
|
118 exp_equiv G x1 x2
|
adamc@176
|
119 -> exp_equiv G y1 y2
|
adamc@176
|
120 -> exp_equiv G (x1 +^ y1) (x2 +^ y2)
|
adamc@176
|
121
|
adamc@176
|
122 | EqEApp : forall G t1 t2 (f1 : exp _ (t1 --> t2)) (x1 : exp _ t1) f2 x2,
|
adamc@176
|
123 exp_equiv G f1 f2
|
adamc@176
|
124 -> exp_equiv G x1 x2
|
adamc@176
|
125 -> exp_equiv G (f1 @ x1) (f2 @ x2)
|
adamc@176
|
126 | EqEAbs : forall G t1 t2 (f1 : var1 t1 -> exp var1 t2) f2,
|
adamc@176
|
127 (forall v1 v2, exp_equiv (existT _ t1 (v1, v2) :: G) (f1 v1) (f2 v2))
|
adamc@176
|
128 -> exp_equiv G (Abs f1) (Abs f2).
|
adamc@176
|
129 End exp_equiv.
|
adamc@176
|
130
|
adamc@176
|
131 Axiom Exp_equiv : forall t (E : Exp t) var1 var2,
|
adamc@176
|
132 exp_equiv nil (E var1) (E var2).
|
adamc@180
|
133 (* end thide *)
|
adamc@175
|
134 End Source.
|
adamc@175
|
135
|
adamc@175
|
136 Module CPS.
|
adamc@175
|
137 Inductive type : Type :=
|
adamc@175
|
138 | TNat : type
|
adamc@175
|
139 | Cont : type -> type
|
adamc@175
|
140 | TUnit : type
|
adamc@175
|
141 | Prod : type -> type -> type.
|
adamc@175
|
142
|
adamc@175
|
143 Notation "'Nat'" := TNat : cps_scope.
|
adamc@175
|
144 Notation "'Unit'" := TUnit : cps_scope.
|
adamc@175
|
145 Notation "t --->" := (Cont t) (at level 61) : cps_scope.
|
adamc@175
|
146 Infix "**" := Prod (right associativity, at level 60) : cps_scope.
|
adamc@175
|
147
|
adamc@175
|
148 Bind Scope cps_scope with type.
|
adamc@175
|
149 Delimit Scope cps_scope with cps.
|
adamc@175
|
150
|
adamc@175
|
151 Section vars.
|
adamc@175
|
152 Variable var : type -> Type.
|
adamc@175
|
153
|
adamc@175
|
154 Inductive prog : Type :=
|
adamc@175
|
155 | PHalt :
|
adamc@175
|
156 var Nat
|
adamc@175
|
157 -> prog
|
adamc@175
|
158 | App : forall t,
|
adamc@175
|
159 var (t --->)
|
adamc@175
|
160 -> var t
|
adamc@175
|
161 -> prog
|
adamc@175
|
162 | Bind : forall t,
|
adamc@175
|
163 primop t
|
adamc@175
|
164 -> (var t -> prog)
|
adamc@175
|
165 -> prog
|
adamc@175
|
166
|
adamc@175
|
167 with primop : type -> Type :=
|
adamc@175
|
168 | Var : forall t,
|
adamc@175
|
169 var t
|
adamc@175
|
170 -> primop t
|
adamc@175
|
171
|
adamc@175
|
172 | Const : nat -> primop Nat
|
adamc@175
|
173 | Plus : var Nat -> var Nat -> primop Nat
|
adamc@175
|
174
|
adamc@175
|
175 | Abs : forall t,
|
adamc@175
|
176 (var t -> prog)
|
adamc@175
|
177 -> primop (t --->)
|
adamc@175
|
178
|
adamc@175
|
179 | Pair : forall t1 t2,
|
adamc@175
|
180 var t1
|
adamc@175
|
181 -> var t2
|
adamc@175
|
182 -> primop (t1 ** t2)
|
adamc@175
|
183 | Fst : forall t1 t2,
|
adamc@175
|
184 var (t1 ** t2)
|
adamc@175
|
185 -> primop t1
|
adamc@175
|
186 | Snd : forall t1 t2,
|
adamc@175
|
187 var (t1 ** t2)
|
adamc@175
|
188 -> primop t2.
|
adamc@175
|
189 End vars.
|
adamc@175
|
190
|
adamc@175
|
191 Implicit Arguments PHalt [var].
|
adamc@175
|
192 Implicit Arguments App [var t].
|
adamc@175
|
193
|
adamc@175
|
194 Implicit Arguments Var [var t].
|
adamc@175
|
195 Implicit Arguments Const [var].
|
adamc@175
|
196 Implicit Arguments Plus [var].
|
adamc@175
|
197 Implicit Arguments Abs [var t].
|
adamc@175
|
198 Implicit Arguments Pair [var t1 t2].
|
adamc@175
|
199 Implicit Arguments Fst [var t1 t2].
|
adamc@175
|
200 Implicit Arguments Snd [var t1 t2].
|
adamc@175
|
201
|
adamc@175
|
202 Notation "'Halt' x" := (PHalt x) (no associativity, at level 75) : cps_scope.
|
adamc@175
|
203 Infix "@@" := App (no associativity, at level 75) : cps_scope.
|
adamc@175
|
204 Notation "x <- p ; e" := (Bind p (fun x => e))
|
adamc@175
|
205 (right associativity, at level 76, p at next level) : cps_scope.
|
adamc@175
|
206 Notation "! <- p ; e" := (Bind p (fun _ => e))
|
adamc@175
|
207 (right associativity, at level 76, p at next level) : cps_scope.
|
adamc@175
|
208
|
adamc@175
|
209 Notation "# v" := (Var v) (at level 70) : cps_scope.
|
adamc@175
|
210
|
adamc@175
|
211 Notation "^ n" := (Const n) (at level 70) : cps_scope.
|
adamc@175
|
212 Infix "+^" := Plus (left associativity, at level 79) : cps_scope.
|
adamc@175
|
213
|
adamc@175
|
214 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : cps_scope.
|
adamc@175
|
215 Notation "\ ! , e" := (Abs (fun _ => e)) (at level 78) : cps_scope.
|
adamc@175
|
216
|
adamc@179
|
217 Notation "[ x1 , x2 ]" := (Pair x1 x2) : cps_scope.
|
adamc@175
|
218 Notation "#1 x" := (Fst x) (at level 72) : cps_scope.
|
adamc@175
|
219 Notation "#2 x" := (Snd x) (at level 72) : cps_scope.
|
adamc@175
|
220
|
adamc@175
|
221 Bind Scope cps_scope with prog primop.
|
adamc@175
|
222
|
adamc@175
|
223 Open Scope cps_scope.
|
adamc@175
|
224
|
adamc@175
|
225 Fixpoint typeDenote (t : type) : Set :=
|
adamc@175
|
226 match t with
|
adamc@175
|
227 | Nat => nat
|
adamc@175
|
228 | t' ---> => typeDenote t' -> nat
|
adamc@175
|
229 | Unit => unit
|
adamc@175
|
230 | t1 ** t2 => (typeDenote t1 * typeDenote t2)%type
|
adamc@175
|
231 end.
|
adamc@175
|
232
|
adamc@175
|
233 Fixpoint progDenote (e : prog typeDenote) : nat :=
|
adamc@175
|
234 match e with
|
adamc@175
|
235 | PHalt n => n
|
adamc@175
|
236 | App _ f x => f x
|
adamc@175
|
237 | Bind _ p x => progDenote (x (primopDenote p))
|
adamc@175
|
238 end
|
adamc@175
|
239
|
adamc@175
|
240 with primopDenote t (p : primop typeDenote t) {struct p} : typeDenote t :=
|
adamc@175
|
241 match p in (primop _ t) return (typeDenote t) with
|
adamc@175
|
242 | Var _ v => v
|
adamc@175
|
243
|
adamc@175
|
244 | Const n => n
|
adamc@175
|
245 | Plus n1 n2 => n1 + n2
|
adamc@175
|
246
|
adamc@175
|
247 | Abs _ e => fun x => progDenote (e x)
|
adamc@175
|
248
|
adamc@175
|
249 | Pair _ _ v1 v2 => (v1, v2)
|
adamc@175
|
250 | Fst _ _ v => fst v
|
adamc@175
|
251 | Snd _ _ v => snd v
|
adamc@175
|
252 end.
|
adamc@175
|
253
|
adamc@175
|
254 Definition Prog := forall var, prog var.
|
adamc@175
|
255 Definition Primop t := forall var, primop var t.
|
adamc@175
|
256 Definition ProgDenote (E : Prog) := progDenote (E _).
|
adamc@175
|
257 Definition PrimopDenote t (P : Primop t) := primopDenote (P _).
|
adamc@175
|
258 End CPS.
|
adamc@175
|
259
|
adamc@175
|
260 Import Source CPS.
|
adamc@175
|
261
|
adamc@180
|
262 (* begin thide *)
|
adamc@175
|
263 Fixpoint cpsType (t : Source.type) : CPS.type :=
|
adamc@175
|
264 match t with
|
adamc@175
|
265 | Nat => Nat%cps
|
adamc@175
|
266 | t1 --> t2 => (cpsType t1 ** (cpsType t2 --->) --->)%cps
|
adamc@175
|
267 end%source.
|
adamc@175
|
268
|
adamc@175
|
269 Reserved Notation "x <-- e1 ; e2" (right associativity, at level 76, e1 at next level).
|
adamc@175
|
270
|
adamc@175
|
271 Section cpsExp.
|
adamc@175
|
272 Variable var : CPS.type -> Type.
|
adamc@175
|
273
|
adamc@175
|
274 Import Source.
|
adamc@175
|
275 Open Scope cps_scope.
|
adamc@175
|
276
|
adamc@175
|
277 Fixpoint cpsExp t (e : exp (fun t => var (cpsType t)) t) {struct e}
|
adamc@175
|
278 : (var (cpsType t) -> prog var) -> prog var :=
|
adamc@175
|
279 match e in (exp _ t) return ((var (cpsType t) -> prog var) -> prog var) with
|
adamc@175
|
280 | Var _ v => fun k => k v
|
adamc@175
|
281
|
adamc@175
|
282 | Const n => fun k =>
|
adamc@175
|
283 x <- ^n;
|
adamc@175
|
284 k x
|
adamc@175
|
285 | Plus e1 e2 => fun k =>
|
adamc@175
|
286 x1 <-- e1;
|
adamc@175
|
287 x2 <-- e2;
|
adamc@175
|
288 x <- x1 +^ x2;
|
adamc@175
|
289 k x
|
adamc@175
|
290
|
adamc@175
|
291 | App _ _ e1 e2 => fun k =>
|
adamc@175
|
292 f <-- e1;
|
adamc@175
|
293 x <-- e2;
|
adamc@175
|
294 kf <- \r, k r;
|
adamc@175
|
295 p <- [x, kf];
|
adamc@175
|
296 f @@ p
|
adamc@175
|
297 | Abs _ _ e' => fun k =>
|
adamc@175
|
298 f <- CPS.Abs (var := var) (fun p =>
|
adamc@175
|
299 x <- #1 p;
|
adamc@175
|
300 kf <- #2 p;
|
adamc@175
|
301 r <-- e' x;
|
adamc@175
|
302 kf @@ r);
|
adamc@175
|
303 k f
|
adamc@175
|
304 end
|
adamc@175
|
305
|
adamc@175
|
306 where "x <-- e1 ; e2" := (cpsExp e1 (fun x => e2)).
|
adamc@175
|
307 End cpsExp.
|
adamc@175
|
308
|
adamc@175
|
309 Notation "x <-- e1 ; e2" := (cpsExp e1 (fun x => e2)) : cps_scope.
|
adamc@175
|
310 Notation "! <-- e1 ; e2" := (cpsExp e1 (fun _ => e2))
|
adamc@175
|
311 (right associativity, at level 76, e1 at next level) : cps_scope.
|
adamc@175
|
312
|
adamc@175
|
313 Implicit Arguments cpsExp [var t].
|
adamc@175
|
314 Definition CpsExp (E : Exp Nat) : Prog :=
|
adamc@175
|
315 fun var => cpsExp (E _) (PHalt (var := _)).
|
adamc@180
|
316 (* end thide *)
|
adamc@175
|
317
|
adamc@175
|
318 Eval compute in CpsExp zero.
|
adamc@175
|
319 Eval compute in CpsExp one.
|
adamc@175
|
320 Eval compute in CpsExp zpo.
|
adamc@175
|
321 Eval compute in CpsExp app_ident.
|
adamc@175
|
322 Eval compute in CpsExp app_ident'.
|
adamc@175
|
323
|
adamc@175
|
324 Eval compute in ProgDenote (CpsExp zero).
|
adamc@175
|
325 Eval compute in ProgDenote (CpsExp one).
|
adamc@175
|
326 Eval compute in ProgDenote (CpsExp zpo).
|
adamc@175
|
327 Eval compute in ProgDenote (CpsExp app_ident).
|
adamc@175
|
328 Eval compute in ProgDenote (CpsExp app_ident').
|
adamc@175
|
329
|
adamc@180
|
330 (* begin thide *)
|
adamc@176
|
331 Fixpoint lr (t : Source.type) : Source.typeDenote t -> CPS.typeDenote (cpsType t) -> Prop :=
|
adamc@176
|
332 match t return (Source.typeDenote t -> CPS.typeDenote (cpsType t) -> Prop) with
|
adamc@176
|
333 | Nat => fun n1 n2 => n1 = n2
|
adamc@176
|
334 | t1 --> t2 => fun f1 f2 =>
|
adamc@176
|
335 forall x1 x2, lr _ x1 x2
|
adamc@176
|
336 -> forall k, exists r,
|
adamc@176
|
337 f2 (x2, k) = k r
|
adamc@176
|
338 /\ lr _ (f1 x1) r
|
adamc@176
|
339 end%source.
|
adamc@176
|
340
|
adamc@176
|
341 Lemma cpsExp_correct : forall G t (e1 : exp _ t) (e2 : exp _ t),
|
adamc@176
|
342 exp_equiv G e1 e2
|
adamc@176
|
343 -> (forall t v1 v2, In (existT _ t (v1, v2)) G -> lr t v1 v2)
|
adamc@176
|
344 -> forall k, exists r,
|
adamc@176
|
345 progDenote (cpsExp e2 k) = progDenote (k r)
|
adamc@176
|
346 /\ lr t (expDenote e1) r.
|
adamc@176
|
347 induction 1; crush; fold typeDenote in *;
|
adamc@176
|
348 repeat (match goal with
|
adamc@176
|
349 | [ H : forall k, exists r, progDenote (cpsExp ?E k) = _ /\ _
|
adamc@176
|
350 |- context[cpsExp ?E ?K] ] =>
|
adamc@176
|
351 generalize (H K); clear H
|
adamc@176
|
352 | [ |- exists r, progDenote (_ ?R) = progDenote (_ r) /\ _ ] =>
|
adamc@176
|
353 exists R
|
adamc@176
|
354 | [ t1 : Source.type |- _ ] =>
|
adamc@176
|
355 match goal with
|
adamc@176
|
356 | [ Hlr : lr t1 ?X1 ?X2, IH : forall v1 v2, _ |- _ ] =>
|
adamc@176
|
357 generalize (IH X1 X2); clear IH; intro IH;
|
adamc@176
|
358 match type of IH with
|
adamc@176
|
359 | ?P -> _ => assert P
|
adamc@176
|
360 end
|
adamc@176
|
361 end
|
adamc@176
|
362 end; crush); eauto.
|
adamc@176
|
363 Qed.
|
adamc@176
|
364
|
adamc@176
|
365 Lemma vars_easy : forall (t : Source.type) (v1 : Source.typeDenote t)
|
adamc@176
|
366 (v2 : typeDenote (cpsType t)),
|
adamc@176
|
367 In
|
adamc@176
|
368 (existT
|
adamc@176
|
369 (fun t0 : Source.type =>
|
adamc@176
|
370 (Source.typeDenote t0 * typeDenote (cpsType t0))%type) t
|
adamc@176
|
371 (v1, v2)) nil -> lr t v1 v2.
|
adamc@176
|
372 crush.
|
adamc@176
|
373 Qed.
|
adamc@176
|
374
|
adamc@176
|
375 Theorem CpsExp_correct : forall (E : Exp Nat),
|
adamc@176
|
376 ProgDenote (CpsExp E) = ExpDenote E.
|
adamc@176
|
377 unfold ProgDenote, CpsExp, ExpDenote; intros;
|
adamc@176
|
378 generalize (cpsExp_correct (e1 := E _) (e2 := E _)
|
adamc@176
|
379 (Exp_equiv _ _ _) vars_easy (PHalt (var := _))); crush.
|
adamc@176
|
380 Qed.
|
adamc@180
|
381 (* end thide *)
|
adamc@176
|
382
|
adamc@175
|
383 End STLC.
|
adamc@177
|
384
|
adamc@177
|
385
|
adamc@177
|
386 (** * A Pattern Compiler *)
|
adamc@177
|
387
|
adamc@177
|
388 Module PatMatch.
|
adamc@177
|
389 Module Source.
|
adamc@177
|
390 Inductive type : Type :=
|
adamc@177
|
391 | Unit : type
|
adamc@177
|
392 | Arrow : type -> type -> type
|
adamc@177
|
393 | Prod : type -> type -> type
|
adamc@177
|
394 | Sum : type -> type -> type.
|
adamc@177
|
395
|
adamc@177
|
396 Infix "-->" := Arrow (right associativity, at level 61).
|
adamc@177
|
397 Infix "++" := Sum (right associativity, at level 60).
|
adamc@177
|
398 Infix "**" := Prod (right associativity, at level 59).
|
adamc@177
|
399
|
adamc@177
|
400 Inductive pat : type -> list type -> Type :=
|
adamc@177
|
401 | PVar : forall t,
|
adamc@177
|
402 pat t (t :: nil)
|
adamc@177
|
403 | PPair : forall t1 t2 ts1 ts2,
|
adamc@177
|
404 pat t1 ts1
|
adamc@177
|
405 -> pat t2 ts2
|
adamc@177
|
406 -> pat (t1 ** t2) (ts1 ++ ts2)
|
adamc@177
|
407 | PInl : forall t1 t2 ts,
|
adamc@177
|
408 pat t1 ts
|
adamc@177
|
409 -> pat (t1 ++ t2) ts
|
adamc@177
|
410 | PInr : forall t1 t2 ts,
|
adamc@177
|
411 pat t2 ts
|
adamc@177
|
412 -> pat (t1 ++ t2) ts.
|
adamc@177
|
413
|
adamc@177
|
414 Implicit Arguments PVar [t].
|
adamc@177
|
415 Implicit Arguments PInl [t1 t2 ts].
|
adamc@177
|
416 Implicit Arguments PInr [t1 t2 ts].
|
adamc@177
|
417
|
adamc@177
|
418 Notation "##" := PVar (at level 70) : pat_scope.
|
adamc@179
|
419 Notation "[ p1 , p2 ]" := (PPair p1 p2) : pat_scope.
|
adamc@177
|
420 Notation "'Inl' p" := (PInl p) (at level 71) : pat_scope.
|
adamc@177
|
421 Notation "'Inr' p" := (PInr p) (at level 71) : pat_scope.
|
adamc@177
|
422
|
adamc@177
|
423 Bind Scope pat_scope with pat.
|
adamc@177
|
424 Delimit Scope pat_scope with pat.
|
adamc@177
|
425
|
adamc@177
|
426 Section vars.
|
adamc@177
|
427 Variable var : type -> Type.
|
adamc@177
|
428
|
adamc@177
|
429 Inductive exp : type -> Type :=
|
adamc@177
|
430 | Var : forall t,
|
adamc@177
|
431 var t
|
adamc@177
|
432 -> exp t
|
adamc@177
|
433
|
adamc@177
|
434 | EUnit : exp Unit
|
adamc@177
|
435
|
adamc@177
|
436 | App : forall t1 t2,
|
adamc@177
|
437 exp (t1 --> t2)
|
adamc@177
|
438 -> exp t1
|
adamc@177
|
439 -> exp t2
|
adamc@177
|
440 | Abs : forall t1 t2,
|
adamc@177
|
441 (var t1 -> exp t2)
|
adamc@177
|
442 -> exp (t1 --> t2)
|
adamc@177
|
443
|
adamc@177
|
444 | Pair : forall t1 t2,
|
adamc@177
|
445 exp t1
|
adamc@177
|
446 -> exp t2
|
adamc@177
|
447 -> exp (t1 ** t2)
|
adamc@177
|
448
|
adamc@177
|
449 | EInl : forall t1 t2,
|
adamc@177
|
450 exp t1
|
adamc@177
|
451 -> exp (t1 ++ t2)
|
adamc@177
|
452 | EInr : forall t1 t2,
|
adamc@177
|
453 exp t2
|
adamc@177
|
454 -> exp (t1 ++ t2)
|
adamc@177
|
455
|
adamc@177
|
456 | Case : forall t1 t2 (tss : list (list type)),
|
adamc@177
|
457 exp t1
|
adamc@177
|
458 -> (forall ts, member ts tss -> pat t1 ts)
|
adamc@177
|
459 -> (forall ts, member ts tss -> hlist var ts -> exp t2)
|
adamc@177
|
460 -> exp t2
|
adamc@177
|
461 -> exp t2.
|
adamc@177
|
462 End vars.
|
adamc@177
|
463
|
adamc@177
|
464 Definition Exp t := forall var, exp var t.
|
adamc@177
|
465
|
adamc@177
|
466 Implicit Arguments Var [var t].
|
adamc@177
|
467 Implicit Arguments EUnit [var].
|
adamc@177
|
468 Implicit Arguments App [var t1 t2].
|
adamc@177
|
469 Implicit Arguments Abs [var t1 t2].
|
adamc@177
|
470 Implicit Arguments Pair [var t1 t2].
|
adamc@177
|
471 Implicit Arguments EInl [var t1 t2].
|
adamc@177
|
472 Implicit Arguments EInr [var t1 t2].
|
adamc@177
|
473 Implicit Arguments Case [var t1 t2].
|
adamc@177
|
474
|
adamc@177
|
475 Notation "# v" := (Var v) (at level 70) : source_scope.
|
adamc@177
|
476
|
adamc@177
|
477 Notation "()" := EUnit : source_scope.
|
adamc@177
|
478
|
adamc@177
|
479 Infix "@" := App (left associativity, at level 77) : source_scope.
|
adamc@177
|
480 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : source_scope.
|
adamc@177
|
481
|
adamc@179
|
482 Notation "[ x , y ]" := (Pair x y) : source_scope.
|
adamc@177
|
483
|
adamc@177
|
484 Notation "'Inl' e" := (EInl e) (at level 71) : source_scope.
|
adamc@177
|
485 Notation "'Inr' e" := (EInr e) (at level 71) : source_scope.
|
adamc@177
|
486
|
adamc@178
|
487 Delimit Scope source_scope with source.
|
adamc@177
|
488 Bind Scope source_scope with exp.
|
adamc@177
|
489
|
adamc@177
|
490 Open Local Scope source_scope.
|
adamc@177
|
491
|
adamc@177
|
492 Fixpoint typeDenote (t : type) : Set :=
|
adamc@177
|
493 match t with
|
adamc@177
|
494 | Unit => unit
|
adamc@177
|
495 | t1 --> t2 => typeDenote t1 -> typeDenote t2
|
adamc@177
|
496 | t1 ** t2 => (typeDenote t1 * typeDenote t2)%type
|
adamc@177
|
497 | t1 ++ t2 => (typeDenote t1 + typeDenote t2)%type
|
adamc@177
|
498 end.
|
adamc@177
|
499
|
adamc@177
|
500 Fixpoint patDenote t ts (p : pat t ts) {struct p} : typeDenote t -> option (hlist typeDenote ts) :=
|
adamc@177
|
501 match p in (pat t ts) return (typeDenote t -> option (hlist typeDenote ts)) with
|
adamc@177
|
502 | PVar _ => fun v => Some (v, tt)
|
adamc@177
|
503 | PPair _ _ _ _ p1 p2 => fun v =>
|
adamc@177
|
504 match patDenote p1 (fst v), patDenote p2 (snd v) with
|
adamc@177
|
505 | Some tup1, Some tup2 => Some (happ tup1 tup2)
|
adamc@177
|
506 | _, _ => None
|
adamc@177
|
507 end
|
adamc@177
|
508 | PInl _ _ _ p' => fun v =>
|
adamc@177
|
509 match v with
|
adamc@177
|
510 | inl v' => patDenote p' v'
|
adamc@177
|
511 | _ => None
|
adamc@177
|
512 end
|
adamc@177
|
513 | PInr _ _ _ p' => fun v =>
|
adamc@177
|
514 match v with
|
adamc@177
|
515 | inr v' => patDenote p' v'
|
adamc@177
|
516 | _ => None
|
adamc@177
|
517 end
|
adamc@177
|
518 end.
|
adamc@177
|
519
|
adamc@177
|
520 Section matchesDenote.
|
adamc@177
|
521 Variables t2 : type.
|
adamc@177
|
522 Variable default : typeDenote t2.
|
adamc@177
|
523
|
adamc@177
|
524 Fixpoint matchesDenote (tss : list (list type))
|
adamc@177
|
525 : (forall ts, member ts tss -> option (hlist typeDenote ts))
|
adamc@177
|
526 -> (forall ts, member ts tss -> hlist typeDenote ts -> typeDenote t2)
|
adamc@177
|
527 -> typeDenote t2 :=
|
adamc@177
|
528 match tss return (forall ts, member ts tss -> _)
|
adamc@177
|
529 -> (forall ts, member ts tss -> _)
|
adamc@177
|
530 -> _ with
|
adamc@177
|
531 | nil => fun _ _ =>
|
adamc@177
|
532 default
|
adamc@177
|
533 | ts :: tss' => fun (envs : forall ts', member ts' (ts :: tss') -> option (hlist typeDenote ts'))
|
adamc@177
|
534 (bodies : forall ts', member ts' (ts :: tss') -> hlist typeDenote ts' -> typeDenote t2) =>
|
adamc@177
|
535 match envs _ (hfirst (refl_equal _)) with
|
adamc@177
|
536 | None => matchesDenote tss'
|
adamc@177
|
537 (fun _ mem => envs _ (hnext mem))
|
adamc@177
|
538 (fun _ mem => bodies _ (hnext mem))
|
adamc@177
|
539 | Some env => (bodies _ (hfirst (refl_equal _))) env
|
adamc@177
|
540 end
|
adamc@177
|
541 end.
|
adamc@177
|
542 End matchesDenote.
|
adamc@177
|
543
|
adamc@177
|
544 Implicit Arguments matchesDenote [t2 tss].
|
adamc@177
|
545
|
adamc@177
|
546 Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t :=
|
adamc@177
|
547 match e in (exp _ t) return (typeDenote t) with
|
adamc@177
|
548 | Var _ v => v
|
adamc@177
|
549
|
adamc@177
|
550 | EUnit => tt
|
adamc@177
|
551
|
adamc@177
|
552 | App _ _ e1 e2 => (expDenote e1) (expDenote e2)
|
adamc@177
|
553 | Abs _ _ e' => fun x => expDenote (e' x)
|
adamc@177
|
554
|
adamc@177
|
555 | Pair _ _ e1 e2 => (expDenote e1, expDenote e2)
|
adamc@177
|
556
|
adamc@177
|
557 | EInl _ _ e' => inl _ (expDenote e')
|
adamc@177
|
558 | EInr _ _ e' => inr _ (expDenote e')
|
adamc@177
|
559
|
adamc@177
|
560 | Case _ _ _ e ps es def =>
|
adamc@177
|
561 matchesDenote (expDenote def)
|
adamc@177
|
562 (fun _ mem => patDenote (ps _ mem) (expDenote e))
|
adamc@177
|
563 (fun _ mem env => expDenote (es _ mem env))
|
adamc@177
|
564 end.
|
adamc@177
|
565
|
adamc@177
|
566 Definition ExpDenote t (E : Exp t) := expDenote (E _).
|
adamc@177
|
567 End Source.
|
adamc@177
|
568
|
adamc@177
|
569 Import Source.
|
adamc@177
|
570
|
adamc@178
|
571 Module Elab.
|
adamc@177
|
572 Section vars.
|
adamc@177
|
573 Variable var : type -> Type.
|
adamc@177
|
574
|
adamc@177
|
575 Inductive exp : type -> Type :=
|
adamc@177
|
576 | Var : forall t,
|
adamc@177
|
577 var t
|
adamc@177
|
578 -> exp t
|
adamc@177
|
579
|
adamc@177
|
580 | EUnit : exp Unit
|
adamc@177
|
581
|
adamc@177
|
582 | App : forall t1 t2,
|
adamc@177
|
583 exp (t1 --> t2)
|
adamc@177
|
584 -> exp t1
|
adamc@177
|
585 -> exp t2
|
adamc@177
|
586 | Abs : forall t1 t2,
|
adamc@177
|
587 (var t1 -> exp t2)
|
adamc@177
|
588 -> exp (t1 --> t2)
|
adamc@177
|
589
|
adamc@177
|
590 | Pair : forall t1 t2,
|
adamc@177
|
591 exp t1
|
adamc@177
|
592 -> exp t2
|
adamc@177
|
593 -> exp (t1 ** t2)
|
adamc@177
|
594 | Fst : forall t1 t2,
|
adamc@177
|
595 exp (t1 ** t2)
|
adamc@177
|
596 -> exp t1
|
adamc@177
|
597 | Snd : forall t1 t2,
|
adamc@177
|
598 exp (t1 ** t2)
|
adamc@177
|
599 -> exp t2
|
adamc@177
|
600
|
adamc@177
|
601 | EInl : forall t1 t2,
|
adamc@177
|
602 exp t1
|
adamc@177
|
603 -> exp (t1 ++ t2)
|
adamc@177
|
604 | EInr : forall t1 t2,
|
adamc@177
|
605 exp t2
|
adamc@177
|
606 -> exp (t1 ++ t2)
|
adamc@177
|
607 | Case : forall t1 t2 t,
|
adamc@177
|
608 exp (t1 ++ t2)
|
adamc@177
|
609 -> (var t1 -> exp t)
|
adamc@177
|
610 -> (var t2 -> exp t)
|
adamc@177
|
611 -> exp t.
|
adamc@177
|
612 End vars.
|
adamc@177
|
613
|
adamc@177
|
614 Definition Exp t := forall var, exp var t.
|
adamc@177
|
615
|
adamc@177
|
616 Implicit Arguments Var [var t].
|
adamc@177
|
617 Implicit Arguments EUnit [var].
|
adamc@177
|
618 Implicit Arguments App [var t1 t2].
|
adamc@177
|
619 Implicit Arguments Abs [var t1 t2].
|
adamc@177
|
620 Implicit Arguments Pair [var t1 t2].
|
adamc@177
|
621 Implicit Arguments Fst [var t1 t2].
|
adamc@177
|
622 Implicit Arguments Snd [var t1 t2].
|
adamc@177
|
623 Implicit Arguments EInl [var t1 t2].
|
adamc@177
|
624 Implicit Arguments EInr [var t1 t2].
|
adamc@177
|
625 Implicit Arguments Case [var t1 t2 t].
|
adamc@177
|
626
|
adamc@177
|
627
|
adamc@177
|
628 Notation "# v" := (Var v) (at level 70) : elab_scope.
|
adamc@177
|
629
|
adamc@177
|
630 Notation "()" := EUnit : elab_scope.
|
adamc@177
|
631
|
adamc@177
|
632 Infix "@" := App (left associativity, at level 77) : elab_scope.
|
adamc@177
|
633 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : elab_scope.
|
adamc@177
|
634 Notation "\ ? , e" := (Abs (fun _ => e)) (at level 78) : elab_scope.
|
adamc@177
|
635
|
adamc@179
|
636 Notation "[ x , y ]" := (Pair x y) : elab_scope.
|
adamc@177
|
637 Notation "#1 e" := (Fst e) (at level 72) : elab_scope.
|
adamc@177
|
638 Notation "#2 e" := (Snd e) (at level 72) : elab_scope.
|
adamc@177
|
639
|
adamc@177
|
640 Notation "'Inl' e" := (EInl e) (at level 71) : elab_scope.
|
adamc@177
|
641 Notation "'Inr' e" := (EInr e) (at level 71) : elab_scope.
|
adamc@177
|
642
|
adamc@177
|
643 Bind Scope elab_scope with exp.
|
adamc@177
|
644 Delimit Scope elab_scope with elab.
|
adamc@177
|
645
|
adamc@177
|
646 Open Scope elab_scope.
|
adamc@177
|
647
|
adamc@177
|
648 Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t :=
|
adamc@177
|
649 match e in (exp _ t) return (typeDenote t) with
|
adamc@177
|
650 | Var _ v => v
|
adamc@177
|
651
|
adamc@177
|
652 | EUnit => tt
|
adamc@177
|
653
|
adamc@177
|
654 | App _ _ e1 e2 => (expDenote e1) (expDenote e2)
|
adamc@177
|
655 | Abs _ _ e' => fun x => expDenote (e' x)
|
adamc@177
|
656
|
adamc@177
|
657 | Pair _ _ e1 e2 => (expDenote e1, expDenote e2)
|
adamc@177
|
658 | Fst _ _ e' => fst (expDenote e')
|
adamc@177
|
659 | Snd _ _ e' => snd (expDenote e')
|
adamc@177
|
660
|
adamc@177
|
661 | EInl _ _ e' => inl _ (expDenote e')
|
adamc@177
|
662 | EInr _ _ e' => inr _ (expDenote e')
|
adamc@177
|
663 | Case _ _ _ e' e1 e2 =>
|
adamc@177
|
664 match expDenote e' with
|
adamc@177
|
665 | inl v => expDenote (e1 v)
|
adamc@177
|
666 | inr v => expDenote (e2 v)
|
adamc@177
|
667 end
|
adamc@177
|
668 end.
|
adamc@177
|
669
|
adamc@177
|
670 Definition ExpDenote t (E : Exp t) := expDenote (E _).
|
adamc@177
|
671 End Elab.
|
adamc@177
|
672
|
adamc@178
|
673 Import Elab.
|
adamc@178
|
674
|
adamc@178
|
675 Notation "x <- e1 ; e2" := ((\x, e2) @ e1)%source
|
adamc@178
|
676 (right associativity, at level 76, e1 at next level) : source_scope.
|
adamc@178
|
677 Notation "x <- e1 ; e2" := ((\x, e2) @ e1)%elab
|
adamc@178
|
678 (right associativity, at level 76, e1 at next level) : elab_scope.
|
adamc@178
|
679
|
adamc@178
|
680 Section choice_tree.
|
adamc@178
|
681 Open Scope source_scope.
|
adamc@178
|
682
|
adamc@178
|
683 Fixpoint choice_tree var (t : type) (result : Type) : Type :=
|
adamc@178
|
684 match t with
|
adamc@178
|
685 | t1 ** t2 =>
|
adamc@178
|
686 choice_tree var t1
|
adamc@178
|
687 (choice_tree var t2
|
adamc@178
|
688 result)
|
adamc@178
|
689 | t1 ++ t2 =>
|
adamc@178
|
690 choice_tree var t1 result
|
adamc@178
|
691 * choice_tree var t2 result
|
adamc@178
|
692 | t => exp var t -> result
|
adamc@178
|
693 end%type.
|
adamc@178
|
694
|
adamc@178
|
695 Fixpoint merge var t result {struct t}
|
adamc@178
|
696 : (result -> result -> result)
|
adamc@178
|
697 -> choice_tree var t result -> choice_tree var t result -> choice_tree var t result :=
|
adamc@178
|
698 match t return ((result -> result -> result)
|
adamc@178
|
699 -> choice_tree var t result -> choice_tree var t result -> choice_tree var t result) with
|
adamc@178
|
700 | _ ** _ => fun mr ct1 ct2 =>
|
adamc@178
|
701 merge _ _
|
adamc@178
|
702 (merge _ _ mr)
|
adamc@178
|
703 ct1 ct2
|
adamc@178
|
704
|
adamc@178
|
705 | _ ++ _ => fun mr ct1 ct2 =>
|
adamc@178
|
706 (merge var _ mr (fst ct1) (fst ct2),
|
adamc@178
|
707 merge var _ mr (snd ct1) (snd ct2))
|
adamc@178
|
708
|
adamc@178
|
709 | _ => fun mr ct1 ct2 e => mr (ct1 e) (ct2 e)
|
adamc@178
|
710 end.
|
adamc@178
|
711
|
adamc@178
|
712 Fixpoint everywhere var t result {struct t}
|
adamc@178
|
713 : (exp var t -> result) -> choice_tree var t result :=
|
adamc@178
|
714 match t return ((exp var t -> result) -> choice_tree var t result) with
|
adamc@178
|
715 | t1 ** t2 => fun r =>
|
adamc@178
|
716 everywhere (t := t1) (fun e1 =>
|
adamc@178
|
717 everywhere (t := t2) (fun e2 =>
|
adamc@178
|
718 r ([e1, e2])%elab))
|
adamc@178
|
719
|
adamc@178
|
720 | _ ++ _ => fun r =>
|
adamc@178
|
721 (everywhere (fun e => r (Inl e)%elab),
|
adamc@178
|
722 everywhere (fun e => r (Inr e)%elab))
|
adamc@178
|
723
|
adamc@178
|
724 | _ => fun r => r
|
adamc@178
|
725 end.
|
adamc@178
|
726 End choice_tree.
|
adamc@178
|
727
|
adamc@178
|
728 Implicit Arguments merge [var t result].
|
adamc@178
|
729
|
adamc@178
|
730 Section elaborate.
|
adamc@178
|
731 Open Local Scope elab_scope.
|
adamc@178
|
732
|
adamc@178
|
733 Fixpoint elaboratePat var t1 ts result (p : pat t1 ts) {struct p} :
|
adamc@178
|
734 (hlist (exp var) ts -> result) -> result -> choice_tree var t1 result :=
|
adamc@178
|
735 match p in (pat t1 ts) return ((hlist (exp var) ts -> result)
|
adamc@178
|
736 -> result -> choice_tree var t1 result) with
|
adamc@178
|
737 | PVar _ => fun succ fail =>
|
adamc@178
|
738 everywhere (fun disc => succ (disc, tt))
|
adamc@178
|
739
|
adamc@178
|
740 | PPair _ _ _ _ p1 p2 => fun succ fail =>
|
adamc@178
|
741 elaboratePat _ p1
|
adamc@178
|
742 (fun tup1 =>
|
adamc@178
|
743 elaboratePat _ p2
|
adamc@178
|
744 (fun tup2 =>
|
adamc@178
|
745 succ (happ tup1 tup2))
|
adamc@178
|
746 fail)
|
adamc@178
|
747 (everywhere (fun _ => fail))
|
adamc@178
|
748
|
adamc@178
|
749 | PInl _ _ _ p' => fun succ fail =>
|
adamc@178
|
750 (elaboratePat _ p' succ fail,
|
adamc@178
|
751 everywhere (fun _ => fail))
|
adamc@178
|
752 | PInr _ _ _ p' => fun succ fail =>
|
adamc@178
|
753 (everywhere (fun _ => fail),
|
adamc@178
|
754 elaboratePat _ p' succ fail)
|
adamc@178
|
755 end.
|
adamc@178
|
756
|
adamc@178
|
757 Implicit Arguments elaboratePat [var t1 ts result].
|
adamc@178
|
758
|
adamc@178
|
759 Fixpoint letify var t ts {struct ts} : (hlist var ts -> exp var t)
|
adamc@178
|
760 -> hlist (exp var) ts -> exp var t :=
|
adamc@178
|
761 match ts return ((hlist var ts -> exp var t)
|
adamc@178
|
762 -> hlist (exp var) ts -> exp var t) with
|
adamc@178
|
763 | nil => fun f _ => f tt
|
adamc@178
|
764 | _ :: _ => fun f tup => letify _ (fun tup' => x <- fst tup; f (x, tup')) (snd tup)
|
adamc@178
|
765 end.
|
adamc@178
|
766
|
adamc@178
|
767 Implicit Arguments letify [var t ts].
|
adamc@178
|
768
|
adamc@178
|
769 Fixpoint expand var result t1 t2
|
adamc@178
|
770 (out : result -> exp var t2) {struct t1}
|
adamc@178
|
771 : forall ct : choice_tree var t1 result,
|
adamc@178
|
772 exp var t1
|
adamc@178
|
773 -> exp var t2 :=
|
adamc@178
|
774 match t1 return (forall ct : choice_tree var t1 result, exp var t1
|
adamc@178
|
775 -> exp var t2) with
|
adamc@178
|
776 | (_ ** _)%source => fun ct disc =>
|
adamc@178
|
777 expand
|
adamc@178
|
778 (fun ct' => expand out ct' (#2 disc)%source)
|
adamc@178
|
779 ct
|
adamc@178
|
780 (#1 disc)
|
adamc@178
|
781
|
adamc@178
|
782 | (_ ++ _)%source => fun ct disc =>
|
adamc@178
|
783 Case disc
|
adamc@178
|
784 (fun x => expand out (fst ct) (#x))
|
adamc@178
|
785 (fun y => expand out (snd ct) (#y))
|
adamc@178
|
786
|
adamc@178
|
787 | _ => fun ct disc =>
|
adamc@178
|
788 x <- disc; out (ct (#x))
|
adamc@178
|
789 end.
|
adamc@178
|
790
|
adamc@178
|
791 Definition mergeOpt A (o1 o2 : option A) :=
|
adamc@178
|
792 match o1 with
|
adamc@178
|
793 | None => o2
|
adamc@178
|
794 | _ => o1
|
adamc@178
|
795 end.
|
adamc@178
|
796
|
adamc@178
|
797 Import Source.
|
adamc@178
|
798
|
adamc@178
|
799 Fixpoint elaborateMatches var t1 t2
|
adamc@178
|
800 (tss : list (list type)) {struct tss}
|
adamc@178
|
801 : (forall ts, member ts tss -> pat t1 ts)
|
adamc@178
|
802 -> (forall ts, member ts tss -> hlist var ts -> Elab.exp var t2)
|
adamc@178
|
803 -> choice_tree var t1 (option (Elab.exp var t2)) :=
|
adamc@178
|
804 match tss return (forall ts, member ts tss -> pat t1 ts)
|
adamc@178
|
805 -> (forall ts, member ts tss -> _)
|
adamc@178
|
806 -> _ with
|
adamc@178
|
807 | nil => fun _ _ =>
|
adamc@178
|
808 everywhere (fun _ => None)
|
adamc@178
|
809 | ts :: tss' => fun (ps : forall ts', member ts' (ts :: tss') -> pat t1 ts')
|
adamc@178
|
810 (es : forall ts', member ts' (ts :: tss') -> hlist var ts' -> Elab.exp var t2) =>
|
adamc@178
|
811 merge (@mergeOpt _)
|
adamc@178
|
812 (elaboratePat (ps _ (hfirst (refl_equal _)))
|
adamc@178
|
813 (fun ts => Some (letify
|
adamc@178
|
814 (fun ts' => es _ (hfirst (refl_equal _)) ts')
|
adamc@178
|
815 ts))
|
adamc@178
|
816 None)
|
adamc@178
|
817 (elaborateMatches tss'
|
adamc@178
|
818 (fun _ mem => ps _ (hnext mem))
|
adamc@178
|
819 (fun _ mem => es _ (hnext mem)))
|
adamc@178
|
820 end.
|
adamc@178
|
821
|
adamc@178
|
822 Implicit Arguments elaborateMatches [var t1 t2 tss].
|
adamc@178
|
823
|
adamc@178
|
824 Open Scope cps_scope.
|
adamc@178
|
825
|
adamc@178
|
826 Fixpoint elaborate var t (e : Source.exp var t) {struct e} : Elab.exp var t :=
|
adamc@178
|
827 match e in (Source.exp _ t) return (Elab.exp var t) with
|
adamc@178
|
828 | Var _ v => #v
|
adamc@178
|
829
|
adamc@178
|
830 | EUnit => ()
|
adamc@178
|
831
|
adamc@178
|
832 | App _ _ e1 e2 => elaborate e1 @ elaborate e2
|
adamc@178
|
833 | Abs _ _ e' => \x, elaborate (e' x)
|
adamc@178
|
834
|
adamc@178
|
835 | Pair _ _ e1 e2 => [elaborate e1, elaborate e2]
|
adamc@178
|
836 | EInl _ _ e' => Inl (elaborate e')
|
adamc@178
|
837 | EInr _ _ e' => Inr (elaborate e')
|
adamc@178
|
838
|
adamc@178
|
839 | Case _ _ _ e' ps es def =>
|
adamc@178
|
840 expand
|
adamc@178
|
841 (fun eo => match eo with
|
adamc@178
|
842 | None => elaborate def
|
adamc@178
|
843 | Some e => e
|
adamc@178
|
844 end)
|
adamc@178
|
845 (elaborateMatches ps (fun _ mem env => elaborate (es _ mem env)))
|
adamc@178
|
846 (elaborate e')
|
adamc@178
|
847 end.
|
adamc@178
|
848 End elaborate.
|
adamc@178
|
849
|
adamc@178
|
850 Definition Elaborate t (E : Source.Exp t) : Elab.Exp t :=
|
adamc@178
|
851 fun _ => elaborate (E _).
|
adamc@178
|
852
|
adamc@179
|
853 Fixpoint grab t result : choice_tree typeDenote t result -> typeDenote t -> result :=
|
adamc@179
|
854 match t return (choice_tree typeDenote t result -> typeDenote t -> result) with
|
adamc@179
|
855 | t1 ** t2 => fun ct v =>
|
adamc@179
|
856 grab t2 _ (grab t1 _ ct (fst v)) (snd v)
|
adamc@179
|
857 | t1 ++ t2 => fun ct v =>
|
adamc@179
|
858 match v with
|
adamc@179
|
859 | inl v' => grab t1 _ (fst ct) v'
|
adamc@179
|
860 | inr v' => grab t2 _ (snd ct) v'
|
adamc@179
|
861 end
|
adamc@179
|
862 | t => fun ct v => ct (#v)%elab
|
adamc@179
|
863 end%source%type.
|
adamc@179
|
864
|
adamc@179
|
865 Implicit Arguments grab [t result].
|
adamc@179
|
866
|
adamc@179
|
867 Ltac my_crush :=
|
adamc@179
|
868 crush;
|
adamc@179
|
869 repeat (match goal with
|
adamc@179
|
870 | [ |- context[match ?E with inl _ => _ | inr _ => _ end] ] =>
|
adamc@179
|
871 destruct E
|
adamc@179
|
872 end; crush).
|
adamc@179
|
873
|
adamc@179
|
874 Lemma expand_grab : forall t2 t1 result
|
adamc@179
|
875 (out : result -> Elab.exp typeDenote t2)
|
adamc@179
|
876 (ct : choice_tree typeDenote t1 result)
|
adamc@179
|
877 (disc : Elab.exp typeDenote t1),
|
adamc@179
|
878 Elab.expDenote (expand out ct disc) = Elab.expDenote (out (grab ct (Elab.expDenote disc))).
|
adamc@179
|
879 induction t1; my_crush.
|
adamc@179
|
880 Qed.
|
adamc@179
|
881
|
adamc@179
|
882 Lemma recreate_pair : forall t1 t2
|
adamc@179
|
883 (x : Elab.exp typeDenote t1)
|
adamc@179
|
884 (x0 : Elab.exp typeDenote t2)
|
adamc@179
|
885 (v : typeDenote (t1 ** t2)),
|
adamc@179
|
886 expDenote x = fst v
|
adamc@179
|
887 -> expDenote x0 = snd v
|
adamc@179
|
888 -> @eq (typeDenote t1 * typeDenote t2) (expDenote [x, x0]) v.
|
adamc@179
|
889 destruct v; crush.
|
adamc@179
|
890 Qed.
|
adamc@179
|
891
|
adamc@179
|
892 Lemma everywhere_correct : forall t1 result
|
adamc@179
|
893 (succ : Elab.exp typeDenote t1 -> result) disc,
|
adamc@179
|
894 exists disc', grab (everywhere succ) (Elab.expDenote disc) = succ disc'
|
adamc@179
|
895 /\ Elab.expDenote disc' = Elab.expDenote disc.
|
adamc@179
|
896 Hint Resolve recreate_pair.
|
adamc@179
|
897
|
adamc@179
|
898 induction t1; my_crush; eauto; fold choice_tree;
|
adamc@179
|
899 repeat (fold typeDenote in *; crush;
|
adamc@179
|
900 match goal with
|
adamc@179
|
901 | [ IH : forall result succ, _ |- context[grab (everywhere ?S) _] ] =>
|
adamc@179
|
902 generalize (IH _ S); clear IH
|
adamc@179
|
903 | [ e : exp typeDenote (?T ** _), IH : forall _ : exp typeDenote ?T, _ |- _ ] =>
|
adamc@179
|
904 generalize (IH (#1 e)); clear IH
|
adamc@179
|
905 | [ e : exp typeDenote (_ ** ?T), IH : forall _ : exp typeDenote ?T, _ |- _ ] =>
|
adamc@179
|
906 generalize (IH (#2 e)); clear IH
|
adamc@179
|
907 | [ e : typeDenote ?T, IH : forall _ : exp typeDenote ?T, _ |- _ ] =>
|
adamc@179
|
908 generalize (IH (#e)); clear IH
|
adamc@179
|
909 end; crush); eauto.
|
adamc@179
|
910 Qed.
|
adamc@179
|
911
|
adamc@179
|
912 Lemma merge_correct : forall t result
|
adamc@179
|
913 (ct1 ct2 : choice_tree typeDenote t result)
|
adamc@179
|
914 (mr : result -> result -> result) v,
|
adamc@179
|
915 grab (merge mr ct1 ct2) v = mr (grab ct1 v) (grab ct2 v).
|
adamc@179
|
916 induction t; crush.
|
adamc@179
|
917 Qed.
|
adamc@179
|
918
|
adamc@179
|
919 Lemma everywhere_fail : forall t result
|
adamc@179
|
920 (fail : result) v,
|
adamc@179
|
921 grab (everywhere (fun _ : Elab.exp typeDenote t => fail)) v = fail.
|
adamc@179
|
922 induction t; crush.
|
adamc@179
|
923 Qed.
|
adamc@179
|
924
|
adamc@179
|
925 Lemma elaboratePat_correct : forall t1 ts (p : pat t1 ts)
|
adamc@179
|
926 result (succ : hlist (Elab.exp typeDenote) ts -> result)
|
adamc@179
|
927 (fail : result) v env,
|
adamc@179
|
928 patDenote p v = Some env
|
adamc@179
|
929 -> exists env', grab (elaboratePat typeDenote p succ fail) v = succ env'
|
adamc@179
|
930 /\ env = hmap Elab.expDenote env'.
|
adamc@179
|
931 Hint Resolve hmap_happ.
|
adamc@179
|
932
|
adamc@179
|
933 induction p; crush; fold choice_tree;
|
adamc@179
|
934 repeat (match goal with
|
adamc@179
|
935 | [ |- context[grab (everywhere ?succ) ?v] ] =>
|
adamc@179
|
936 generalize (everywhere_correct succ (#v)%elab)
|
adamc@179
|
937
|
adamc@179
|
938 | [ H : forall result sudc fail, _ |- context[grab (elaboratePat _ _ ?S ?F) ?V] ] =>
|
adamc@179
|
939 generalize (H _ S F V); clear H
|
adamc@179
|
940 | [ H1 : context[match ?E with Some _ => _ | None => _ end],
|
adamc@179
|
941 H2 : forall env, ?E = Some env -> _ |- _ ] =>
|
adamc@179
|
942 destruct E
|
adamc@179
|
943 | [ H : forall env, Some ?E = Some env -> _ |- _ ] =>
|
adamc@179
|
944 generalize (H _ (refl_equal _)); clear H
|
adamc@179
|
945 end; crush); eauto.
|
adamc@179
|
946 Qed.
|
adamc@179
|
947
|
adamc@179
|
948 Lemma elaboratePat_fails : forall t1 ts (p : pat t1 ts)
|
adamc@179
|
949 result (succ : hlist (Elab.exp typeDenote) ts -> result)
|
adamc@179
|
950 (fail : result) v,
|
adamc@179
|
951 patDenote p v = None
|
adamc@179
|
952 -> grab (elaboratePat typeDenote p succ fail) v = fail.
|
adamc@179
|
953 Hint Resolve everywhere_fail.
|
adamc@179
|
954
|
adamc@179
|
955 induction p; try solve [ crush ];
|
adamc@179
|
956 simpl; fold choice_tree; intuition; simpl in *;
|
adamc@179
|
957 repeat match goal with
|
adamc@179
|
958 | [ IH : forall result succ fail v, patDenote ?P v = _ -> _
|
adamc@179
|
959 |- context[grab (elaboratePat _ ?P ?S ?F) ?V] ] =>
|
adamc@179
|
960 generalize (IH _ S F V); clear IH; intro IH;
|
adamc@179
|
961 generalize (elaboratePat_correct P S F V); intros;
|
adamc@179
|
962 destruct (patDenote P V); try discriminate
|
adamc@179
|
963 | [ H : forall env, Some _ = Some env -> _ |- _ ] =>
|
adamc@179
|
964 destruct (H _ (refl_equal _)); clear H; intuition
|
adamc@179
|
965 | [ H : _ |- _ ] => rewrite H; intuition
|
adamc@179
|
966 end.
|
adamc@179
|
967 Qed.
|
adamc@179
|
968
|
adamc@179
|
969 Implicit Arguments letify [var t ts].
|
adamc@179
|
970
|
adamc@179
|
971 Lemma letify_correct : forall t ts (f : hlist typeDenote ts -> Elab.exp typeDenote t)
|
adamc@179
|
972 (env : hlist (Elab.exp typeDenote) ts),
|
adamc@179
|
973 Elab.expDenote (letify f env)
|
adamc@179
|
974 = Elab.expDenote (f (hmap Elab.expDenote env)).
|
adamc@179
|
975 induction ts; crush.
|
adamc@179
|
976 Qed.
|
adamc@179
|
977
|
adamc@179
|
978 Theorem elaborate_correct : forall t (e : Source.exp typeDenote t),
|
adamc@179
|
979 Elab.expDenote (elaborate e) = Source.expDenote e.
|
adamc@179
|
980 Hint Rewrite expand_grab merge_correct letify_correct : cpdt.
|
adamc@179
|
981 Hint Rewrite everywhere_fail elaboratePat_fails using assumption : cpdt.
|
adamc@179
|
982
|
adamc@179
|
983 induction e; crush; try (ext_eq; crush);
|
adamc@179
|
984 match goal with
|
adamc@179
|
985 | [ tss : list (list type) |- _ ] =>
|
adamc@179
|
986 induction tss; crush;
|
adamc@179
|
987 match goal with
|
adamc@179
|
988 | [ |- context[grab (elaboratePat _ ?P ?S ?F) ?V] ] =>
|
adamc@179
|
989 case_eq (patDenote P V); [intros env Heq;
|
adamc@179
|
990 destruct (elaboratePat_correct P S F _ Heq); crush;
|
adamc@179
|
991 match goal with
|
adamc@179
|
992 | [ H : _ |- _ ] => rewrite <- H; crush
|
adamc@179
|
993 end
|
adamc@179
|
994 | crush ]
|
adamc@179
|
995 end
|
adamc@179
|
996 end.
|
adamc@179
|
997 Qed.
|
adamc@179
|
998
|
adamc@179
|
999 Theorem Elaborate_correct : forall t (E : Source.Exp t),
|
adamc@179
|
1000 Elab.ExpDenote (Elaborate E) = Source.ExpDenote E.
|
adamc@179
|
1001 unfold Elab.ExpDenote, Elaborate, Source.ExpDenote;
|
adamc@179
|
1002 intros; apply elaborate_correct.
|
adamc@179
|
1003 Qed.
|
adamc@179
|
1004
|
adamc@177
|
1005 End PatMatch.
|