aboutsummaryrefslogtreecommitdiffstats
path: root/theories/evallang/interp_proofs.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/evallang/interp_proofs.v')
-rw-r--r--theories/evallang/interp_proofs.v478
1 files changed, 478 insertions, 0 deletions
diff --git a/theories/evallang/interp_proofs.v b/theories/evallang/interp_proofs.v
new file mode 100644
index 0000000..0a26dd1
--- /dev/null
+++ b/theories/evallang/interp_proofs.v
@@ -0,0 +1,478 @@
1From mininix Require Export evallang.interp.
2From stdpp Require Import options.
3
4Module Import evallang.
5Export evallang.
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 ds x => EId ((thunk_to_expr <$> E !! x) ∪ ds) x
38 | EEval ds e => EEval ((thunk_to_expr <$> E) ∪ ds) (subst_env E e)
39 | EAbs ex e => EAbs (subst_env E ex) (subst_env E e)
40 | EApp e1 e2 => EApp (subst_env E e1) (subst_env E e2)
41 end.
42Proof. destruct e; rewrite /subst_env' /= ?lookup_fmap //. Qed.
43
44Lemma subst_env_alt E e : subst_env E e = subst (thunk_to_expr <$> E) e.
45Proof. done. Qed.
46
47(* Use the unfolding lemmas, don't rely on conversion *)
48Opaque subst_env'.
49
50Definition val_to_expr (v : val) : expr :=
51 match v with
52 | VString s => EString s
53 | VClo x E e => EAbs (EString x) (subst_env E e)
54 end.
55
56Lemma final_val_to_expr v : final (val_to_expr v).
57Proof. by destruct v. Qed.
58Lemma step_not_val_to_expr v e : val_to_expr v --> e → False.
59Proof. intros []%step_not_final. apply final_val_to_expr. Qed.
60
61Lemma subst_empty e : subst ∅ e = e.
62Proof. induction e; f_equal/=; rewrite ?lookup_empty ?left_id_L //. Qed.
63
64Lemma subst_env_empty e : subst_env ∅ e = e.
65Proof. rewrite subst_env_alt. apply subst_empty. Qed.
66
67Lemma interp_le {n1 n2 E e mv} :
68 interp n1 E e = Res mv → n1 ≤ n2 → interp n2 E e = Res mv.
69Proof.
70 revert n2 E e mv.
71 induction n1 as [|n1 IH]; intros [|n2] E e mv He ?; [by (done || lia)..|].
72 rewrite interp_S in He; rewrite interp_S; destruct e;
73 repeat match goal with
74 | _ => case_match
75 | H : context [(_ <$> ?mx)] |- _ => destruct mx eqn:?; simplify_res
76 | H : ?r ≫= _ = _ |- _ => destruct r as [[]|] eqn:?; simplify_res
77 | H : _ <$> ?r = _ |- _ => destruct r as [[]|] eqn:?; simplify_res
78 | |- interp ?n ?E ?e ≫= _ = _ => erewrite (IH n E e) by (done || lia)
79 | _ => progress simplify_res
80 | _ => progress simplify_option_eq
81 end; eauto with lia.
82Qed.
83
84Lemma interp_agree {n1 n2 E e mv1 mv2} :
85 interp n1 E e = Res mv1 → interp n2 E e = Res mv2 → mv1 = mv2.
86Proof.
87 intros He1 He2. apply (inj Res). destruct (total (≤) n1 n2).
88 - rewrite -He2. symmetry. eauto using interp_le.
89 - rewrite -He1. eauto using interp_le.
90Qed.
91
92Lemma subst_env_union E1 E2 e :
93 subst_env (E1 ∪ E2) e = subst_env E1 (subst_env E2 e).
94Proof.
95 revert E1 E2. induction e; intros E1 E2; rewrite subst_env_eq /=.
96 - done.
97 - rewrite !subst_env_eq lookup_union. by destruct (E1 !! _), (E2 !! _), ds.
98 - rewrite !(subst_env_eq (EEval _ _)) IHe. f_equal.
99 by rewrite assoc_L map_fmap_union.
100 - rewrite !(subst_env_eq (EAbs _ _)) /=. f_equal; auto.
101 - rewrite !(subst_env_eq (EApp _ _)) /=. f_equal; auto.
102Qed.
103
104Lemma subst_env_insert E x e t :
105 subst_env (<[x:=t]> E) e = subst {[x:=thunk_to_expr t]} (subst_env E e).
106Proof.
107 rewrite insert_union_singleton_l subst_env_union subst_env_alt.
108 by rewrite map_fmap_singleton.
109Qed.
110
111Lemma subst_env_insert_eq e1 e2 E1 E2 x E1' E2' e1' e2' :
112 subst_env E1 e1 = subst_env E2 e2 →
113 subst_env E1' e1' = subst_env E2' e2' →
114 subst_env (<[x:=Thunk E1' e1']> E1) e1 = subst_env (<[x:=Thunk E2' e2']> E2) e2.
115Proof. intros He He'. by rewrite !subst_env_insert //= He' He. Qed.
116
117Lemma option_fmap_thunk_to_expr_Thunk (me : option expr) :
118 thunk_to_expr <$> (Thunk ∅ <$> me) = me.
119Proof. destruct me; f_equal/=. by rewrite subst_env_empty. Qed.
120
121Lemma map_fmap_thunk_to_expr_Thunk (es : gmap string expr) :
122 thunk_to_expr <$> (Thunk ∅ <$> es) = es.
123Proof.
124 apply map_eq=> x. by rewrite !lookup_fmap option_fmap_thunk_to_expr_Thunk.
125Qed.
126
127Lemma subst_env_eval_eq E1 E2 ds1 ds2 e :
128 (thunk_to_expr <$> E1) ∪ ds1 = (thunk_to_expr <$> E2) ∪ ds2 →
129 subst_env (E1 ∪ (Thunk ∅ <$> ds1)) e = subst_env (E2 ∪ (Thunk ∅ <$> ds2)) e.
130Proof.
131 intros HE.
132 by rewrite !subst_env_alt !map_fmap_union !map_fmap_thunk_to_expr_Thunk HE.
133Qed.
134
135Lemma interp_proper n E1 E2 e1 e2 mv :
136 subst_env E1 e1 = subst_env E2 e2 →
137 interp n E1 e1 = Res mv →
138 ∃ mw m, interp m E2 e2 = Res mw ∧
139 val_to_expr <$> mv = val_to_expr <$> mw.
140Proof.
141 revert n E1 E2 e1 e2 mv. induction n as [|n IHn]; [done|].
142 intros E1 E2 e1 e2 mv Hsubst Hinterp.
143 rewrite 2!subst_env_eq in Hsubst.
144 rewrite interp_S in Hinterp. destruct e1, e2; simplify_res; try done.
145 - eexists (Some (VString _)), 1. by rewrite interp_S.
146 - assert (thunk_to_expr <$> E1 !! x0 ∪ (Thunk ∅ <$> ds) =
147 thunk_to_expr <$> E2 !! x0 ∪ (Thunk ∅ <$> ds0)).
148 { destruct (E1 !! _), (E2 !! _), ds, ds0; simplify_eq/=;
149 f_equal/=; by rewrite ?subst_env_empty. }
150 destruct (E1 !! x0 ∪ (Thunk ∅ <$> ds)) as [[E1' e1']|],
151 (E2 !! x0 ∪ (Thunk ∅ <$> ds0)) as [[E2' e2']|] eqn:HE2;
152 simplify_res; last first.
153 { exists None, 1. by rewrite interp_S /= HE2. }
154 eapply IHn in Hinterp as (mw & m & Hinterp2 & ?); [|by eauto..].
155 exists mw, (S m). split; [|done]. rewrite interp_S /= HE2 /=. done.
156 - destruct (interp n _ e1) as [mv1|] eqn:Hinterp'; simplify_eq/=.
157 eapply IHn in Hinterp' as (mw1 & m1 & Hinterp1 & ?); last done.
158 destruct mv1 as [v1|], mw1 as [w1|]; simplify_res; last first.
159 { exists None, (S m1). by rewrite interp_S /= Hinterp1. }
160 destruct (maybe VString v1) as [x|] eqn:Hv1;
161 simplify_res; last first.
162 { exists None, (S m1). split; [|done]. rewrite interp_S /= Hinterp1 /=.
163 destruct v1, w1; repeat destruct select base_lit; by simplify_eq/=. }
164 destruct v1, w1; repeat destruct select base_lit; simplify_eq/=.
165 destruct (parse _) as [e|] eqn:Hparse; simplify_res; last first.
166 { exists None, (S m1). split; [|done]. rewrite interp_S /= Hinterp1 /=.
167 by rewrite Hparse. }
168 eapply IHn in Hinterp
169 as (mw & m2 & Hinterp2 & ?); last by apply subst_env_eval_eq.
170 exists mw, (S (m1 `max` m2)). split; [|done]. rewrite interp_S /=.
171 rewrite (interp_le Hinterp1) /=; last lia. rewrite Hparse /=.
172 eauto using interp_le with lia.
173 - destruct (interp n _ _) as [mv1|] eqn:Hinterp'; simplify_eq/=.
174 eapply IHn in Hinterp' as (mw1 & m1 & Hinterp1 & ?); last done.
175 destruct mv1 as [v1|], mw1 as [w1|]; simplify_res; last first.
176 { exists None, (S m1). by rewrite interp_S /= Hinterp1. }
177 destruct (maybe VString _) eqn:Hstring; simplify_res; last first.
178 { exists None, (S m1). rewrite interp_S /= Hinterp1 /=.
179 by assert (maybe VString w1 = None) as -> by (by destruct v1, w1). }
180 destruct v1, w1; simplify_eq/=.
181 eexists (Some (VClo _ _ _)), (S m1).
182 rewrite interp_S /= Hinterp1 /=. split; [done|]. by do 2 f_equal/=.
183 - destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res.
184 eapply IHn in Hinterp' as (mw' & m1 & Hinterp1 & ?); last done.
185 destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first.
186 { exists None, (S m1). by rewrite interp_S /= Hinterp1. }
187 destruct (maybe3 VClo _) eqn:Hclo; simplify_res; last first.
188 { exists None, (S m1). rewrite interp_S /= Hinterp1 /=.
189 by assert (maybe3 VClo w' = None) as -> by (by destruct v', w'). }
190 destruct v', w'; simplify_eq/=.
191 eapply IHn with (E2 := <[x0:=Thunk E2 e2_2]> E0) in Hinterp
192 as (w & m2 & Hinterp2 & ?); last by apply subst_env_insert_eq.
193 exists w, (S (m1 `max` m2)). rewrite interp_S /=.
194 rewrite (interp_le Hinterp1) /=; last lia.
195 rewrite (interp_le Hinterp2) /=; last lia. done.
196Qed.
197
198Lemma subst_as_subst_env x e1 e2 :
199 subst {[x:=e2]} e1 = subst_env (<[x:=Thunk ∅ e2]> ∅) e1.
200Proof. rewrite subst_env_insert //= !subst_env_empty //. Qed.
201
202Lemma interp_subst_abs n x e1 e2 mv :
203 interp n ∅ (subst {[x:=e2]} e1) = Res mv →
204 ∃ mw m, interp m (<[x:=Thunk ∅ e2]> ∅) e1 = Res mw ∧
205 val_to_expr <$> mv = val_to_expr <$> mw.
206Proof.
207 apply interp_proper. by rewrite subst_env_empty subst_as_subst_env.
208Qed.
209
210Lemma interp_subst_eval n e ds mv :
211 interp n ∅ (subst ds e) = Res mv →
212 ∃ mw m, interp m (Thunk ∅ <$> ds) e = Res mw ∧
213 val_to_expr <$> mv = val_to_expr <$> mw.
214Proof.
215 apply interp_proper.
216 by rewrite subst_env_empty subst_env_alt map_fmap_thunk_to_expr_Thunk.
217Qed.
218
219Lemma interp_step e1 e2 n mv :
220 e1 --> e2 →
221 interp n ∅ e2 = Res mv →
222 ∃ mw m, interp m ∅ e1 = Res mw ∧ val_to_expr <$> mv = val_to_expr <$> mw.
223Proof.
224 intros Hstep. revert mv n.
225 induction Hstep; intros mv n Hinterp.
226 - apply interp_subst_abs in Hinterp as (mw & [|m] & Hinterp & Hv);
227 simplify_eq/=; [|done..].
228 exists mw, (S (S (S m))). rewrite !interp_S /= -!interp_S.
229 eauto using interp_le with lia.
230 - exists mv, (S n). rewrite !interp_S /=.
231 rewrite lookup_empty left_id_L /=. done.
232 - apply interp_subst_eval in Hinterp as (mw & [|m] & Hinterp & Hv);
233 simplify_eq/=; [|done..].
234 exists mw, (S (S m)). rewrite !interp_S /= -interp_S.
235 rewrite left_id_L H /=. done.
236 - destruct n as [|n]; [done|rewrite interp_S /= in Hinterp].
237 destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res.
238 apply IHHstep in Hinterp' as (mw' & m1 & Hinterp1 & ?); simplify_res.
239 destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first.
240 { exists None, (S m1). by rewrite interp_S /= Hinterp1. }
241 destruct (maybe VString _) eqn:Hstring; simplify_res; last first.
242 { exists None, (S m1). rewrite interp_S /= Hinterp1 /=.
243 by assert (maybe VString w' = None) as -> by (by destruct v', w'). }
244 destruct v', w'; simplify_eq/=.
245 eexists (Some (VClo _ _ _)), (S m1). rewrite !interp_S /=.
246 rewrite (interp_le Hinterp1) /=; last lia. done.
247 - destruct n as [|n]; [done|rewrite interp_S /= in Hinterp].
248 destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res.
249 apply IHHstep in Hinterp' as (mw' & m1 & Hinterp1 & ?); simplify_res.
250 destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first.
251 { exists None, (S m1). by rewrite interp_S /= Hinterp1. }
252 destruct (maybe3 VClo _) eqn:Hclo; simplify_res; last first.
253 { exists None, (S m1). rewrite interp_S /= Hinterp1 /=.
254 by assert (maybe3 VClo w' = None) as -> by (by destruct v', w'). }
255 destruct v', w'; simplify_eq/=.
256 eapply interp_proper in Hinterp as (mw & m2 & Hinterp2 & Hv);
257 last apply subst_env_insert_eq; try done.
258 exists mw, (S (m1 `max` m2)). rewrite !interp_S /=.
259 rewrite (interp_le Hinterp1) /=; last lia.
260 by rewrite (interp_le Hinterp2) /=; last lia.
261 - destruct n as [|n]; [done|rewrite interp_S /= in Hinterp].
262 destruct (interp n _ e1') as [mv1|] eqn:Hinterp1; simplify_eq/=.
263 apply IHHstep in Hinterp1 as (mw1 & m & Hinterp1 & Hw1).
264 destruct mv1 as [v1|], mw1 as [w1|]; simplify_res; last first.
265 { exists None, (S m). by rewrite interp_S /= Hinterp1. }
266 destruct (maybe VString _) eqn:Hstring; simplify_res; last first.
267 { exists None, (S m). rewrite interp_S /= Hinterp1 /=.
268 by assert (maybe VString w1 = None) as -> by (by destruct v1, w1). }
269 destruct v1, w1; simplify_eq/=.
270 exists mv, (S (n `max` m)). split; [|done]. rewrite interp_S /=.
271 rewrite (interp_le Hinterp1) /=; last lia.
272 destruct (parse _); simplify_res; eauto using interp_le with lia.
273Qed.
274
275Lemma final_interp e :
276 final e →
277 ∃ w m, interp m ∅ e = mret w ∧ e = val_to_expr w.
278Proof.
279 induction e as [| | |[]|]; inv 1.
280 - eexists (VString _), 1. by rewrite interp_S /=.
281 - eexists (VClo _ _ _), 2. rewrite interp_S /=. split; [done|].
282 by rewrite subst_env_empty.
283Qed.
284
285Lemma red_final_interp e :
286 red step e ∨ final e ∨ ∃ m, interp m ∅ e = mfail.
287Proof.
288 induction e.
289 - (* ENat *) right; left. constructor.
290 - (* EId *) destruct ds as [e|].
291 + left. by repeat econstructor.
292 + do 2 right. by exists 1.
293 - (* EEval *) destruct IHe as [[??]|[Hfinal|[m Hinterp]]].
294 + left. by repeat econstructor.
295 + apply final_interp in Hfinal as (w & m & Hinterp & ->).
296 destruct (maybe VString w) as [x|] eqn:Hw; last first.
297 { do 2 right. exists (S m). rewrite interp_S /= Hinterp /=.
298 by rewrite Hw. }
299 destruct w; simplify_eq/=.
300 destruct (parse x) as [e|] eqn:Hparse; last first.
301 { do 2 right. exists (S m). rewrite interp_S /= Hinterp /=.
302 by rewrite Hparse. }
303 left. by repeat econstructor.
304 + do 2 right. exists (S m). rewrite interp_S /= Hinterp. done.
305 - (* EAbs *) destruct IHe1 as [[??]|[Hfinal|[m Hinterp]]].
306 + left. by repeat econstructor.
307 + apply final_interp in Hfinal as (w & m & Hinterp & ->).
308 destruct (maybe VString w) as [x|] eqn:Hw; last first.
309 { do 2 right. exists (S m). rewrite interp_S /= Hinterp /=.
310 by rewrite Hw. }
311 destruct w; naive_solver.
312 + do 2 right. exists (S m). rewrite interp_S /= Hinterp. done.
313 - (* EApp *) destruct IHe1 as [[??]|[Hfinal|[m Hinterp]]].
314 + left. by repeat econstructor.
315 + apply final_interp in Hfinal as (w & m & Hinterp & ->).
316 destruct (maybe3 VClo w) eqn:Hw.
317 { destruct w; simplify_eq/=. left. by repeat econstructor. }
318 do 2 right. exists (S m). by rewrite interp_S /= Hinterp /= Hw.
319 + do 2 right. exists (S m). by rewrite interp_S /= Hinterp.
320Qed.
321
322Lemma interp_complete e1 e2 :
323 e1 -->* e2 →
324 nf step e2 →
325 ∃ mw m, interp m ∅ e1 = Res mw ∧
326 if mw is Some w then e2 = val_to_expr w else ¬final e2.
327Proof.
328 intros Hsteps Hnf. induction Hsteps as [e|e1 e2 e3 Hstep _ IH].
329 { destruct (red_final_interp e) as [?|[Hfinal|[m Hinterp]]]; [done|..].
330 - apply final_interp in Hfinal as (w & m & ? & ?).
331 by exists (Some w), m.
332 - exists None, m. split; [done|]. intros Hfinal.
333 apply final_interp in Hfinal as (w & m' & ? & _).
334 by assert (mfail = mret w) by eauto using interp_agree. }
335 destruct IH as (mw & m & Hinterp & ?); try done.
336 eapply interp_step in Hinterp as (mw' & m' & ? & ?); last done.
337 destruct mw, mw'; naive_solver.
338Qed.
339
340Lemma interp_complete_ret e1 e2 :
341 e1 -->* e2 → final e2 →
342 ∃ w m, interp m ∅ e1 = mret w ∧ e2 = val_to_expr w.
343Proof.
344 intros Hsteps Hfinal. apply interp_complete in Hsteps
345 as ([w|] & m & ? & ?); naive_solver eauto using final_nf.
346Qed.
347Lemma interp_complete_fail e1 e2 :
348 e1 -->* e2 → nf step e2 → ¬final e2 →
349 ∃ m, interp m ∅ e1 = mfail.
350Proof.
351 intros Hsteps Hnf Hforce.
352 apply interp_complete in Hsteps as ([w|] & m & ? & ?); simplify_eq/=; try by eauto.
353 destruct Hforce. apply final_val_to_expr.
354Qed.
355
356Lemma interp_sound_open E e n mv :
357 interp n E e = Res mv →
358 ∃ e', subst_env E e -->* e' ∧
359 if mv is Some v then e' = val_to_expr v else stuck e'.
360Proof.
361 revert E e mv.
362 induction n as [|n IH]; intros E e mv Hinterp; first done.
363 rewrite subst_env_eq. rewrite interp_S in Hinterp.
364 destruct e; simplify_res.
365 - (* EString *) by eexists.
366 - (* EId *)
367 assert (thunk_to_expr <$> (E !! x) ∪ (Thunk ∅ <$> ds)
368 = (thunk_to_expr <$> E !! x) ∪ ds).
369 { destruct (_ !! _), ds; f_equal/=. by rewrite subst_env_empty. }
370 destruct (_ ∪ (_ <$> _)) as [[E1 e1]|], (_ ∪ _) as [e2|]; simplify_res.
371 * apply IH in Hinterp as (e'' & Hsteps & He'').
372 exists e''; split; [|done].
373 eapply rtc_l; [|done]. by econstructor.
374 * eexists; split; [done|]. split; [|inv 1].
375 intros [? Hstep]. inv_step; simplify_eq/=; congruence.
376 - (* EEval *)
377 destruct (interp _ _ _) as [mv1|] eqn:Hinterp1; simplify_res.
378 apply IH in Hinterp1 as (e1' & Hsteps1 & He1').
379 destruct mv1 as [v1|]; simplify_res; last first.
380 { eexists; split; [by eapply SEval_rtc|]. split; [|inv 1].
381 intros [??]. destruct He1' as [Hnf []].
382 inv_step; simpl; eauto. destruct Hnf; eauto. }
383 destruct (maybe VString _) as [x|] eqn:Hv1; simplify_res; last first.
384 { eexists; split; [by eapply SEval_rtc|]. split; [|inv 1].
385 intros [??]. destruct v1; inv_step. }
386 destruct v1; simplify_eq/=.
387 destruct (parse x) as [ex|] eqn:Hparse; simplify_res; last first.
388 { eexists; split; [by eapply SEval_rtc|].
389 split; [|inv 1]. intros [??]. inv_step. }
390 apply IH in Hinterp as (e'' & Hsteps & He'').
391 exists e''; split; [|done]. etrans; [by eapply SEval_rtc|].
392 eapply rtc_l; [by econstructor|].
393 by rewrite subst_env_alt map_fmap_union
394 map_fmap_thunk_to_expr_Thunk in Hsteps.
395 - (* EAbs *)
396 destruct (interp _ _ _) as [mv1|] eqn:Hinterp1; simplify_res.
397 apply IH in Hinterp1 as (e1' & Hsteps1 & He1').
398 destruct mv1 as [v1|]; simplify_res; last first.
399 { eexists; split; [by eapply SAbsL_rtc|]. split.
400 + intros [??]. destruct He1' as [Hnf []].
401 inv_step; simpl; eauto. destruct Hnf; eauto.
402 + intros ?. destruct He1' as [_ []]. by destruct e1'. }
403 eexists; split; [by eapply SAbsL_rtc|].
404 destruct (maybe VString _) as [x|] eqn:Hv1; simplify_res; last first.
405 { split; [|destruct v1; inv 1]. intros [??]. destruct v1; inv_step. }
406 by destruct v1; simplify_eq/=.
407 - (* EApp *) destruct (interp _ _ _) as [mv'|] eqn:Hinterp'; simplify_res.
408 apply IH in Hinterp' as (e' & Hsteps & He'); try done.
409 destruct mv' as [v'|]; simplify_res; last first.
410 { eexists; repeat split; [by apply SAppL_rtc| |inv 1].
411 intros [e'' Hstep]. destruct He' as [Hnf Hfinal].
412 inv Hstep; [by destruct Hfinal; constructor|]. destruct Hnf. eauto. }
413 destruct (maybe3 VClo v') eqn:?; simplify_res; last first.
414 { eexists; repeat split; [by apply SAppL_rtc| |inv 1].
415 intros [e'' Hstep]. inv Hstep; destruct v'; by repeat inv_step. }
416 destruct v'; simplify_res.
417 apply IH in Hinterp as (e'' & Hsteps' & He'').
418 eexists; split; [|done]. etrans; [by apply SAppL_rtc|].
419 eapply rtc_l; first by constructor.
420 rewrite subst_env_insert // in Hsteps'.
421Qed.
422
423Lemma interp_sound n e mv :
424 interp n ∅ e = Res mv →
425 ∃ e', e -->* e' ∧ if mv is Some v then e' = val_to_expr v else stuck e'.
426Proof.
427 intros Hsteps%interp_sound_open; try done.
428 by rewrite subst_env_empty in Hsteps.
429Qed.
430
431(** Final theorems *)
432Theorem interp_sound_complete_ret e v :
433 (∃ w n, interp n ∅ e = mret w ∧ val_to_expr v = val_to_expr w)
434 ↔ e -->* val_to_expr v.
435Proof.
436 split.
437 - by intros (n & w & (e' & ? & ->)%interp_sound & ->).
438 - intros Hsteps. apply interp_complete in Hsteps as ([] & ? & ? & ?);
439 unfold nf, red;
440 naive_solver eauto using final_val_to_expr, step_not_val_to_expr.
441Qed.
442
443Theorem interp_sound_complete_ret_string e s :
444 (∃ n, interp n ∅ e = mret (VString s)) ↔ e -->* EString s.
445Proof.
446 split.
447 - by intros [n (e' & ? & ->)%interp_sound].
448 - intros Hsteps. apply interp_complete_ret in Hsteps as ([] & ? & ? & ?);
449 simplify_eq/=; eauto.
450Qed.
451
452Theorem interp_sound_complete_fail e :
453 (∃ n, interp n ∅ e = mfail) ↔ ∃ e', e -->* e' ∧ stuck e'.
454Proof.
455 split.
456 - by intros [n ?%interp_sound].
457 - intros (e' & Hsteps & Hnf & Hforced). by eapply interp_complete_fail.
458Qed.
459
460Theorem interp_sound_complete_no_fuel e :
461 (∀ n, interp n ∅ e = NoFuel) ↔ all_loop step e.
462Proof.
463 rewrite all_loop_alt. split.
464 - intros Hnofuel e' Hsteps.
465 destruct (red_final_interp e') as [|[|He']]; [done|..].
466 + apply interp_complete_ret in Hsteps as (w & m & Hinterp & _); last done.
467 by rewrite Hnofuel in Hinterp.
468 + apply interp_sound_complete_fail in He' as (e'' & ? & [Hnf _]).
469 destruct (interp_complete e e'') as (mv & n & Hinterp & _); [by etrans|done|].
470 by rewrite Hnofuel in Hinterp.
471 - intros Hred n. destruct (interp n ∅ e) as [mv|] eqn:Hinterp; [|done].
472 apply interp_sound in Hinterp as (e' & Hsteps%Hred & Hstuck).
473 destruct mv as [v|]; simplify_eq/=.
474 + apply final_nf in Hsteps as []. apply final_val_to_expr.
475 + by destruct Hstuck as [[] ?].
476Qed.
477
478End evallang.