aboutsummaryrefslogtreecommitdiffstats
path: root/theories/lambda
diff options
context:
space:
mode:
Diffstat (limited to 'theories/lambda')
-rw-r--r--theories/lambda/interp.v44
-rw-r--r--theories/lambda/interp_proofs.v614
-rw-r--r--theories/lambda/operational.v38
-rw-r--r--theories/lambda/operational_props.v29
4 files changed, 725 insertions, 0 deletions
diff --git a/theories/lambda/interp.v b/theories/lambda/interp.v
new file mode 100644
index 0000000..5bc60d1
--- /dev/null
+++ b/theories/lambda/interp.v
@@ -0,0 +1,44 @@
1From mininix Require Export res lambda.operational_props.
2From stdpp Require Import options.
3
4Module Import lambda.
5Export lambda.
6
7Inductive thunk :=
8 Thunk { thunk_env : gmap string thunk; thunk_expr : expr }.
9Add Printing Constructor thunk.
10Notation env := (gmap string thunk).
11
12Inductive val :=
13 | VString (s : string)
14 | VClo (x : string) (E : env) (e : expr).
15
16Global Instance maybe_VClo : Maybe3 VClo := λ v,
17 if v is VClo x E e then Some (x, E, e) else None.
18
19Definition interp1 (interp : env → expr → res val) (E : env) (e : expr) : res val :=
20 match e with
21 | EString s =>
22 mret (VString s)
23 | EId x =>
24 t ← Res (E !! x);
25 interp (thunk_env t) (thunk_expr t)
26 | EAbs x e =>
27 mret (VClo x E e)
28 | EApp e1 e2 =>
29 v1 ← interp E e1;
30 '(x, E', e') ← Res (maybe3 VClo v1);
31 interp (<[x:=Thunk E e2]> E') e'
32 end.
33
34Fixpoint interp (n : nat) (E : env) (e : expr) : res val :=
35 match n with
36 | O => NoFuel
37 | S n => interp1 (interp n) E e
38 end.
39
40Global Opaque interp.
41
42End lambda.
43
44Add Printing Constructor lambda.thunk.
diff --git a/theories/lambda/interp_proofs.v b/theories/lambda/interp_proofs.v
new file mode 100644
index 0000000..efd0982
--- /dev/null
+++ b/theories/lambda/interp_proofs.v
@@ -0,0 +1,614 @@
1From mininix Require Export lambda.interp.
2From stdpp Require Import options.
3
4Module Import lambda.
5Export lambda.
6
7Lemma interp_S n : interp (S n) = interp1 (interp n).
8Proof. done. Qed.
9
10Fixpoint thunk_size (t : thunk) : nat :=
11 S (map_sum_with thunk_size (thunk_env t)).
12Definition env_size (E : env) : nat :=
13 map_sum_with thunk_size E.
14
15Lemma env_ind (P : env → Prop) :
16 (∀ E, map_Forall (λ i, P ∘ thunk_env) E → P E) →
17 ∀ E : env, P E.
18Proof.
19 intros Pbs E.
20 induction (Nat.lt_wf_0_projected env_size E) as [E _ IH].
21 apply Pbs, map_Forall_lookup=> y [E' e'] Hy.
22 apply (map_sum_with_lookup_le thunk_size) in Hy.
23 apply IH. by rewrite -Nat.le_succ_l.
24Qed.
25
26(** Correspondence to operational semantics *)
27Definition subst_env' (thunk_to_expr : thunk → expr) (E : env) : expr → expr :=
28 subst (thunk_to_expr <$> E).
29Fixpoint thunk_to_expr (t : thunk) : expr :=
30 subst_env' thunk_to_expr (thunk_env t) (thunk_expr t).
31Notation subst_env := (subst_env' thunk_to_expr).
32
33Lemma subst_env_eq e E :
34 subst_env E e =
35 match e with
36 | EString s => EString s
37 | EId x => if E !! x is Some t then thunk_to_expr t else EId x
38 | EAbs x e => EAbs x (subst_env (delete x E) e)
39 | EApp e1 e2 => EApp (subst_env E e1) (subst_env E e2)
40 end.
41Proof.
42 rewrite /subst_env. destruct e; simpl; try done.
43 - rewrite lookup_fmap. by destruct (E !! x) as [[]|].
44 - by rewrite fmap_delete.
45Qed.
46Lemma subst_env_id x E :
47 subst_env E (EId x) = if E !! x is Some t then thunk_to_expr t else EId x.
48Proof. by rewrite subst_env_eq. Qed.
49
50Lemma subst_env_alt E e : subst_env E e = subst (thunk_to_expr <$> E) e.
51Proof. done. Qed.
52
53(* Use the unfolding lemmas, don't rely on conversion *)
54Opaque subst_env'.
55
56Definition val_to_expr (v : val) : expr :=
57 match v with
58 | VString s => EString s
59 | VClo x E e => EAbs x (subst_env (delete x E) e)
60 end.
61
62Lemma final_val_to_expr v : final (val_to_expr v).
63Proof. by destruct v. Qed.
64Lemma step_not_val_to_expr v e : val_to_expr v --> e → False.
65Proof. intros []%step_not_final. apply final_val_to_expr. Qed.
66
67Lemma subst_empty e : subst ∅ e = e.
68Proof. induction e; f_equal/=; auto. Qed.
69
70Lemma subst_env_empty e : subst_env ∅ e = e.
71Proof. rewrite subst_env_alt. apply subst_empty. Qed.
72
73Lemma interp_le {n1 n2 E e mv} :
74 interp n1 E e = Res mv → n1 ≤ n2 → interp n2 E e = Res mv.
75Proof.
76 revert n2 E e mv.
77 induction n1 as [|n1 IH]; intros [|n2] E e mv He ?; [by (done || lia)..|].
78 rewrite interp_S in He; rewrite interp_S; destruct e;
79 repeat match goal with
80 | _ => case_match
81 | H : context [(_ <$> ?mx)] |- _ => destruct mx eqn:?; simplify_res
82 | H : ?r ≫= _ = _ |- _ => destruct r as [[]|] eqn:?; simplify_res
83 | H : _ <$> ?r = _ |- _ => destruct r as [[]|] eqn:?; simplify_res
84 | |- interp ?n ?E ?e ≫= _ = _ => erewrite (IH n E e) by (done || lia)
85 | _ => progress simplify_res
86 | _ => progress simplify_option_eq
87 end; eauto with lia.
88Qed.
89
90Lemma interp_agree {n1 n2 E e mv1 mv2} :
91 interp n1 E e = Res mv1 → interp n2 E e = Res mv2 → mv1 = mv2.
92Proof.
93 intros He1 He2. apply (inj Res). destruct (total (≤) n1 n2).
94 - rewrite -He2. symmetry. eauto using interp_le.
95 - rewrite -He1. eauto using interp_le.
96Qed.
97
98Definition is_not_id (e : expr) : Prop :=
99 match e with EId _ => False | _ => True end.
100
101Lemma id_or_not e : (∃ x, e = EId x) ∨ is_not_id e.
102Proof. destruct e; naive_solver. Qed.
103
104Lemma interp_not_id n E e v :
105 interp n E e = mret v → is_not_id (subst_env E e).
106Proof.
107 revert E e v. induction n as [|n IH]; intros E e v; [done|].
108 rewrite interp_S. destruct e; simpl; try done.
109 rewrite subst_env_id. destruct (_ !! _) as [[[]]|]; naive_solver.
110Qed.
111
112Fixpoint closed (X : stringset) (e : expr) : Prop :=
113 match e with
114 | EString _ => True
115 | EId x => x ∈ X
116 | EAbs x e => closed ({[ x ]} ∪ X) e
117 | EApp e1 e2 => closed X e1 ∧ closed X e2
118 end.
119
120Inductive closed_thunk (t : thunk) : Prop := {
121 closed_thunk_env : map_Forall (λ _, closed_thunk) (thunk_env t);
122 closed_thunk_expr : closed (dom (thunk_env t)) (thunk_expr t);
123}.
124Notation closed_env := (map_Forall (M:=env) (λ _, closed_thunk)).
125
126Definition closed_val (v : val) : Prop :=
127 match v with
128 | VString _ => True
129 | VClo x E e => closed_env E ∧ closed ({[x]} ∪ dom E) e
130 end.
131
132Lemma closed_thunk_eq E e :
133 closed_thunk (Thunk E e) ↔ closed_env E ∧ closed (dom E) e.
134Proof. split; inv 1; constructor; done. Qed.
135
136Lemma closed_env_delete x E : closed_env E → closed_env (delete x E).
137Proof. apply map_Forall_delete. Qed.
138
139Lemma closed_env_insert x t E :
140 closed_thunk t → closed_env E → closed_env (<[x:=t]> E).
141Proof. apply: map_Forall_insert_2. Qed.
142
143Lemma closed_env_lookup E x t :
144 closed_env E → E !! x = Some t → closed_thunk t.
145Proof. apply map_Forall_lookup_1. Qed.
146
147Lemma closed_subst E ds e :
148 dom ds ## E → closed E e → subst ds e = e.
149Proof.
150 revert E ds.
151 induction e; intros E ds Hdisj Heclosed; simplify_eq/=; first done.
152 - assert (Hxds : x ∉ dom ds) by set_solver.
153 by rewrite (not_elem_of_dom_1 _ _ Hxds).
154 - f_equal. by apply IHe with (E := {[x]} ∪ E); first set_solver.
155 - f_equal; naive_solver.
156Qed.
157
158Lemma closed_weaken X Y e : closed X e → X ⊆ Y → closed Y e.
159Proof. revert X Y; induction e; naive_solver eauto with set_solver. Qed.
160
161Lemma subst_closed ds X e :
162 map_Forall (λ _, closed ∅) ds →
163 closed (dom ds ∪ X) e →
164 closed X (subst ds e).
165Proof.
166 revert X ds. induction e; intros X ds; repeat (case_decide || simplify_eq/=).
167 - done.
168 - intros. case_match.
169 + apply H in H1. by eapply closed_weaken.
170 + apply not_elem_of_dom in H1. set_solver.
171 - intros. apply IHe.
172 + by apply map_Forall_delete.
173 + by rewrite dom_delete_L assoc_L difference_union_L
174 [dom _ ∪ _]comm_L -assoc_L.
175 - naive_solver.
176Qed.
177
178Lemma subst_env_delete_closed E X e x :
179 closed_env E →
180 closed ({[x]} ∪ X) (subst_env E e) →
181 closed ({[x]} ∪ X) (subst_env (delete x E) e).
182Proof.
183 revert E X x.
184 induction e as [s | z | z e IHe | e1 IHe1 e2 IHe2]; intros E X x.
185 - rewrite !subst_env_eq //.
186 - rewrite !subst_env_eq /=. case_match.
187 + destruct (decide (x = z)) as [->|?].
188 * rewrite lookup_delete. set_solver.
189 * rewrite lookup_delete_ne // H //.
190 + destruct (decide (x = z)) as [->|?].
191 * rewrite delete_notin // H //.
192 * rewrite lookup_delete_ne // H //.
193 - intros HE.
194 rewrite [subst_env (delete _ _) _]subst_env_eq subst_env_eq /=
195 delete_commute comm_L -assoc_L.
196 by apply IHe, map_Forall_delete.
197 - rewrite [subst_env (delete _ _) _]subst_env_eq subst_env_eq /=.
198 naive_solver.
199Qed.
200
201Lemma subst_env_closed E X e :
202 closed_env E → closed (dom E ∪ X) e → closed X (subst_env E e).
203Proof.
204 revert e X. induction E using env_ind.
205 induction e; intros X Hcenv Hclosed; simplify_eq/=.
206 - done.
207 - rewrite subst_env_eq. case_match.
208 + destruct t as [Et et]; simpl.
209 apply closed_env_lookup in H0 as Htclosed; last done.
210 apply closed_thunk_eq in Htclosed as [HEtclosed Hetclosed].
211 apply (H _ _ H0); simpl.
212 * exact HEtclosed.
213 * eapply closed_weaken; set_solver.
214 + simpl in *. apply not_elem_of_dom in H0. set_solver.
215 - rewrite subst_env_eq. simpl in *.
216 rewrite comm_L -assoc_L in Hclosed.
217 apply IHe in Hclosed; last exact Hcenv.
218 apply subst_env_delete_closed; first done.
219 by rewrite comm_L.
220 - rewrite subst_env_eq. naive_solver.
221Qed.
222
223Lemma thunk_to_expr_closed t : closed_thunk t → closed ∅ (thunk_to_expr t).
224Proof.
225 destruct t as [E e]. intros [HEclosed Heclosed]%closed_thunk_eq.
226 by apply subst_env_closed; last rewrite union_empty_r_L.
227Qed.
228
229Lemma subst_env_insert E x e t :
230 closed_env E →
231 subst_env (<[x:=t]> E) e
232 = subst {[x:=thunk_to_expr t]} (subst_env (delete x E) e).
233Proof.
234 revert E. induction e; intros E HEclosed; simpl.
235 - done.
236 - destruct (decide (x = x0)) as [->|?].
237 + rewrite subst_env_eq lookup_insert subst_env_id
238 lookup_delete /= lookup_singleton. done.
239 + rewrite subst_env_eq lookup_insert_ne // subst_env_id.
240 destruct (E !! x0) eqn:Elookup.
241 * apply closed_env_lookup in Elookup as Hc0closed; last done.
242 apply thunk_to_expr_closed in Hc0closed.
243 rewrite lookup_delete_ne // Elookup.
244 by erewrite closed_subst with (E := ∅).
245 * by rewrite lookup_delete_ne // Elookup /= lookup_singleton_ne.
246 - rewrite (subst_env_eq (EAbs x0 e)) (subst_env_eq (EAbs _ _)) /=. f_equal.
247 destruct (decide (x0 = x)) as [->|?].
248 + by rewrite delete_insert_delete delete_idemp
249 delete_singleton subst_empty.
250 + rewrite delete_insert_ne // delete_singleton_ne // delete_commute.
251 apply IHe. by apply closed_env_delete.
252 - rewrite (subst_env_eq (EApp _ _)) [subst_env (delete x E) _]subst_env_eq /=.
253 f_equal; auto.
254Qed.
255
256Lemma subst_env_insert_eq e1 e2 E1 E2 x E1' E2' e1' e2' :
257 closed_env E1 → closed_env E2 →
258 subst_env (delete x E1) e1 = subst_env (delete x E2) e2 →
259 subst_env E1' e1' = subst_env E2' e2' →
260 subst_env (<[x:=Thunk E1' e1']> E1) e1
261 = subst_env (<[x:=Thunk E2' e2']> E2) e2.
262Proof.
263 intros HE1closed HE2closed He' He.
264 rewrite !subst_env_insert //=. by rewrite He' He.
265Qed.
266
267Lemma interp_closed n E e mv :
268 closed_env E → closed (dom E) e → interp n E e = Res mv →
269 if mv is Some v then closed_val v else True.
270Proof.
271 revert E e mv.
272 induction n; first done; intros E e mv HEclosed Heclosed Hinterp.
273 destruct e.
274 - rewrite interp_S /= in Hinterp. by destruct mv; simplify_res.
275 - rewrite interp_S /= in Hinterp. simplify_option_eq.
276 destruct (E !! x) eqn:Hlookup; simplify_res; try done.
277 apply closed_env_lookup in Hlookup; last assumption.
278 destruct t as [E' e']. apply closed_thunk_eq in Hlookup as [Henv Hexpr].
279 by apply IHn with (E := E') (e := e').
280 - rewrite interp_S /= in Hinterp. simplify_option_eq.
281 destruct mv as [v|]; simplify_res. split_and!.
282 + set_solver.
283 + done.
284 - rewrite interp_S /= in Hinterp. simplify_option_eq.
285 destruct Heclosed as [He1closed He2closed].
286 destruct (interp n E e1) as [[[]|]|] eqn:Einterp; simplify_res; try done.
287 apply IHn in Einterp; try done.
288 simpl in Einterp. destruct Einterp as [Hinterp1 Hinterp2].
289 apply IHn in Hinterp; first done.
290 + rewrite <-insert_delete_insert.
291 apply map_Forall_insert; first apply lookup_delete. split.
292 * by split.
293 * by apply closed_env_delete.
294 + by rewrite dom_insert_L.
295Qed.
296
297Lemma interp_proper n E1 E2 e1 e2 mv :
298 closed_env E1 → closed_env E2 →
299 closed (dom E1) e1 → closed (dom E2) e2 →
300 subst_env E1 e1 = subst_env E2 e2 →
301 interp n E1 e1 = Res mv →
302 ∃ mw m, interp m E2 e2 = Res mw ∧
303 val_to_expr <$> mv = val_to_expr <$> mw.
304Proof.
305 revert n E2 E1 e1 e2 mv. induction n as [|n IHn]; [done|].
306 intros E2. induction E2 as [E2 IH] using env_ind.
307 intros E1 e1 e2 mv HE1closed HE2closed He1closed He2closed Hsubst Hinterp.
308 destruct (id_or_not e1) as [[x ->]|?].
309 { rewrite interp_S /= in Hinterp.
310 destruct (E1 !! x) as [[E' e']|] eqn:Hx; simplify_eq/=;
311 last by apply not_elem_of_dom in Hx.
312 rewrite subst_env_id Hx in Hsubst.
313 apply closed_env_lookup in Hx; last done.
314 rewrite closed_thunk_eq in Hx.
315 destruct Hx as [HE'close He'closed].
316 eauto. }
317 destruct (id_or_not e2) as [[x ->]|?].
318 { rewrite subst_env_id in Hsubst.
319 destruct (E2 !! x) as [[E' e']|] eqn:Hx; simplify_eq/=.
320 - apply closed_env_lookup in Hx as Hclosed; last done.
321 rewrite closed_thunk_eq in Hclosed.
322 destruct Hclosed as [HE'closed He'closed].
323 rewrite map_Forall_lookup in IH.
324 odestruct (IH _ _ Hx) as (w & m & Hinterp' & Hw);
325 first apply HE1closed; try done.
326 exists w, (S m). by rewrite interp_S /= Hx /=.
327 - destruct mv as [v|].
328 + apply interp_not_id in Hinterp. by rewrite Hsubst in Hinterp.
329 + exists None, 1. by rewrite interp_S /= Hx. }
330 rewrite (subst_env_eq e1) (subst_env_eq e2) in Hsubst.
331 rewrite interp_S in Hinterp. destruct e1, e2; simplify_res; try done.
332 - eexists (Some (VString _)), 1. by rewrite interp_S.
333 - eexists (Some (VClo _ _ _)), 1. split; first by rewrite interp_S.
334 by do 2 f_equal/=.
335 - destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res.
336 destruct He1closed as [He1_1closed He1_2closed],
337 He2closed as [He2_1closed He2_2closed].
338 apply interp_closed in Hinterp' as Hclosed; [|done..].
339 eapply IHn with (e2 := e2_1) in Hinterp' as (mw' & m1 & Hinterp1 & ?);
340 try done.
341 destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first.
342 { exists None, (S m1). by rewrite interp_S /= Hinterp1. }
343 destruct (maybe3 VClo _) eqn:Hclo; simplify_res; last first.
344 { exists None, (S m1). rewrite interp_S /= Hinterp1 /=.
345 by assert (maybe3 VClo w' = None) as -> by (by destruct v', w'). }
346 destruct v', w'; simplify_eq/=.
347 eapply IHn with (E2 := <[x0:=Thunk E2 e2_2]> E0) in Hinterp
348 as (w & m2 & Hinterp2 & ?).
349 + exists w, (S (m1 `max` m2)). rewrite interp_S /=.
350 rewrite (interp_le Hinterp1) /=; last lia.
351 rewrite (interp_le Hinterp2) /=; last lia. done.
352 + rewrite -insert_delete_insert.
353 apply map_Forall_insert; first apply lookup_delete.
354 split; first done. apply closed_env_delete. naive_solver.
355 + apply interp_closed in Hinterp1; [|done..].
356 rewrite /closed_val in Hinterp1. destruct Hinterp1 as [??].
357 by apply map_Forall_insert_2.
358 + rewrite dom_insert_L. naive_solver.
359 + rewrite dom_insert_L.
360 apply interp_closed in Hinterp1; [|done..].
361 rewrite /closed_val in Hinterp1. by destruct Hinterp1 as [_ ?].
362 + apply interp_closed in Hinterp1; [|done..].
363 rewrite /closed_val in Hinterp1. destruct Hinterp1 as [? _].
364 apply subst_env_insert_eq; try naive_solver.
365Qed.
366
367Lemma subst_as_subst_env x e1 e2 :
368 subst {[x:=e2]} e1 = subst_env (<[x:=Thunk ∅ e2]> ∅) e1.
369Proof. rewrite subst_env_insert //= !subst_env_empty //. Qed.
370
371Lemma interp_subst n x e1 e2 mv :
372 closed {[x]} e1 → closed ∅ e2 →
373 interp n ∅ (subst {[x:=e2]} e1) = Res mv →
374 ∃ mw m, interp m (<[x:=Thunk ∅ e2]> ∅) e1 = Res mw ∧
375 val_to_expr <$> mv = val_to_expr <$> mw.
376Proof.
377 intros He1 He2.
378 apply interp_proper.
379 - done.
380 - by apply closed_env_insert.
381 - apply subst_closed.
382 + by apply map_Forall_singleton.
383 + by rewrite dom_singleton_L dom_empty_L union_empty_r_L.
384 - by rewrite insert_empty dom_singleton_L.
385 - by rewrite subst_env_empty subst_as_subst_env.
386Qed.
387
388Lemma closed_step e1 e2 : closed ∅ e1 → e1 --> e2 → closed ∅ e2.
389Proof.
390 intros Hclosed Hstep. revert Hclosed.
391 induction Hstep; intros He1closed.
392 - simplify_eq/=. destruct He1closed.
393 apply subst_closed.
394 + by eapply map_Forall_singleton.
395 + by rewrite dom_singleton_L.
396 - simplify_eq/=. destruct He1closed. auto.
397Qed.
398
399Lemma closed_steps e1 e2 : closed ∅ e1 → e1 -->* e2 → closed ∅ e2.
400Proof. induction 2; eauto using closed_step. Qed.
401
402Lemma interp_step e1 e2 n v :
403 closed ∅ e1 →
404 e1 --> e2 →
405 interp n ∅ e2 = Res v →
406 ∃ w m, interp m ∅ e1 = Res w ∧ val_to_expr <$> v = val_to_expr <$> w.
407Proof.
408 intros He1closed Hstep. revert v n He1closed.
409 induction Hstep as [|???? IH]; intros v n He1closed Hinterp.
410 { rewrite /= union_empty_r_L in He1closed.
411 destruct He1closed as [He1closed He2closed].
412 apply interp_subst in Hinterp as (w & [|m] & Hinterp & Hv);
413 simplify_eq/=; [|done..].
414 exists w, (S (S m)). by rewrite !interp_S /= -interp_S. }
415 simpl in He1closed. destruct He1closed as [He1closed He2closed].
416 destruct n as [|n]; [done|rewrite interp_S /= in Hinterp].
417 destruct (interp n _ _) eqn:Hinterp'; simplify_res.
418 destruct x; simplify_res; last first.
419 { apply IH in Hinterp' as (mw' & m1 & Hinterp1 & ?); simplify_res; last done.
420 destruct mw'; try done. exists None, (S m1).
421 by rewrite interp_S /= Hinterp1. }
422 apply closed_step in Hstep as He1'closed; last done.
423 apply interp_closed in Hinterp' as Hcloclosed;
424 [|done|by rewrite dom_empty_L].
425 apply IH in Hinterp' as ([] & m1 & Hinterp1 & ?); simplify_eq/=; last done.
426 destruct (maybe3 VClo _) eqn:Hclo; simplify_res; last first.
427 { exists None, (S m1). rewrite interp_S /= Hinterp1 /=.
428 by assert (maybe3 VClo v1 = None) as -> by (by destruct v1, v0). }
429 simplify_option_eq.
430 simpl in Hcloclosed. destruct Hcloclosed as [HEclosed Heclosed].
431 apply interp_closed in Hinterp1 as Hcloclosed;
432 [|done|by rewrite dom_empty_L]. simpl in Hcloclosed.
433 destruct v1; simplify_option_eq.
434 destruct Hcloclosed as [HE0closed He0closed].
435 eapply interp_proper with (E2 := <[x0:=Thunk ∅ e2]> E0) (e2 := e0)
436 in Hinterp as (w & m2 & Hinterp2 & Hv); last apply subst_env_insert_eq.
437 { exists w, (S (m1 `max` m2)). rewrite !interp_S /=.
438 rewrite (interp_le Hinterp1) /=; last lia.
439 by rewrite (interp_le Hinterp2) /=; last lia. }
440 - by apply closed_env_insert.
441 - by apply closed_env_insert.
442 - by rewrite dom_insert_L.
443 - by rewrite dom_insert_L.
444 - done.
445 - done.
446 - done.
447 - done.
448Qed.
449
450Lemma final_interp e :
451 final e →
452 ∃ w m, interp m ∅ e = mret w ∧ e = val_to_expr w.
453Proof.
454 induction e; inv 1.
455 - eexists (VString _), 1. by rewrite interp_S /=.
456 - eexists (VClo _ _ _), 1. rewrite interp_S /=. split; [done|].
457 by rewrite delete_empty subst_env_empty.
458Qed.
459
460Lemma red_final_interp e :
461 red step e ∨ final e ∨ ∃ m, interp m ∅ e = mfail.
462Proof.
463 induction e.
464 - (* ENat *) right; left. constructor.
465 - (* EId *) do 2 right. by exists 1.
466 - (* EAbs *) right; left. constructor.
467 - (* EApp *) destruct IHe1 as [[??]|[Hfinal|[m Hinterp]]].
468 + left. by repeat econstructor.
469 + apply final_interp in Hfinal as (w & m & Hinterp & ->).
470 destruct (maybe3 VClo w) eqn:Hw.
471 { destruct w; simplify_eq/=. left. by repeat econstructor. }
472 do 2 right. exists (S m). by rewrite interp_S /= Hinterp /= Hw.
473 + do 2 right. exists (S m). by rewrite interp_S /= Hinterp.
474Qed.
475
476Lemma interp_complete e1 e2 :
477 closed ∅ e1 →
478 e1 -->* e2 →
479 nf step e2 →
480 ∃ mw m, interp m ∅ e1 = Res mw ∧
481 if mw is Some w then e2 = val_to_expr w else ¬final e2.
482Proof.
483 intros He1 Hsteps Hnf. induction Hsteps as [e|e1 e2 e3 Hstep _ IH].
484 { destruct (red_final_interp e) as [?|[Hfinal|[m Hinterp]]]; [done|..].
485 - apply final_interp in Hfinal as (w & m & ? & ?).
486 by exists (Some w), m.
487 - exists None, m. split; [done|]. intros Hfinal.
488 apply final_interp in Hfinal as (w & m' & ? & _).
489 by assert (mfail = mret w) by eauto using interp_agree. }
490 apply closed_step in Hstep as He2; last assumption.
491 destruct IH as (mw & m & Hinterp & ?); try done.
492 eapply interp_step in Hinterp as (mw' & m' & ? & ?).
493 - destruct mw, mw'; naive_solver.
494 - done.
495 - done.
496Qed.
497
498Lemma interp_complete_ret e1 e2 :
499 closed ∅ e1 →
500 e1 -->* e2 → final e2 →
501 ∃ w m, interp m ∅ e1 = mret w ∧ e2 = val_to_expr w.
502Proof.
503 intros Hclosed Hsteps Hfinal. apply interp_complete in Hsteps
504 as ([w|] & m & ? & ?); naive_solver eauto using final_nf.
505Qed.
506Lemma interp_complete_fail e1 e2 :
507 closed ∅ e1 →
508 e1 -->* e2 → nf step e2 → ¬final e2 →
509 ∃ m, interp m ∅ e1 = mfail.
510Proof.
511 intros Hclosed Hsteps Hnf Hforce.
512 apply interp_complete in Hsteps as ([w|] & m & ? & ?); simplify_eq/=; try by eauto.
513 destruct Hforce. apply final_val_to_expr.
514Qed.
515
516Lemma interp_sound_open E e n mv :
517 closed_env E → closed (dom E) e →
518 interp n E e = Res mv →
519 ∃ e', subst_env E e -->* e' ∧
520 if mv is Some v then e' = val_to_expr v else stuck e'.
521Proof.
522 revert E e mv.
523 induction n as [|n IH]; intros E e mv HEclosed Heclosed Hinterp; first done.
524 rewrite subst_env_eq. rewrite interp_S in Hinterp.
525 destruct e; simplify_res.
526 - (* ENat *) by eexists.
527 - (* EId *) destruct (_ !! _) as [[E' e]|] eqn:Hx; simplify_res.
528 + apply closed_env_lookup in Hx as Hxclosed; last done.
529 rewrite closed_thunk_eq in Hxclosed. destruct_and!.
530 apply IH in Hinterp as (e' & Hsteps & He'); naive_solver.
531 + eexists; repeat split; [done| |inv 1]. intros [? Hstep]. inv Hstep.
532 - (* EAbs *) by eexists.
533 - (* EApp *) destruct_and!.
534 destruct (interp _ _ _) as [mv'|] eqn:Hinterp'; simplify_res.
535 apply interp_closed in Hinterp' as Hvclosed; [|done..].
536 apply IH in Hinterp' as (e' & Hsteps & He'); [|done..].
537 destruct mv' as [v'|]; simplify_res; last first.
538 { eexists; repeat split; [by apply SAppL_rtc| |inv 1].
539 intros [e'' Hstep]. destruct He' as [Hnf Hfinal].
540 inv Hstep; [by destruct Hfinal; constructor|]. destruct Hnf. eauto. }
541 destruct (maybe3 VClo v') eqn:?; simplify_res; last first.
542 { eexists; repeat split; [by apply SAppL_rtc| |inv 1].
543 intros [e'' Hstep]. inv Hstep; destruct v'; by repeat inv_step. }
544 destruct v'; simplify_res. destruct_and!.
545 apply IH in Hinterp as (e'' & Hsteps' & He'').
546 + eexists; split; [|done]. etrans; [by apply SAppL_rtc|].
547 eapply rtc_l; first by constructor.
548 rewrite subst_env_insert // in Hsteps'.
549 + by apply closed_env_insert.
550 + by rewrite dom_insert_L.
551Qed.
552
553Lemma interp_sound n e mv :
554 closed ∅ e →
555 interp n ∅ e = Res mv →
556 ∃ e', e -->* e' ∧ if mv is Some v then e' = val_to_expr v else stuck e'.
557Proof.
558 intros He Hsteps%interp_sound_open; try done.
559 by rewrite subst_env_empty in Hsteps.
560Qed.
561
562(** Final theorems *)
563Theorem interp_sound_complete_ret e v :
564 closed ∅ e →
565 (∃ w n, interp n ∅ e = mret w ∧ val_to_expr v = val_to_expr w)
566 ↔ e -->* val_to_expr v.
567Proof.
568 split.
569 - by intros (n & w & (e' & ? & ->)%interp_sound & ->).
570 - intros Hsteps. apply interp_complete in Hsteps as ([] & ? & ? & ?);
571 unfold nf, red;
572 naive_solver eauto using final_val_to_expr, step_not_val_to_expr.
573Qed.
574
575Theorem interp_sound_complete_ret_string e s :
576 closed ∅ e →
577 (∃ n, interp n ∅ e = mret (VString s)) ↔ e -->* EString s.
578Proof.
579 split.
580 - by intros [n (e' & ? & ->)%interp_sound].
581 - intros Hsteps. apply interp_complete_ret in Hsteps as ([] & ? & ? & ?);
582 simplify_eq/=; eauto.
583Qed.
584
585Theorem interp_sound_complete_fail e :
586 closed ∅ e →
587 (∃ n, interp n ∅ e = mfail) ↔ ∃ e', e -->* e' ∧ stuck e'.
588Proof.
589 split.
590 - by intros [n ?%interp_sound].
591 - intros (e' & Hsteps & Hnf & Hforced). by eapply interp_complete_fail.
592Qed.
593
594Theorem interp_sound_complete_no_fuel e :
595 closed ∅ e →
596 (∀ n, interp n ∅ e = NoFuel) ↔ all_loop step e.
597Proof.
598 rewrite all_loop_alt. split.
599 - intros Hnofuel e' Hsteps.
600 destruct (red_final_interp e') as [|[|He']]; [done|..].
601 + apply interp_complete_ret in Hsteps as (w & m & Hinterp & _); [|done..].
602 by rewrite Hnofuel in Hinterp.
603 + apply interp_sound_complete_fail in He' as (e'' & ? & [Hnf _]);
604 last by eauto using closed_steps.
605 destruct (interp_complete e e'') as (mv & n & Hinterp & _); [done|by etrans|done|].
606 by rewrite Hnofuel in Hinterp.
607 - intros Hred n. destruct (interp n ∅ e) as [mv|] eqn:Hinterp; [|done].
608 apply interp_sound in Hinterp as (e' & Hsteps%Hred & Hstuck); [|done].
609 destruct mv as [v|]; simplify_eq/=.
610 + apply final_nf in Hsteps as []. apply final_val_to_expr.
611 + by destruct Hstuck as [[] ?].
612Qed.
613
614End lambda.
diff --git a/theories/lambda/operational.v b/theories/lambda/operational.v
new file mode 100644
index 0000000..b0fa366
--- /dev/null
+++ b/theories/lambda/operational.v
@@ -0,0 +1,38 @@
1From mininix Require Export utils.
2From stdpp Require Import options.
3
4Module Import lambda.
5
6Inductive expr :=
7 | EString (s : string)
8 | EId (x : string)
9 | EAbs (x : string) (e : expr)
10 | EApp (e1 e2 : expr).
11
12Fixpoint subst (ds : gmap string expr) (e : expr) : expr :=
13 match e with
14 | EString s => EString s
15 | EId x => if ds !! x is Some d then d else EId x
16 | EAbs x e => EAbs x (subst (delete x ds) e)
17 | EApp e1 e2 => EApp (subst ds e1) (subst ds e2)
18 end.
19
20Reserved Infix "-->" (right associativity, at level 55).
21Inductive step : expr → expr → Prop :=
22 | Sβ x e1 e2 : EApp (EAbs x e1) e2 --> subst {[x:=e2]} e1
23 | SAppL e1 e1' e2 : e1 --> e1' → EApp e1 e2 --> EApp e1' e2
24where "e1 --> e2" := (step e1 e2).
25
26Infix "-->*" := (rtc step) (right associativity, at level 55).
27
28Definition final (e : expr) : Prop :=
29 match e with
30 | EString _ => True
31 | EAbs _ _ => True
32 | _ => False
33 end.
34
35Definition stuck (e : expr) : Prop :=
36 nf step e ∧ ¬final e.
37
38End lambda.
diff --git a/theories/lambda/operational_props.v b/theories/lambda/operational_props.v
new file mode 100644
index 0000000..c331924
--- /dev/null
+++ b/theories/lambda/operational_props.v
@@ -0,0 +1,29 @@
1From mininix Require Export lambda.operational.
2From stdpp Require Import options.
3
4Module Import lambda.
5Export lambda.
6
7(** Properties of operational semantics *)
8Lemma step_not_final e1 e2 : e1 --> e2 → ¬final e1.
9Proof. induction 1; inv 1; naive_solver. Qed.
10Lemma final_nf e : final e → nf step e.
11Proof. by intros ? [??%step_not_final]. Qed.
12
13Lemma SAppL_rtc e1 e1' e2 : e1 -->* e1' → EApp e1 e2 -->* EApp e1' e2.
14Proof. induction 1; repeat (done || econstructor). Qed.
15
16Ltac inv_step := repeat
17 match goal with H : ?e --> _ |- _ => assert_fails (is_var e); inv H end.
18
19Lemma step_det e d1 d2 :
20 e --> d1 →
21 e --> d2 →
22 d1 = d2.
23Proof.
24 intros Hred1. revert d2.
25 induction Hred1; intros d2 Hred2; inv Hred2; try by inv_step.
26 f_equal. by apply IHHred1.
27Qed.
28
29End lambda.