adamc@182
|
1 (* Copyright (c) 2008, Adam Chlipala
|
adamc@182
|
2 *
|
adamc@182
|
3 * This work is licensed under a
|
adamc@182
|
4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0
|
adamc@182
|
5 * Unported License.
|
adamc@182
|
6 * The license text is available at:
|
adamc@182
|
7 * http://creativecommons.org/licenses/by-nc-nd/3.0/
|
adamc@182
|
8 *)
|
adamc@182
|
9
|
adamc@182
|
10 (* begin hide *)
|
adamc@184
|
11 Require Import Arith Bool String List Eqdep JMeq.
|
adamc@182
|
12
|
adamc@182
|
13 Require Import Axioms Tactics DepList.
|
adamc@182
|
14
|
adamc@182
|
15 Set Implicit Arguments.
|
adamc@184
|
16
|
adamc@184
|
17 Infix "==" := JMeq (at level 70, no associativity).
|
adamc@182
|
18 (* end hide *)
|
adamc@182
|
19
|
adamc@182
|
20
|
adamc@184
|
21
|
adamc@184
|
22
|
adamc@182
|
23 (** %\chapter{Intensional Transformations}% *)
|
adamc@182
|
24
|
adamc@182
|
25 (** TODO: Prose for this chapter *)
|
adamc@182
|
26
|
adamc@182
|
27
|
adamc@182
|
28 (** * Closure Conversion *)
|
adamc@182
|
29
|
adamc@182
|
30 Module Source.
|
adamc@182
|
31 Inductive type : Type :=
|
adamc@182
|
32 | TNat : type
|
adamc@182
|
33 | Arrow : type -> type -> type.
|
adamc@182
|
34
|
adamc@182
|
35 Notation "'Nat'" := TNat : source_scope.
|
adamc@182
|
36 Infix "-->" := Arrow (right associativity, at level 60) : source_scope.
|
adamc@182
|
37
|
adamc@182
|
38 Open Scope source_scope.
|
adamc@182
|
39 Bind Scope source_scope with type.
|
adamc@182
|
40 Delimit Scope source_scope with source.
|
adamc@182
|
41
|
adamc@182
|
42 Section vars.
|
adamc@182
|
43 Variable var : type -> Type.
|
adamc@182
|
44
|
adamc@182
|
45 Inductive exp : type -> Type :=
|
adamc@182
|
46 | Var : forall t,
|
adamc@182
|
47 var t
|
adamc@182
|
48 -> exp t
|
adamc@182
|
49
|
adamc@182
|
50 | Const : nat -> exp Nat
|
adamc@182
|
51 | Plus : exp Nat -> exp Nat -> exp Nat
|
adamc@182
|
52
|
adamc@182
|
53 | App : forall t1 t2,
|
adamc@182
|
54 exp (t1 --> t2)
|
adamc@182
|
55 -> exp t1
|
adamc@182
|
56 -> exp t2
|
adamc@182
|
57 | Abs : forall t1 t2,
|
adamc@182
|
58 (var t1 -> exp t2)
|
adamc@182
|
59 -> exp (t1 --> t2).
|
adamc@182
|
60 End vars.
|
adamc@182
|
61
|
adamc@182
|
62 Definition Exp t := forall var, exp var t.
|
adamc@182
|
63
|
adamc@182
|
64 Implicit Arguments Var [var t].
|
adamc@182
|
65 Implicit Arguments Const [var].
|
adamc@182
|
66 Implicit Arguments Plus [var].
|
adamc@182
|
67 Implicit Arguments App [var t1 t2].
|
adamc@182
|
68 Implicit Arguments Abs [var t1 t2].
|
adamc@182
|
69
|
adamc@182
|
70 Notation "# v" := (Var v) (at level 70) : source_scope.
|
adamc@182
|
71
|
adamc@182
|
72 Notation "^ n" := (Const n) (at level 70) : source_scope.
|
adamc@182
|
73 Infix "+^" := Plus (left associativity, at level 79) : source_scope.
|
adamc@182
|
74
|
adamc@182
|
75 Infix "@" := App (left associativity, at level 77) : source_scope.
|
adamc@182
|
76 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : source_scope.
|
adamc@182
|
77 Notation "\ ! , e" := (Abs (fun _ => e)) (at level 78) : source_scope.
|
adamc@182
|
78
|
adamc@182
|
79 Bind Scope source_scope with exp.
|
adamc@182
|
80
|
adamc@182
|
81 Definition zero : Exp Nat := fun _ => ^0.
|
adamc@182
|
82 Definition one : Exp Nat := fun _ => ^1.
|
adamc@182
|
83 Definition zpo : Exp Nat := fun _ => zero _ +^ one _.
|
adamc@182
|
84 Definition ident : Exp (Nat --> Nat) := fun _ => \x, #x.
|
adamc@182
|
85 Definition app_ident : Exp Nat := fun _ => ident _ @ zpo _.
|
adamc@182
|
86 Definition app : Exp ((Nat --> Nat) --> Nat --> Nat) := fun _ =>
|
adamc@182
|
87 \f, \x, #f @ #x.
|
adamc@182
|
88 Definition app_ident' : Exp Nat := fun _ => app _ @ ident _ @ zpo _.
|
adamc@182
|
89
|
adamc@182
|
90 Fixpoint typeDenote (t : type) : Set :=
|
adamc@182
|
91 match t with
|
adamc@182
|
92 | Nat => nat
|
adamc@182
|
93 | t1 --> t2 => typeDenote t1 -> typeDenote t2
|
adamc@182
|
94 end.
|
adamc@182
|
95
|
adamc@182
|
96 Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t :=
|
adamc@182
|
97 match e in (exp _ t) return (typeDenote t) with
|
adamc@182
|
98 | Var _ v => v
|
adamc@182
|
99
|
adamc@182
|
100 | Const n => n
|
adamc@182
|
101 | Plus e1 e2 => expDenote e1 + expDenote e2
|
adamc@182
|
102
|
adamc@182
|
103 | App _ _ e1 e2 => (expDenote e1) (expDenote e2)
|
adamc@182
|
104 | Abs _ _ e' => fun x => expDenote (e' x)
|
adamc@182
|
105 end.
|
adamc@182
|
106
|
adamc@182
|
107 Definition ExpDenote t (e : Exp t) := expDenote (e _).
|
adamc@182
|
108
|
adamc@182
|
109 Section exp_equiv.
|
adamc@182
|
110 Variables var1 var2 : type -> Type.
|
adamc@182
|
111
|
adamc@182
|
112 Inductive exp_equiv : list { t : type & var1 t * var2 t }%type -> forall t, exp var1 t -> exp var2 t -> Prop :=
|
adamc@182
|
113 | EqVar : forall G t (v1 : var1 t) v2,
|
adamc@182
|
114 In (existT _ t (v1, v2)) G
|
adamc@182
|
115 -> exp_equiv G (#v1) (#v2)
|
adamc@182
|
116
|
adamc@182
|
117 | EqConst : forall G n,
|
adamc@182
|
118 exp_equiv G (^n) (^n)
|
adamc@182
|
119 | EqPlus : forall G x1 y1 x2 y2,
|
adamc@182
|
120 exp_equiv G x1 x2
|
adamc@182
|
121 -> exp_equiv G y1 y2
|
adamc@182
|
122 -> exp_equiv G (x1 +^ y1) (x2 +^ y2)
|
adamc@182
|
123
|
adamc@182
|
124 | EqApp : forall G t1 t2 (f1 : exp _ (t1 --> t2)) (x1 : exp _ t1) f2 x2,
|
adamc@182
|
125 exp_equiv G f1 f2
|
adamc@182
|
126 -> exp_equiv G x1 x2
|
adamc@182
|
127 -> exp_equiv G (f1 @ x1) (f2 @ x2)
|
adamc@182
|
128 | EqAbs : forall G t1 t2 (f1 : var1 t1 -> exp var1 t2) f2,
|
adamc@182
|
129 (forall v1 v2, exp_equiv (existT _ t1 (v1, v2) :: G) (f1 v1) (f2 v2))
|
adamc@182
|
130 -> exp_equiv G (Abs f1) (Abs f2).
|
adamc@182
|
131 End exp_equiv.
|
adamc@182
|
132
|
adamc@182
|
133 Axiom Exp_equiv : forall t (E : Exp t) var1 var2,
|
adamc@182
|
134 exp_equiv nil (E var1) (E var2).
|
adamc@182
|
135 End Source.
|
adamc@182
|
136
|
adamc@183
|
137 Module Closed.
|
adamc@182
|
138 Inductive type : Type :=
|
adamc@182
|
139 | TNat : type
|
adamc@182
|
140 | Arrow : type -> type -> type
|
adamc@182
|
141 | Code : type -> type -> type -> type
|
adamc@182
|
142 | Prod : type -> type -> type
|
adamc@182
|
143 | TUnit : type.
|
adamc@182
|
144
|
adamc@182
|
145 Notation "'Nat'" := TNat : cc_scope.
|
adamc@182
|
146 Notation "'Unit'" := TUnit : cc_scope.
|
adamc@182
|
147 Infix "-->" := Arrow (right associativity, at level 60) : cc_scope.
|
adamc@182
|
148 Infix "**" := Prod (right associativity, at level 59) : cc_scope.
|
adamc@182
|
149 Notation "env @@ dom ---> ran" := (Code env dom ran) (no associativity, at level 62, dom at next level) : cc_scope.
|
adamc@182
|
150
|
adamc@182
|
151 Bind Scope cc_scope with type.
|
adamc@182
|
152 Delimit Scope cc_scope with cc.
|
adamc@182
|
153
|
adamc@182
|
154 Open Local Scope cc_scope.
|
adamc@182
|
155
|
adamc@182
|
156 Section vars.
|
adamc@182
|
157 Variable var : type -> Set.
|
adamc@182
|
158
|
adamc@182
|
159 Inductive exp : type -> Type :=
|
adamc@182
|
160 | Var : forall t,
|
adamc@182
|
161 var t
|
adamc@182
|
162 -> exp t
|
adamc@182
|
163
|
adamc@182
|
164 | Const : nat -> exp Nat
|
adamc@182
|
165 | Plus : exp Nat -> exp Nat -> exp Nat
|
adamc@182
|
166
|
adamc@182
|
167 | App : forall dom ran,
|
adamc@182
|
168 exp (dom --> ran)
|
adamc@182
|
169 -> exp dom
|
adamc@182
|
170 -> exp ran
|
adamc@182
|
171
|
adamc@182
|
172 | Pack : forall env dom ran,
|
adamc@182
|
173 exp (env @@ dom ---> ran)
|
adamc@182
|
174 -> exp env
|
adamc@182
|
175 -> exp (dom --> ran)
|
adamc@182
|
176
|
adamc@182
|
177 | EUnit : exp Unit
|
adamc@182
|
178
|
adamc@182
|
179 | Pair : forall t1 t2,
|
adamc@182
|
180 exp t1
|
adamc@182
|
181 -> exp t2
|
adamc@182
|
182 -> exp (t1 ** t2)
|
adamc@182
|
183 | Fst : forall t1 t2,
|
adamc@182
|
184 exp (t1 ** t2)
|
adamc@182
|
185 -> exp t1
|
adamc@182
|
186 | Snd : forall t1 t2,
|
adamc@182
|
187 exp (t1 ** t2)
|
adamc@183
|
188 -> exp t2
|
adamc@183
|
189
|
adamc@183
|
190 | Let : forall t1 t2,
|
adamc@183
|
191 exp t1
|
adamc@183
|
192 -> (var t1 -> exp t2)
|
adamc@182
|
193 -> exp t2.
|
adamc@182
|
194
|
adamc@182
|
195 Section funcs.
|
adamc@182
|
196 Variable T : Type.
|
adamc@182
|
197
|
adamc@182
|
198 Inductive funcs : Type :=
|
adamc@182
|
199 | Main : T -> funcs
|
adamc@182
|
200 | Abs : forall env dom ran,
|
adamc@182
|
201 (var env -> var dom -> exp ran)
|
adamc@182
|
202 -> (var (env @@ dom ---> ran) -> funcs)
|
adamc@182
|
203 -> funcs.
|
adamc@182
|
204 End funcs.
|
adamc@182
|
205
|
adamc@182
|
206 Definition prog t := funcs (exp t).
|
adamc@182
|
207 End vars.
|
adamc@182
|
208
|
adamc@182
|
209 Implicit Arguments Var [var t].
|
adamc@182
|
210 Implicit Arguments Const [var].
|
adamc@182
|
211 Implicit Arguments EUnit [var].
|
adamc@182
|
212 Implicit Arguments Fst [var t1 t2].
|
adamc@182
|
213 Implicit Arguments Snd [var t1 t2].
|
adamc@182
|
214
|
adamc@182
|
215 Implicit Arguments Main [var T].
|
adamc@182
|
216 Implicit Arguments Abs [var T env dom ran].
|
adamc@182
|
217
|
adamc@182
|
218 Notation "# v" := (Var v) (at level 70) : cc_scope.
|
adamc@182
|
219
|
adamc@182
|
220 Notation "^ n" := (Const n) (at level 70) : cc_scope.
|
adamc@182
|
221 Infix "+^" := Plus (left associativity, at level 79) : cc_scope.
|
adamc@182
|
222
|
adamc@183
|
223 Infix "@" := App (left associativity, at level 77) : cc_scope.
|
adamc@182
|
224 Infix "##" := Pack (no associativity, at level 71) : cc_scope.
|
adamc@182
|
225
|
adamc@182
|
226 Notation "()" := EUnit : cc_scope.
|
adamc@182
|
227
|
adamc@182
|
228 Notation "[ x1 , x2 ]" := (Pair x1 x2) (at level 73) : cc_scope.
|
adamc@182
|
229 Notation "#1 x" := (Fst x) (at level 72) : cc_scope.
|
adamc@182
|
230 Notation "#2 x" := (Snd x) (at level 72) : cc_scope.
|
adamc@182
|
231
|
adamc@183
|
232 Notation "f <== \\ x , y , e ; fs" :=
|
adamc@182
|
233 (Abs (fun x y => e) (fun f => fs))
|
adamc@182
|
234 (right associativity, at level 80, e at next level) : cc_scope.
|
adamc@182
|
235
|
adamc@183
|
236 Notation "x <- e1 ; e2" := (Let e1 (fun x => e2))
|
adamc@183
|
237 (right associativity, at level 80, e1 at next level) : cc_scope.
|
adamc@183
|
238
|
adamc@182
|
239 Bind Scope cc_scope with exp funcs prog.
|
adamc@182
|
240
|
adamc@182
|
241 Fixpoint typeDenote (t : type) : Set :=
|
adamc@182
|
242 match t with
|
adamc@182
|
243 | Nat => nat
|
adamc@182
|
244 | Unit => unit
|
adamc@182
|
245 | dom --> ran => typeDenote dom -> typeDenote ran
|
adamc@182
|
246 | t1 ** t2 => typeDenote t1 * typeDenote t2
|
adamc@182
|
247 | env @@ dom ---> ran => typeDenote env -> typeDenote dom -> typeDenote ran
|
adamc@182
|
248 end%type.
|
adamc@182
|
249
|
adamc@182
|
250 Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t :=
|
adamc@182
|
251 match e in (exp _ t) return (typeDenote t) with
|
adamc@182
|
252 | Var _ v => v
|
adamc@182
|
253
|
adamc@182
|
254 | Const n => n
|
adamc@182
|
255 | Plus e1 e2 => expDenote e1 + expDenote e2
|
adamc@182
|
256
|
adamc@182
|
257 | App _ _ f x => (expDenote f) (expDenote x)
|
adamc@182
|
258 | Pack _ _ _ f env => (expDenote f) (expDenote env)
|
adamc@182
|
259
|
adamc@182
|
260 | EUnit => tt
|
adamc@182
|
261
|
adamc@182
|
262 | Pair _ _ e1 e2 => (expDenote e1, expDenote e2)
|
adamc@182
|
263 | Fst _ _ e' => fst (expDenote e')
|
adamc@182
|
264 | Snd _ _ e' => snd (expDenote e')
|
adamc@183
|
265
|
adamc@183
|
266 | Let _ _ e1 e2 => expDenote (e2 (expDenote e1))
|
adamc@182
|
267 end.
|
adamc@182
|
268
|
adamc@182
|
269 Fixpoint funcsDenote T (fs : funcs typeDenote T) : T :=
|
adamc@182
|
270 match fs with
|
adamc@182
|
271 | Main v => v
|
adamc@182
|
272 | Abs _ _ _ e fs =>
|
adamc@182
|
273 funcsDenote (fs (fun env arg => expDenote (e env arg)))
|
adamc@182
|
274 end.
|
adamc@182
|
275
|
adamc@182
|
276 Definition progDenote t (p : prog typeDenote t) : typeDenote t :=
|
adamc@182
|
277 expDenote (funcsDenote p).
|
adamc@182
|
278
|
adamc@182
|
279 Definition Exp t := forall var, exp var t.
|
adamc@182
|
280 Definition Prog t := forall var, prog var t.
|
adamc@182
|
281
|
adamc@182
|
282 Definition ExpDenote t (E : Exp t) := expDenote (E _).
|
adamc@182
|
283 Definition ProgDenote t (P : Prog t) := progDenote (P _).
|
adamc@182
|
284 End Closed.
|
adamc@182
|
285
|
adamc@183
|
286 Import Source Closed.
|
adamc@183
|
287
|
adamc@183
|
288 Section splice.
|
adamc@183
|
289 Open Local Scope cc_scope.
|
adamc@183
|
290
|
adamc@183
|
291 Fixpoint spliceFuncs var T1 (fs : funcs var T1)
|
adamc@183
|
292 T2 (f : T1 -> funcs var T2) {struct fs} : funcs var T2 :=
|
adamc@183
|
293 match fs with
|
adamc@183
|
294 | Main v => f v
|
adamc@183
|
295 | Abs _ _ _ e fs' => Abs e (fun x => spliceFuncs (fs' x) f)
|
adamc@183
|
296 end.
|
adamc@183
|
297 End splice.
|
adamc@183
|
298
|
adamc@183
|
299 Notation "x <-- e1 ; e2" := (spliceFuncs e1 (fun x => e2))
|
adamc@183
|
300 (right associativity, at level 80, e1 at next level) : cc_scope.
|
adamc@183
|
301
|
adamc@183
|
302 Definition natvar (_ : Source.type) := nat.
|
adamc@183
|
303 Definition isfree := hlist (fun (_ : Source.type) => bool).
|
adamc@183
|
304
|
adamc@183
|
305 Ltac maybe_destruct E :=
|
adamc@183
|
306 match goal with
|
adamc@183
|
307 | [ x : _ |- _ ] =>
|
adamc@183
|
308 match E with
|
adamc@183
|
309 | x => idtac
|
adamc@183
|
310 end
|
adamc@183
|
311 | _ =>
|
adamc@183
|
312 match E with
|
adamc@183
|
313 | eq_nat_dec _ _ => idtac
|
adamc@183
|
314 end
|
adamc@183
|
315 end; destruct E.
|
adamc@183
|
316
|
adamc@183
|
317 Ltac my_crush :=
|
adamc@183
|
318 crush; repeat (match goal with
|
adamc@183
|
319 | [ x : (_ * _)%type |- _ ] => destruct x
|
adamc@183
|
320 | [ |- context[if ?B then _ else _] ] => maybe_destruct B
|
adamc@183
|
321 | [ _ : context[if ?B then _ else _] |- _ ] => maybe_destruct B
|
adamc@183
|
322 end; crush).
|
adamc@183
|
323
|
adamc@183
|
324 Section isfree.
|
adamc@183
|
325 Import Source.
|
adamc@183
|
326 Open Local Scope source_scope.
|
adamc@183
|
327
|
adamc@183
|
328 Hint Extern 3 False => omega.
|
adamc@183
|
329
|
adamc@183
|
330 Fixpoint lookup_type (envT : list Source.type) (n : nat) {struct envT}
|
adamc@183
|
331 : isfree envT -> option Source.type :=
|
adamc@183
|
332 match envT return (isfree envT -> _) with
|
adamc@183
|
333 | nil => fun _ => None
|
adamc@183
|
334 | first :: rest => fun fvs =>
|
adamc@183
|
335 if eq_nat_dec n (length rest)
|
adamc@183
|
336 then match fvs with
|
adamc@183
|
337 | (true, _) => Some first
|
adamc@183
|
338 | (false, _) => None
|
adamc@183
|
339 end
|
adamc@183
|
340 else lookup_type rest n (snd fvs)
|
adamc@183
|
341 end.
|
adamc@183
|
342
|
adamc@183
|
343 Implicit Arguments lookup_type [envT].
|
adamc@183
|
344
|
adamc@183
|
345 Notation ok := (fun (envT : list Source.type) (fvs : isfree envT)
|
adamc@183
|
346 (n : nat) (t : Source.type)
|
adamc@183
|
347 => lookup_type n fvs = Some t).
|
adamc@183
|
348
|
adamc@183
|
349 Fixpoint wfExp (envT : list Source.type) (fvs : isfree envT)
|
adamc@183
|
350 t (e : Source.exp natvar t) {struct e} : Prop :=
|
adamc@183
|
351 match e with
|
adamc@183
|
352 | Var t v => ok envT fvs v t
|
adamc@183
|
353
|
adamc@183
|
354 | Const _ => True
|
adamc@183
|
355 | Plus e1 e2 => wfExp envT fvs e1 /\ wfExp envT fvs e2
|
adamc@183
|
356
|
adamc@183
|
357 | App _ _ e1 e2 => wfExp envT fvs e1 /\ wfExp envT fvs e2
|
adamc@183
|
358 | Abs dom _ e' => wfExp (dom :: envT) (true ::: fvs) (e' (length envT))
|
adamc@183
|
359 end.
|
adamc@183
|
360
|
adamc@183
|
361 Implicit Arguments wfExp [envT t].
|
adamc@183
|
362
|
adamc@183
|
363 Theorem wfExp_weaken : forall t (e : exp natvar t) envT (fvs fvs' : isfree envT),
|
adamc@183
|
364 wfExp fvs e
|
adamc@183
|
365 -> (forall n t, ok _ fvs n t -> ok _ fvs' n t)
|
adamc@183
|
366 -> wfExp fvs' e.
|
adamc@183
|
367 Hint Extern 1 (lookup_type (envT := _ :: _) _ _ = Some _) =>
|
adamc@183
|
368 simpl in *; my_crush.
|
adamc@183
|
369
|
adamc@183
|
370 induction e; my_crush; eauto.
|
adamc@183
|
371 Defined.
|
adamc@183
|
372
|
adamc@183
|
373 Fixpoint isfree_none (envT : list Source.type) : isfree envT :=
|
adamc@183
|
374 match envT return (isfree envT) with
|
adamc@183
|
375 | nil => tt
|
adamc@183
|
376 | _ :: _ => (false, isfree_none _)
|
adamc@183
|
377 end.
|
adamc@183
|
378
|
adamc@183
|
379 Implicit Arguments isfree_none [envT].
|
adamc@183
|
380
|
adamc@183
|
381 Fixpoint isfree_one (envT : list Source.type) (n : nat) {struct envT} : isfree envT :=
|
adamc@183
|
382 match envT return (isfree envT) with
|
adamc@183
|
383 | nil => tt
|
adamc@183
|
384 | _ :: rest =>
|
adamc@183
|
385 if eq_nat_dec n (length rest)
|
adamc@183
|
386 then (true, isfree_none)
|
adamc@183
|
387 else (false, isfree_one _ n)
|
adamc@183
|
388 end.
|
adamc@183
|
389
|
adamc@183
|
390 Implicit Arguments isfree_one [envT].
|
adamc@183
|
391
|
adamc@183
|
392 Fixpoint isfree_merge (envT : list Source.type) : isfree envT -> isfree envT -> isfree envT :=
|
adamc@183
|
393 match envT return (isfree envT -> isfree envT -> isfree envT) with
|
adamc@183
|
394 | nil => fun _ _ => tt
|
adamc@183
|
395 | _ :: _ => fun fv1 fv2 => (fst fv1 || fst fv2, isfree_merge _ (snd fv1) (snd fv2))
|
adamc@183
|
396 end.
|
adamc@183
|
397
|
adamc@183
|
398 Implicit Arguments isfree_merge [envT].
|
adamc@183
|
399
|
adamc@183
|
400 Fixpoint fvsExp t (e : exp natvar t)
|
adamc@183
|
401 (envT : list Source.type) {struct e} : isfree envT :=
|
adamc@183
|
402 match e with
|
adamc@183
|
403 | Var _ n => isfree_one n
|
adamc@183
|
404
|
adamc@183
|
405 | Const _ => isfree_none
|
adamc@183
|
406 | Plus e1 e2 => isfree_merge (fvsExp e1 envT) (fvsExp e2 envT)
|
adamc@183
|
407
|
adamc@183
|
408 | App _ _ e1 e2 => isfree_merge (fvsExp e1 envT) (fvsExp e2 envT)
|
adamc@183
|
409 | Abs dom _ e' => snd (fvsExp (e' (length envT)) (dom :: envT))
|
adamc@183
|
410 end.
|
adamc@183
|
411
|
adamc@183
|
412 Lemma isfree_one_correct : forall t (v : natvar t) envT fvs,
|
adamc@183
|
413 ok envT fvs v t
|
adamc@183
|
414 -> ok envT (isfree_one (envT:=envT) v) v t.
|
adamc@183
|
415 induction envT; my_crush; eauto.
|
adamc@183
|
416 Defined.
|
adamc@183
|
417
|
adamc@183
|
418 Lemma isfree_merge_correct1 : forall t (v : natvar t) envT fvs1 fvs2,
|
adamc@183
|
419 ok envT fvs1 v t
|
adamc@183
|
420 -> ok envT (isfree_merge (envT:=envT) fvs1 fvs2) v t.
|
adamc@183
|
421 induction envT; my_crush; eauto.
|
adamc@183
|
422 Defined.
|
adamc@183
|
423
|
adamc@183
|
424 Hint Rewrite orb_true_r : cpdt.
|
adamc@183
|
425
|
adamc@183
|
426 Lemma isfree_merge_correct2 : forall t (v : natvar t) envT fvs1 fvs2,
|
adamc@183
|
427 ok envT fvs2 v t
|
adamc@183
|
428 -> ok envT (isfree_merge (envT:=envT) fvs1 fvs2) v t.
|
adamc@183
|
429 induction envT; my_crush; eauto.
|
adamc@183
|
430 Defined.
|
adamc@183
|
431
|
adamc@183
|
432 Hint Resolve isfree_one_correct isfree_merge_correct1 isfree_merge_correct2.
|
adamc@183
|
433
|
adamc@183
|
434 Lemma fvsExp_correct : forall t (e : exp natvar t)
|
adamc@183
|
435 envT (fvs : isfree envT), wfExp fvs e
|
adamc@183
|
436 -> forall (fvs' : isfree envT),
|
adamc@183
|
437 (forall v t, ok envT (fvsExp e envT) v t -> ok envT fvs' v t)
|
adamc@183
|
438 -> wfExp fvs' e.
|
adamc@183
|
439 Hint Extern 1 (_ = _) =>
|
adamc@183
|
440 match goal with
|
adamc@183
|
441 | [ H : lookup_type _ (fvsExp ?X ?Y) = _ |- _ ] =>
|
adamc@183
|
442 destruct (fvsExp X Y); my_crush
|
adamc@183
|
443 end.
|
adamc@183
|
444
|
adamc@183
|
445 induction e; my_crush; eauto.
|
adamc@183
|
446 Defined.
|
adamc@183
|
447
|
adamc@183
|
448 Lemma lookup_type_unique : forall v t1 t2 envT (fvs1 fvs2 : isfree envT),
|
adamc@183
|
449 lookup_type v fvs1 = Some t1
|
adamc@183
|
450 -> lookup_type v fvs2 = Some t2
|
adamc@183
|
451 -> t1 = t2.
|
adamc@183
|
452 induction envT; my_crush; eauto.
|
adamc@183
|
453 Defined.
|
adamc@183
|
454
|
adamc@183
|
455 Implicit Arguments lookup_type_unique [v t1 t2 envT fvs1 fvs2].
|
adamc@183
|
456
|
adamc@183
|
457 Hint Extern 2 (lookup_type _ _ = Some _) =>
|
adamc@183
|
458 match goal with
|
adamc@183
|
459 | [ H1 : lookup_type ?v _ = Some _,
|
adamc@183
|
460 H2 : lookup_type ?v _ = Some _ |- _ ] =>
|
adamc@183
|
461 (generalize (lookup_type_unique H1 H2); intro; subst)
|
adamc@183
|
462 || rewrite <- (lookup_type_unique H1 H2)
|
adamc@183
|
463 end.
|
adamc@183
|
464
|
adamc@183
|
465 Lemma lookup_none : forall v t envT,
|
adamc@183
|
466 lookup_type (envT:=envT) v (isfree_none (envT:=envT)) = Some t
|
adamc@183
|
467 -> False.
|
adamc@183
|
468 induction envT; my_crush.
|
adamc@183
|
469 Defined.
|
adamc@183
|
470
|
adamc@183
|
471 Hint Extern 2 (_ = _) => elimtype False; eapply lookup_none; eassumption.
|
adamc@183
|
472
|
adamc@183
|
473 Lemma lookup_one : forall v' v t envT,
|
adamc@183
|
474 lookup_type (envT:=envT) v' (isfree_one (envT:=envT) v) = Some t
|
adamc@183
|
475 -> v' = v.
|
adamc@183
|
476 induction envT; my_crush.
|
adamc@183
|
477 Defined.
|
adamc@183
|
478
|
adamc@183
|
479 Implicit Arguments lookup_one [v' v t envT].
|
adamc@183
|
480
|
adamc@183
|
481 Hint Extern 2 (lookup_type _ _ = Some _) =>
|
adamc@183
|
482 match goal with
|
adamc@183
|
483 | [ H : lookup_type _ _ = Some _ |- _ ] =>
|
adamc@183
|
484 generalize (lookup_one H); intro; subst
|
adamc@183
|
485 end.
|
adamc@183
|
486
|
adamc@183
|
487 Lemma lookup_merge : forall v t envT (fvs1 fvs2 : isfree envT),
|
adamc@183
|
488 lookup_type v (isfree_merge fvs1 fvs2) = Some t
|
adamc@183
|
489 -> lookup_type v fvs1 = Some t
|
adamc@183
|
490 \/ lookup_type v fvs2 = Some t.
|
adamc@183
|
491 induction envT; my_crush.
|
adamc@183
|
492 Defined.
|
adamc@183
|
493
|
adamc@183
|
494 Implicit Arguments lookup_merge [v t envT fvs1 fvs2].
|
adamc@183
|
495
|
adamc@183
|
496 Lemma lookup_bound : forall v t envT (fvs : isfree envT),
|
adamc@183
|
497 lookup_type v fvs = Some t
|
adamc@183
|
498 -> v < length envT.
|
adamc@183
|
499 Hint Resolve lt_S.
|
adamc@183
|
500 induction envT; my_crush; eauto.
|
adamc@183
|
501 Defined.
|
adamc@183
|
502
|
adamc@183
|
503 Hint Resolve lookup_bound.
|
adamc@183
|
504
|
adamc@183
|
505 Lemma lookup_bound_contra : forall t envT (fvs : isfree envT),
|
adamc@183
|
506 lookup_type (length envT) fvs = Some t
|
adamc@183
|
507 -> False.
|
adamc@183
|
508 intros; assert (length envT < length envT); eauto.
|
adamc@183
|
509 Defined.
|
adamc@183
|
510
|
adamc@183
|
511 Hint Resolve lookup_bound_contra.
|
adamc@183
|
512
|
adamc@183
|
513 Hint Extern 3 (_ = _) => elimtype False; omega.
|
adamc@183
|
514
|
adamc@183
|
515 Lemma lookup_push_drop : forall v t t' envT fvs,
|
adamc@183
|
516 v < length envT
|
adamc@183
|
517 -> lookup_type (envT := t :: envT) v (true, fvs) = Some t'
|
adamc@183
|
518 -> lookup_type (envT := envT) v fvs = Some t'.
|
adamc@183
|
519 my_crush.
|
adamc@183
|
520 Defined.
|
adamc@183
|
521
|
adamc@183
|
522 Lemma lookup_push_add : forall v t t' envT fvs,
|
adamc@183
|
523 lookup_type (envT := envT) v (snd fvs) = Some t'
|
adamc@183
|
524 -> lookup_type (envT := t :: envT) v fvs = Some t'.
|
adamc@183
|
525 my_crush; elimtype False; eauto.
|
adamc@183
|
526 Defined.
|
adamc@183
|
527
|
adamc@183
|
528 Hint Resolve lookup_bound lookup_push_drop lookup_push_add.
|
adamc@183
|
529
|
adamc@183
|
530 Theorem fvsExp_minimal : forall t (e : exp natvar t)
|
adamc@183
|
531 envT (fvs : isfree envT), wfExp fvs e
|
adamc@183
|
532 -> (forall v t, ok envT (fvsExp e envT) v t -> ok envT fvs v t).
|
adamc@183
|
533 Hint Extern 1 (_ = _) =>
|
adamc@183
|
534 match goal with
|
adamc@183
|
535 | [ H : lookup_type _ (isfree_merge _ _) = Some _ |- _ ] =>
|
adamc@183
|
536 destruct (lookup_merge H); clear H; eauto
|
adamc@183
|
537 end.
|
adamc@183
|
538
|
adamc@183
|
539 induction e; my_crush; eauto.
|
adamc@183
|
540 Defined.
|
adamc@183
|
541
|
adamc@183
|
542 Fixpoint ccType (t : Source.type) : Closed.type :=
|
adamc@183
|
543 match t with
|
adamc@183
|
544 | Nat%source => Nat
|
adamc@183
|
545 | (dom --> ran)%source => ccType dom --> ccType ran
|
adamc@183
|
546 end%cc.
|
adamc@183
|
547
|
adamc@183
|
548 Open Local Scope cc_scope.
|
adamc@183
|
549
|
adamc@183
|
550 Fixpoint envType (envT : list Source.type) : isfree envT -> Closed.type :=
|
adamc@183
|
551 match envT return (isfree envT -> _) with
|
adamc@183
|
552 | nil => fun _ => Unit
|
adamc@183
|
553 | t :: _ => fun tup =>
|
adamc@183
|
554 if fst tup
|
adamc@183
|
555 then ccType t ** envType _ (snd tup)
|
adamc@183
|
556 else envType _ (snd tup)
|
adamc@183
|
557 end.
|
adamc@183
|
558
|
adamc@183
|
559 Implicit Arguments envType [envT].
|
adamc@183
|
560
|
adamc@183
|
561 Fixpoint envOf (var : Closed.type -> Set) (envT : list Source.type) {struct envT}
|
adamc@183
|
562 : isfree envT -> Set :=
|
adamc@183
|
563 match envT return (isfree envT -> _) with
|
adamc@183
|
564 | nil => fun _ => unit
|
adamc@183
|
565 | first :: rest => fun fvs =>
|
adamc@183
|
566 match fvs with
|
adamc@183
|
567 | (true, fvs') => (var (ccType first) * envOf var rest fvs')%type
|
adamc@183
|
568 | (false, fvs') => envOf var rest fvs'
|
adamc@183
|
569 end
|
adamc@183
|
570 end.
|
adamc@183
|
571
|
adamc@183
|
572 Implicit Arguments envOf [envT].
|
adamc@183
|
573
|
adamc@183
|
574 Notation "var <| to" := (match to with
|
adamc@183
|
575 | None => unit
|
adamc@183
|
576 | Some t => var (ccType t)
|
adamc@183
|
577 end) (no associativity, at level 70).
|
adamc@183
|
578
|
adamc@183
|
579 Fixpoint lookup (var : Closed.type -> Set) (envT : list Source.type) :
|
adamc@183
|
580 forall (n : nat) (fvs : isfree envT), envOf var fvs -> var <| lookup_type n fvs :=
|
adamc@183
|
581 match envT return (forall (n : nat) (fvs : isfree envT), envOf var fvs
|
adamc@183
|
582 -> var <| lookup_type n fvs) with
|
adamc@183
|
583 | nil => fun _ _ _ => tt
|
adamc@183
|
584 | first :: rest => fun n fvs =>
|
adamc@183
|
585 match (eq_nat_dec n (length rest)) as Heq return
|
adamc@183
|
586 (envOf var (envT := first :: rest) fvs
|
adamc@183
|
587 -> var <| (if Heq
|
adamc@183
|
588 then match fvs with
|
adamc@183
|
589 | (true, _) => Some first
|
adamc@183
|
590 | (false, _) => None
|
adamc@183
|
591 end
|
adamc@183
|
592 else lookup_type n (snd fvs))) with
|
adamc@183
|
593 | left _ =>
|
adamc@183
|
594 match fvs return (envOf var (envT := first :: rest) fvs
|
adamc@183
|
595 -> var <| (match fvs with
|
adamc@183
|
596 | (true, _) => Some first
|
adamc@183
|
597 | (false, _) => None
|
adamc@183
|
598 end)) with
|
adamc@183
|
599 | (true, _) => fun env => fst env
|
adamc@183
|
600 | (false, _) => fun _ => tt
|
adamc@183
|
601 end
|
adamc@183
|
602 | right _ =>
|
adamc@183
|
603 match fvs return (envOf var (envT := first :: rest) fvs
|
adamc@183
|
604 -> var <| (lookup_type n (snd fvs))) with
|
adamc@183
|
605 | (true, fvs') => fun env => lookup var rest n fvs' (snd env)
|
adamc@183
|
606 | (false, fvs') => fun env => lookup var rest n fvs' env
|
adamc@183
|
607 end
|
adamc@183
|
608 end
|
adamc@183
|
609 end.
|
adamc@183
|
610
|
adamc@183
|
611 Theorem lok : forall var n t envT (fvs : isfree envT),
|
adamc@183
|
612 lookup_type n fvs = Some t
|
adamc@183
|
613 -> var <| lookup_type n fvs = var (ccType t).
|
adamc@183
|
614 crush.
|
adamc@183
|
615 Defined.
|
adamc@183
|
616 End isfree.
|
adamc@183
|
617
|
adamc@183
|
618 Implicit Arguments lookup_type [envT].
|
adamc@183
|
619 Implicit Arguments lookup [envT fvs].
|
adamc@183
|
620 Implicit Arguments wfExp [t envT].
|
adamc@183
|
621 Implicit Arguments envType [envT].
|
adamc@183
|
622 Implicit Arguments envOf [envT].
|
adamc@183
|
623 Implicit Arguments lok [var n t envT fvs].
|
adamc@183
|
624
|
adamc@183
|
625 Section lookup_hints.
|
adamc@183
|
626 Hint Resolve lookup_bound_contra.
|
adamc@183
|
627
|
adamc@183
|
628 (*Ltac my_chooser T k :=
|
adamc@183
|
629 match T with
|
adamc@183
|
630 | ptype =>
|
adamc@183
|
631 match goal with
|
adamc@183
|
632 | [ H : lookup _ _ = Some ?t |- _ ] => k t
|
adamc@183
|
633 end
|
adamc@183
|
634 | _ => default_chooser T k
|
adamc@183
|
635 end.
|
adamc@183
|
636
|
adamc@183
|
637 Ltac my_matching := matching equation my_chooser.*)
|
adamc@183
|
638
|
adamc@183
|
639 Hint Resolve lookup_bound_contra.
|
adamc@183
|
640
|
adamc@183
|
641 Lemma lookup_type_push : forall t' envT (fvs1 fvs2 : isfree envT) b1 b2,
|
adamc@183
|
642 (forall (n : nat) (t : Source.type),
|
adamc@183
|
643 lookup_type (envT := t' :: envT) n (b1, fvs1) = Some t ->
|
adamc@183
|
644 lookup_type (envT := t' :: envT) n (b2, fvs2) = Some t)
|
adamc@183
|
645 -> (forall (n : nat) (t : Source.type),
|
adamc@183
|
646 lookup_type n fvs1 = Some t ->
|
adamc@183
|
647 lookup_type n fvs2 = Some t).
|
adamc@183
|
648 intros until b2; intro H; intros n t;
|
adamc@183
|
649 generalize (H n t); my_crush; elimtype False; eauto.
|
adamc@183
|
650 Defined.
|
adamc@183
|
651
|
adamc@183
|
652 Lemma lookup_type_push_contra : forall t' envT (fvs1 fvs2 : isfree envT),
|
adamc@183
|
653 (forall (n : nat) (t : Source.type),
|
adamc@183
|
654 lookup_type (envT := t' :: envT) n (true, fvs1) = Some t ->
|
adamc@183
|
655 lookup_type (envT := t' :: envT) n (false, fvs2) = Some t)
|
adamc@183
|
656 -> False.
|
adamc@183
|
657 intros until fvs2; intro H; generalize (H (length envT) t'); my_crush.
|
adamc@183
|
658 Defined.
|
adamc@183
|
659 End lookup_hints.
|
adamc@183
|
660
|
adamc@183
|
661 Section packing.
|
adamc@183
|
662 Open Local Scope cc_scope.
|
adamc@183
|
663
|
adamc@183
|
664 Hint Resolve lookup_type_push lookup_type_push_contra.
|
adamc@183
|
665
|
adamc@183
|
666 Definition packExp (var : Closed.type -> Set) (envT : list Source.type)
|
adamc@183
|
667 (fvs1 fvs2 : isfree envT)
|
adamc@183
|
668 : (forall n t, lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t)
|
adamc@183
|
669 -> envOf var fvs2 -> exp var (envType fvs1).
|
adamc@183
|
670 refine (fix packExp (var : Closed.type -> Set) (envT : list Source.type) {struct envT}
|
adamc@183
|
671 : forall fvs1 fvs2 : isfree envT,
|
adamc@183
|
672 (forall n t, lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t)
|
adamc@183
|
673 -> envOf var fvs2 -> exp var (envType fvs1) :=
|
adamc@183
|
674 match envT return (forall fvs1 fvs2 : isfree envT,
|
adamc@183
|
675 (forall n t, lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t)
|
adamc@183
|
676 -> envOf var fvs2
|
adamc@183
|
677 -> exp var (envType fvs1)) with
|
adamc@183
|
678 | nil => fun _ _ _ _ => ()
|
adamc@183
|
679 | first :: rest => fun fvs1 =>
|
adamc@183
|
680 match fvs1 return (forall fvs2 : isfree (first :: rest),
|
adamc@183
|
681 (forall n t, lookup_type (envT := first :: rest) n fvs1 = Some t
|
adamc@183
|
682 -> lookup_type n fvs2 = Some t)
|
adamc@183
|
683 -> envOf var fvs2
|
adamc@183
|
684 -> exp var (envType (envT := first :: rest) fvs1)) with
|
adamc@183
|
685 | (false, fvs1') => fun fvs2 =>
|
adamc@183
|
686 match fvs2 return ((forall n t, lookup_type (envT := first :: rest) n (false, fvs1') = Some t
|
adamc@183
|
687 -> lookup_type (envT := first :: rest) n fvs2 = Some t)
|
adamc@183
|
688 -> envOf (envT := first :: rest) var fvs2
|
adamc@183
|
689 -> exp var (envType (envT := first :: rest) (false, fvs1'))) with
|
adamc@183
|
690 | (false, fvs2') => fun Hmin env =>
|
adamc@183
|
691 packExp var _ fvs1' fvs2' _ env
|
adamc@183
|
692 | (true, fvs2') => fun Hmin env =>
|
adamc@183
|
693 packExp var _ fvs1' fvs2' _ (snd env)
|
adamc@183
|
694 end
|
adamc@183
|
695 | (true, fvs1') => fun fvs2 =>
|
adamc@183
|
696 match fvs2 return ((forall n t, lookup_type (envT := first :: rest) n (true, fvs1') = Some t
|
adamc@183
|
697 -> lookup_type (envT := first :: rest) n fvs2 = Some t)
|
adamc@183
|
698 -> envOf (envT := first :: rest) var fvs2
|
adamc@183
|
699 -> exp var (envType (envT := first :: rest) (true, fvs1'))) with
|
adamc@183
|
700 | (false, fvs2') => fun Hmin env =>
|
adamc@183
|
701 False_rect _ _
|
adamc@183
|
702 | (true, fvs2') => fun Hmin env =>
|
adamc@183
|
703 [#(fst env), packExp var _ fvs1' fvs2' _ (snd env)]
|
adamc@183
|
704 end
|
adamc@183
|
705 end
|
adamc@183
|
706 end); eauto.
|
adamc@183
|
707 Defined.
|
adamc@183
|
708
|
adamc@183
|
709 Hint Resolve fvsExp_correct fvsExp_minimal.
|
adamc@183
|
710 Hint Resolve lookup_push_drop lookup_bound lookup_push_add.
|
adamc@183
|
711
|
adamc@183
|
712 Implicit Arguments packExp [var envT].
|
adamc@183
|
713
|
adamc@183
|
714 Fixpoint unpackExp (var : Closed.type -> Set) t (envT : list Source.type) {struct envT}
|
adamc@183
|
715 : forall fvs : isfree envT,
|
adamc@183
|
716 exp var (envType fvs)
|
adamc@183
|
717 -> (envOf var fvs -> exp var t) -> exp var t :=
|
adamc@183
|
718 match envT return (forall fvs : isfree envT,
|
adamc@183
|
719 exp var (envType fvs)
|
adamc@183
|
720 -> (envOf var fvs -> exp var t) -> exp var t) with
|
adamc@183
|
721 | nil => fun _ _ f => f tt
|
adamc@183
|
722 | first :: rest => fun fvs =>
|
adamc@183
|
723 match fvs return (exp var (envType (envT := first :: rest) fvs)
|
adamc@183
|
724 -> (envOf var (envT := first :: rest) fvs -> exp var t)
|
adamc@183
|
725 -> exp var t) with
|
adamc@183
|
726 | (false, fvs') => fun p f =>
|
adamc@183
|
727 unpackExp rest fvs' p f
|
adamc@183
|
728 | (true, fvs') => fun p f =>
|
adamc@183
|
729 x <- #1 p;
|
adamc@183
|
730 unpackExp rest fvs' (#2 p)
|
adamc@183
|
731 (fun env => f (x, env))
|
adamc@183
|
732 end
|
adamc@183
|
733 end.
|
adamc@183
|
734
|
adamc@183
|
735 Implicit Arguments unpackExp [var t envT fvs].
|
adamc@183
|
736
|
adamc@183
|
737 Theorem wfExp_lax : forall t t' envT (fvs : isfree envT) (e : Source.exp natvar t),
|
adamc@183
|
738 wfExp (envT := t' :: envT) (true, fvs) e
|
adamc@183
|
739 -> wfExp (envT := t' :: envT) (true, snd (fvsExp e (t' :: envT))) e.
|
adamc@183
|
740 Hint Extern 1 (_ = _) =>
|
adamc@183
|
741 match goal with
|
adamc@183
|
742 | [ H : lookup_type _ (fvsExp ?X ?Y) = _ |- _ ] =>
|
adamc@183
|
743 destruct (fvsExp X Y); my_crush
|
adamc@183
|
744 end.
|
adamc@183
|
745 eauto.
|
adamc@183
|
746 Defined.
|
adamc@183
|
747
|
adamc@183
|
748 Implicit Arguments wfExp_lax [t t' envT fvs e].
|
adamc@183
|
749
|
adamc@183
|
750 Lemma inclusion : forall t t' envT fvs (e : Source.exp natvar t),
|
adamc@183
|
751 wfExp (envT := t' :: envT) (true, fvs) e
|
adamc@183
|
752 -> (forall n t, lookup_type n (snd (fvsExp e (t' :: envT))) = Some t
|
adamc@183
|
753 -> lookup_type n fvs = Some t).
|
adamc@183
|
754 eauto.
|
adamc@183
|
755 Defined.
|
adamc@183
|
756
|
adamc@183
|
757 Implicit Arguments inclusion [t t' envT fvs e].
|
adamc@183
|
758
|
adamc@183
|
759 Definition env_prog var t envT (fvs : isfree envT) :=
|
adamc@183
|
760 funcs var (envOf var fvs -> Closed.exp var t).
|
adamc@183
|
761
|
adamc@183
|
762 Implicit Arguments env_prog [envT].
|
adamc@183
|
763
|
adamc@183
|
764 Axiom cheat : forall T, T.
|
adamc@183
|
765
|
adamc@183
|
766 Import Source.
|
adamc@183
|
767 Open Local Scope cc_scope.
|
adamc@183
|
768
|
adamc@183
|
769 Fixpoint ccExp var t (e : Source.exp natvar t)
|
adamc@183
|
770 (envT : list Source.type) (fvs : isfree envT)
|
adamc@183
|
771 {struct e} : wfExp fvs e -> env_prog var (ccType t) fvs :=
|
adamc@183
|
772 match e in (Source.exp _ t) return (wfExp fvs e -> env_prog var (ccType t) fvs) with
|
adamc@183
|
773 | Const n => fun _ => Main (fun _ => ^n)
|
adamc@183
|
774 | Plus e1 e2 => fun wf =>
|
adamc@183
|
775 n1 <-- ccExp var e1 _ fvs (proj1 wf);
|
adamc@183
|
776 n2 <-- ccExp var e2 _ fvs (proj2 wf);
|
adamc@183
|
777 Main (fun env => n1 env +^ n2 env)
|
adamc@183
|
778
|
adamc@183
|
779 | Var _ n => fun wf =>
|
adamc@183
|
780 Main (fun env => #(match lok wf in _ = T return T with
|
adamc@183
|
781 | refl_equal => lookup var n env
|
adamc@183
|
782 end))
|
adamc@183
|
783
|
adamc@183
|
784 | App _ _ f x => fun wf =>
|
adamc@183
|
785 f' <-- ccExp var f _ fvs (proj1 wf);
|
adamc@183
|
786 x' <-- ccExp var x _ fvs (proj2 wf);
|
adamc@183
|
787 Main (fun env => f' env @ x' env)
|
adamc@183
|
788
|
adamc@183
|
789 | Abs dom _ b => fun wf =>
|
adamc@183
|
790 b' <-- ccExp var (b (length envT)) (dom :: envT) _ (wfExp_lax wf);
|
adamc@183
|
791 f <== \\env, arg, unpackExp (#env) (fun env => b' (arg, env));
|
adamc@183
|
792 Main (fun env => #f ##
|
adamc@183
|
793 packExp
|
adamc@183
|
794 (snd (fvsExp (b (length envT)) (dom :: envT)))
|
adamc@183
|
795 fvs (inclusion wf) env)
|
adamc@183
|
796 end.
|
adamc@183
|
797 End packing.
|
adamc@183
|
798
|
adamc@183
|
799 Implicit Arguments packExp [var envT].
|
adamc@183
|
800 Implicit Arguments unpackExp [var t envT fvs].
|
adamc@183
|
801
|
adamc@183
|
802 Implicit Arguments ccExp [var t envT].
|
adamc@183
|
803
|
adamc@184
|
804 Fixpoint map_funcs var T1 T2 (f : T1 -> T2) (fs : funcs var T1) {struct fs}
|
adamc@184
|
805 : funcs var T2 :=
|
adamc@183
|
806 match fs with
|
adamc@184
|
807 | Main v => Main (f v)
|
adamc@184
|
808 | Abs _ _ _ e fs' => Abs e (fun x => map_funcs f (fs' x))
|
adamc@183
|
809 end.
|
adamc@183
|
810
|
adamc@184
|
811 Definition CcTerm' t (E : Source.Exp t) (Hwf : wfExp (envT := nil) tt (E _)) : Prog (ccType t) :=
|
adamc@184
|
812 fun _ => map_funcs (fun f => f tt) (ccExp (E _) (envT := nil) tt Hwf).
|
adamc@183
|
813
|
adamc@183
|
814
|
adamc@183
|
815 (** * Correctness *)
|
adamc@183
|
816
|
adamc@184
|
817 Section spliceFuncs_correct.
|
adamc@184
|
818 Variables T1 T2 : Type.
|
adamc@184
|
819 Variable f : T1 -> funcs typeDenote T2.
|
adamc@183
|
820
|
adamc@184
|
821 Theorem spliceFuncs_correct : forall fs,
|
adamc@184
|
822 funcsDenote (spliceFuncs fs f)
|
adamc@184
|
823 = funcsDenote (f (funcsDenote fs)).
|
adamc@184
|
824 induction fs; crush.
|
adamc@183
|
825 Qed.
|
adamc@183
|
826 End spliceFuncs_correct.
|
adamc@183
|
827
|
adamc@183
|
828
|
adamc@183
|
829 Notation "var <| to" := (match to with
|
adamc@183
|
830 | None => unit
|
adamc@184
|
831 | Some t => var (ccType t)
|
adamc@183
|
832 end) (no associativity, at level 70).
|
adamc@183
|
833
|
adamc@183
|
834 Section packing_correct.
|
adamc@184
|
835 Fixpoint makeEnv (envT : list Source.type) : forall (fvs : isfree envT),
|
adamc@184
|
836 Closed.typeDenote (envType fvs)
|
adamc@184
|
837 -> envOf Closed.typeDenote fvs :=
|
adamc@183
|
838 match envT return (forall (fvs : isfree envT),
|
adamc@184
|
839 Closed.typeDenote (envType fvs)
|
adamc@184
|
840 -> envOf Closed.typeDenote fvs) with
|
adamc@183
|
841 | nil => fun _ _ => tt
|
adamc@183
|
842 | first :: rest => fun fvs =>
|
adamc@184
|
843 match fvs return (Closed.typeDenote (envType (envT := first :: rest) fvs)
|
adamc@184
|
844 -> envOf (envT := first :: rest) Closed.typeDenote fvs) with
|
adamc@183
|
845 | (false, fvs') => fun env => makeEnv rest fvs' env
|
adamc@183
|
846 | (true, fvs') => fun env => (fst env, makeEnv rest fvs' (snd env))
|
adamc@183
|
847 end
|
adamc@183
|
848 end.
|
adamc@183
|
849
|
adamc@184
|
850 Implicit Arguments makeEnv [envT fvs].
|
adamc@184
|
851
|
adamc@184
|
852 Theorem unpackExp_correct : forall t (envT : list Source.type) (fvs : isfree envT)
|
adamc@184
|
853 (e1 : Closed.exp Closed.typeDenote (envType fvs))
|
adamc@184
|
854 (e2 : envOf Closed.typeDenote fvs -> Closed.exp Closed.typeDenote t),
|
adamc@184
|
855 Closed.expDenote (unpackExp e1 e2)
|
adamc@184
|
856 = Closed.expDenote (e2 (makeEnv (Closed.expDenote e1))).
|
adamc@184
|
857 induction envT; my_crush.
|
adamc@183
|
858 Qed.
|
adamc@183
|
859
|
adamc@183
|
860 Lemma lookup_type_more : forall v2 envT (fvs : isfree envT) t b v,
|
adamc@183
|
861 (v2 = length envT -> False)
|
adamc@183
|
862 -> lookup_type v2 (envT := t :: envT) (b, fvs) = v
|
adamc@183
|
863 -> lookup_type v2 fvs = v.
|
adamc@184
|
864 my_crush.
|
adamc@183
|
865 Qed.
|
adamc@183
|
866
|
adamc@183
|
867 Lemma lookup_type_less : forall v2 t envT (fvs : isfree (t :: envT)) v,
|
adamc@183
|
868 (v2 = length envT -> False)
|
adamc@183
|
869 -> lookup_type v2 (snd fvs) = v
|
adamc@183
|
870 -> lookup_type v2 (envT := t :: envT) fvs = v.
|
adamc@184
|
871 my_crush.
|
adamc@183
|
872 Qed.
|
adamc@183
|
873
|
adamc@184
|
874 Hint Resolve lookup_bound_contra.
|
adamc@184
|
875
|
adamc@183
|
876 Lemma lookup_bound_contra_eq : forall t envT (fvs : isfree envT) v,
|
adamc@183
|
877 lookup_type v fvs = Some t
|
adamc@183
|
878 -> v = length envT
|
adamc@183
|
879 -> False.
|
adamc@184
|
880 my_crush; elimtype False; eauto.
|
adamc@184
|
881 Qed.
|
adamc@183
|
882
|
adamc@184
|
883 Lemma lookup_type_inner : forall t t' envT v t'' (fvs : isfree envT) e,
|
adamc@184
|
884 wfExp (envT := t' :: envT) (true, fvs) e
|
adamc@184
|
885 -> lookup_type v (snd (fvsExp (t := t) e (t' :: envT))) = Some t''
|
adamc@184
|
886 -> lookup_type v fvs = Some t''.
|
adamc@184
|
887 Hint Resolve lookup_bound_contra_eq fvsExp_minimal
|
adamc@183
|
888 lookup_type_more lookup_type_less.
|
adamc@184
|
889 Hint Extern 2 (Some _ = Some _) => elimtype False.
|
adamc@183
|
890
|
adamc@183
|
891 eauto 6.
|
adamc@183
|
892 Qed.
|
adamc@183
|
893
|
adamc@183
|
894 Lemma cast_irrel : forall T1 T2 x (H1 H2 : T1 = T2),
|
adamc@184
|
895 match H1 in _ = T return T with
|
adamc@184
|
896 | refl_equal => x
|
adamc@184
|
897 end
|
adamc@184
|
898 = match H2 in _ = T return T with
|
adamc@184
|
899 | refl_equal => x
|
adamc@184
|
900 end.
|
adamc@184
|
901 intros; generalize H1; crush;
|
adamc@184
|
902 repeat match goal with
|
adamc@184
|
903 | [ |- context[match ?pf with refl_equal => _ end] ] =>
|
adamc@184
|
904 rewrite (UIP_refl _ _ pf)
|
adamc@184
|
905 end;
|
adamc@184
|
906 reflexivity.
|
adamc@183
|
907 Qed.
|
adamc@183
|
908
|
adamc@183
|
909 Hint Immediate cast_irrel.
|
adamc@183
|
910
|
adamc@184
|
911 Hint Extern 3 (_ == _) =>
|
adamc@183
|
912 match goal with
|
adamc@183
|
913 | [ |- context[False_rect _ ?H] ] =>
|
adamc@183
|
914 apply False_rect; exact H
|
adamc@183
|
915 end.
|
adamc@183
|
916
|
adamc@184
|
917 Theorem packExp_correct : forall v envT (fvs1 fvs2 : isfree envT)
|
adamc@183
|
918 Hincl env,
|
adamc@184
|
919 lookup_type v fvs1 <> None
|
adamc@184
|
920 -> lookup Closed.typeDenote v env
|
adamc@184
|
921 == lookup Closed.typeDenote v
|
adamc@184
|
922 (makeEnv (Closed.expDenote
|
adamc@184
|
923 (packExp fvs1 fvs2 Hincl env))).
|
adamc@184
|
924 induction envT; my_crush.
|
adamc@183
|
925 Qed.
|
adamc@183
|
926 End packing_correct.
|
adamc@183
|
927
|
adamc@184
|
928 (*Lemma typeDenote_same : forall t,
|
adamc@184
|
929 Closed.typeDenote (ccType t) = Source.typeDenote t.
|
adamc@184
|
930 induction t; crush.
|
adamc@184
|
931 Qed.*)
|
adamc@184
|
932
|
adamc@184
|
933 Lemma typeDenote_same : forall t,
|
adamc@184
|
934 Source.typeDenote t = Closed.typeDenote (ccType t).
|
adamc@184
|
935 induction t; crush.
|
adamc@184
|
936 Qed.
|
adamc@184
|
937
|
adamc@184
|
938 Hint Resolve typeDenote_same.
|
adamc@184
|
939
|
adamc@183
|
940 Lemma look : forall envT n (fvs : isfree envT) t,
|
adamc@183
|
941 lookup_type n fvs = Some t
|
adamc@184
|
942 -> Closed.typeDenote <| lookup_type n fvs = Source.typeDenote t.
|
adamc@184
|
943 crush.
|
adamc@183
|
944 Qed.
|
adamc@183
|
945
|
adamc@183
|
946 Implicit Arguments look [envT n fvs t].
|
adamc@183
|
947
|
adamc@184
|
948 Lemma cast_jmeq : forall (T1 T2 : Set) (pf : T1 = T2) (T2' : Set) (v1 : T1) (v2 : T2'),
|
adamc@184
|
949 v1 == v2
|
adamc@184
|
950 -> T2' = T2
|
adamc@184
|
951 -> match pf in _ = T return T with
|
adamc@184
|
952 | refl_equal => v1
|
adamc@184
|
953 end == v2.
|
adamc@184
|
954 intros; generalize pf; subst.
|
adamc@184
|
955 intro.
|
adamc@184
|
956 rewrite (UIP_refl _ _ pf).
|
adamc@184
|
957 auto.
|
adamc@184
|
958 Qed.
|
adamc@183
|
959
|
adamc@184
|
960 Hint Resolve cast_jmeq.
|
adamc@184
|
961
|
adamc@184
|
962 Theorem ccTerm_correct : forall t G
|
adamc@184
|
963 (e1 : Source.exp Source.typeDenote t)
|
adamc@184
|
964 (e2 : Source.exp natvar t),
|
adamc@184
|
965 exp_equiv G e1 e2
|
adamc@184
|
966 -> forall (envT : list Source.type) (fvs : isfree envT)
|
adamc@184
|
967 (env : envOf Closed.typeDenote fvs) (wf : wfExp fvs e2),
|
adamc@184
|
968 (forall t (v1 : Source.typeDenote t) (v2 : natvar t),
|
adamc@184
|
969 In (existT _ _ (v1, v2)) G
|
adamc@183
|
970 -> v2 < length envT)
|
adamc@184
|
971 -> (forall t (v1 : Source.typeDenote t) (v2 : natvar t),
|
adamc@184
|
972 In (existT _ _ (v1, v2)) G
|
adamc@183
|
973 -> lookup_type v2 fvs = Some t
|
adamc@184
|
974 -> lookup Closed.typeDenote v2 env == v1)
|
adamc@184
|
975 -> Closed.expDenote (funcsDenote (ccExp e2 fvs wf) env)
|
adamc@184
|
976 == Source.expDenote e1.
|
adamc@183
|
977
|
adamc@184
|
978 Hint Rewrite spliceFuncs_correct unpackExp_correct : cpdt.
|
adamc@183
|
979 Hint Resolve packExp_correct lookup_type_inner.
|
adamc@183
|
980
|
adamc@184
|
981 induction 1.
|
adamc@183
|
982
|
adamc@184
|
983 crush.
|
adamc@184
|
984 crush.
|
adamc@184
|
985 crush.
|
adamc@184
|
986 crush.
|
adamc@183
|
987
|
adamc@184
|
988 Lemma app_jmeq : forall dom1 dom2 ran1 ran2
|
adamc@184
|
989 (f1 : dom1 -> ran1) (f2 : dom2 -> ran2)
|
adamc@184
|
990 (x1 : dom1) (x2 : dom2),
|
adamc@184
|
991 ran1 = ran2
|
adamc@184
|
992 -> f1 == f2
|
adamc@184
|
993 -> x1 == x2
|
adamc@184
|
994 -> f1 x1 == f2 x2.
|
adamc@184
|
995 crush.
|
adamc@184
|
996 assert (dom1 = dom2).
|
adamc@184
|
997 inversion H1; trivial.
|
adamc@184
|
998 crush.
|
adamc@184
|
999 Qed.
|
adamc@184
|
1000
|
adamc@184
|
1001 Lemma app_jmeq : forall dom ran
|
adamc@184
|
1002 (f1 : Closed.typeDenote (ccType dom) -> Closed.typeDenote (ccType ran))
|
adamc@184
|
1003 (f2 : Source.typeDenote dom -> Source.typeDenote ran)
|
adamc@184
|
1004 (x1 : dom1) (x2 : dom2),
|
adamc@184
|
1005 ran1 = ran2
|
adamc@184
|
1006 -> f1 == f2
|
adamc@184
|
1007 -> x1 == x2
|
adamc@184
|
1008 -> f1 x1 == f2 x2.
|
adamc@184
|
1009 crush.
|
adamc@184
|
1010 assert (dom1 = dom2).
|
adamc@184
|
1011 inversion H1; trivial.
|
adamc@184
|
1012 crush.
|
adamc@184
|
1013 Qed.
|
adamc@183
|
1014
|
adamc@184
|
1015 simpl.
|
adamc@184
|
1016 refine (app_jmeq _ _ _).
|
adamc@184
|
1017 apply app_jmeq.
|
adamc@184
|
1018 dependent rewrite <- IHexp_equiv1.
|
adamc@183
|
1019 Qed.
|
adamc@183
|
1020
|
adamc@183
|
1021
|
adamc@183
|
1022 (** * Parametric version *)
|
adamc@183
|
1023
|
adamc@183
|
1024 Section wf.
|
adamc@183
|
1025 Variable result : ptype.
|
adamc@183
|
1026
|
adamc@183
|
1027 Lemma Pterm_wf' : forall G (e1 e2 : pterm natvar result),
|
adamc@183
|
1028 pterm_equiv G e1 e2
|
adamc@183
|
1029 -> forall envT (fvs : isfree envT),
|
adamc@183
|
1030 (forall t (v1 v2 : natvar t), In (vars (v1, v2)) G
|
adamc@183
|
1031 -> lookup_type v1 fvs = Some t)
|
adamc@183
|
1032 -> wfTerm fvs e1.
|
adamc@183
|
1033 Hint Extern 3 (Some _ = Some _) => contradictory; eapply lookup_bound_contra; eauto.
|
adamc@183
|
1034
|
adamc@183
|
1035 apply (pterm_equiv_mut
|
adamc@183
|
1036 (fun G (e1 e2 : pterm natvar result) =>
|
adamc@183
|
1037 forall envT (fvs : isfree envT),
|
adamc@183
|
1038 (forall t (v1 v2 : natvar t), In (vars (v1, v2)) G
|
adamc@183
|
1039 -> lookup_type v1 fvs = Some t)
|
adamc@183
|
1040 -> wfTerm (envT:=envT) fvs e1)
|
adamc@183
|
1041 (fun G t (p1 p2 : pprimop natvar result t) =>
|
adamc@183
|
1042 forall envT (fvs : isfree envT),
|
adamc@183
|
1043 (forall t (v1 v2 : natvar t), In (vars (v1, v2)) G
|
adamc@183
|
1044 -> lookup_type v1 fvs = Some t)
|
adamc@183
|
1045 -> wfPrimop (envT:=envT) fvs p1));
|
adamc@183
|
1046 simpler;
|
adamc@183
|
1047 match goal with
|
adamc@183
|
1048 | [ envT : list ptype, H : _ |- _ ] =>
|
adamc@183
|
1049 apply (H (length envT) (length envT)); simpler
|
adamc@183
|
1050 end.
|
adamc@183
|
1051 Qed.
|
adamc@183
|
1052
|
adamc@183
|
1053 Theorem Pterm_wf : forall (E : Pterm result),
|
adamc@183
|
1054 wfTerm (envT := nil) tt (E _).
|
adamc@183
|
1055 intros; eapply Pterm_wf';
|
adamc@183
|
1056 [apply Pterm_equiv
|
adamc@183
|
1057 | simpler].
|
adamc@183
|
1058 Qed.
|
adamc@183
|
1059 End wf.
|
adamc@183
|
1060
|
adamc@183
|
1061 Definition CcTerm result (E : Pterm result) : Cprog result :=
|
adamc@183
|
1062 CcTerm' E (Pterm_wf E).
|
adamc@183
|
1063
|
adamc@183
|
1064 Lemma map_funcs_correct : forall result T1 T2 (f : T1 -> T2) (fs : cfuncs ctypeDenote result T1) k,
|
adamc@183
|
1065 cfuncsDenote (map_funcs f fs) k = f (cfuncsDenote fs k).
|
adamc@183
|
1066 induction fs; equation.
|
adamc@183
|
1067 Qed.
|
adamc@183
|
1068
|
adamc@183
|
1069 Theorem CcTerm_correct : forall result (E : Pterm result) k,
|
adamc@183
|
1070 PtermDenote E k
|
adamc@183
|
1071 = CprogDenote (CcTerm E) k.
|
adamc@183
|
1072 Hint Rewrite map_funcs_correct : ltamer.
|
adamc@183
|
1073
|
adamc@183
|
1074 unfold PtermDenote, CprogDenote, CcTerm, CcTerm', cprogDenote;
|
adamc@183
|
1075 simpler;
|
adamc@183
|
1076 apply (ccTerm_correct (result := result)
|
adamc@183
|
1077 (G := nil)
|
adamc@183
|
1078 (e1 := E _)
|
adamc@183
|
1079 (e2 := E _)
|
adamc@183
|
1080 (Pterm_equiv _ _ _)
|
adamc@183
|
1081 nil
|
adamc@183
|
1082 tt
|
adamc@183
|
1083 tt);
|
adamc@183
|
1084 simpler.
|
adamc@183
|
1085 Qed.
|