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