aboutsummaryrefslogtreecommitdiffstats
path: root/theories/dynlang/equiv.v
diff options
context:
space:
mode:
authorRutger Broekhoff2025-07-07 21:52:08 +0200
committerRutger Broekhoff2025-07-07 21:52:08 +0200
commitba61dfd69504ec6263a9dee9931d93adeb6f3142 (patch)
treed6c9b78e50eeab24e0c1c09ab45909a6ae3fd5db /theories/dynlang/equiv.v
downloadverified-dyn-lang-interp-ba61dfd69504ec6263a9dee9931d93adeb6f3142.tar.gz
verified-dyn-lang-interp-ba61dfd69504ec6263a9dee9931d93adeb6f3142.zip
Initialize repository
Diffstat (limited to 'theories/dynlang/equiv.v')
-rw-r--r--theories/dynlang/equiv.v154
1 files changed, 154 insertions, 0 deletions
diff --git a/theories/dynlang/equiv.v b/theories/dynlang/equiv.v
new file mode 100644
index 0000000..aa0b7f3
--- /dev/null
+++ b/theories/dynlang/equiv.v
@@ -0,0 +1,154 @@
1From mininix Require Export lambda.interp_proofs dynlang.interp_proofs.
2From stdpp Require Import options.
3
4Class Lift A B := lift : A → B.
5Global Hint Mode Lift ! - : typeclass_instances.
6Arguments lift {_ _ _} !_ /.
7Notation "⌜ x ⌝" := (lift x) (at level 0).
8Notation "⌜* x ⌝" := (fmap lift x) (at level 0).
9
10Module lambda.
11 Global Instance lambda_expr_lift : Lift lambda.expr dynlang.expr :=
12 fix go e := let _ : Lift _ _ := go in
13 match e with
14 | lambda.EString s => dynlang.EString s
15 | lambda.EId x => dynlang.EId ∅ (dynlang.EString x)
16 | lambda.EAbs x e => dynlang.EAbs (dynlang.EString x) ⌜e⌝
17 | lambda.EApp e1 e2 => dynlang.EApp ⌜e1⌝ ⌜e2⌝
18 end.
19
20 Global Instance lambda_thunk_lift : Lift lambda.thunk dynlang.thunk :=
21 fix go t := let _ : Lift _ _ := go in
22 dynlang.Thunk ⌜*lambda.thunk_env t⌝ ⌜lambda.thunk_expr t⌝.
23
24 Global Instance lambda_val_lift : Lift lambda.val dynlang.val := λ v,
25 match v with
26 | lambda.VString s => dynlang.VString s
27 | lambda.VClo x E e => dynlang.VClo x ⌜*E⌝ ⌜e⌝
28 end.
29End lambda.
30
31Lemma interp_open_lambda_dynlang E e mv n :
32 lambda.closed_env E → lambda.closed (dom E) e →
33 lambda.interp n E e = Res mv →
34 ∃ m, dynlang.interp m ⌜*E⌝ ⌜e⌝ = Res ⌜*mv⌝.
35Proof.
36 revert E e mv. induction n as [|n IH]; [done|]; intros E e mv HE He Hinterp.
37 rewrite lambda.interp_S in Hinterp. destruct e as [s|z|ex e|e1 e2]; simplify_res.
38 - (* EString *) by exists 1.
39 - (* EId *)
40 apply elem_of_dom in He as [[Et et] Hz]. rewrite Hz /= in Hinterp.
41 apply lambda.closed_env_lookup in Hz as He; last done.
42 rewrite lambda.closed_thunk_eq/= in He. destruct He as [HEtclosed Hetclosed].
43 apply IH in Hinterp as [m Hinterp]; [|done..].
44 exists (S (S m)). rewrite !dynlang.interp_S /= -dynlang.interp_S.
45 rewrite lookup_empty /= right_id_L lookup_fmap Hz /=.
46 eauto using dynlang.interp_le with lia.
47 - (* EAbs *) by exists 2.
48 - (* EApp *)
49 destruct He as [He1 He2].
50 destruct (lambda.interp _ _ e1) as [mw|] eqn:Hinterp1; simplify_res.
51 pose proof Hinterp1 as Hinterp1'.
52 apply lambda.interp_closed in Hinterp1' as Hmw; [|done..].
53 eapply IH in Hinterp1 as [m1 Hinterp1]; [|done..].
54 destruct mw as [w|]; simplify_res; last first.
55 { exists (S m1). by rewrite dynlang.interp_S /= Hinterp1. }
56 destruct (maybe3 lambda.VClo w) eqn:?; simplify_res; last first.
57 { exists (S m1). rewrite dynlang.interp_S /= Hinterp1 /=. by destruct w. }
58 destruct w; simplify_res.
59 apply IH in Hinterp as [m2 Hinterp2].
60 + exists (S (m1 + m2)). rewrite dynlang.interp_S /=.
61 rewrite (dynlang.interp_le Hinterp1) /=; last lia.
62 rewrite fmap_insert /= in Hinterp2.
63 rewrite (dynlang.interp_le Hinterp2) /=; last lia. done.
64 + apply lambda.closed_env_insert; [by split|naive_solver].
65 + rewrite dom_insert_L. set_solver.
66Qed.
67Lemma interp_lambda_dynlang e mv n :
68 lambda.closed ∅ e →
69 lambda.interp n ∅ e = Res mv →
70 ∃ m, dynlang.interp m ∅ ⌜e⌝ = Res ⌜*mv⌝.
71Proof. intro. by apply interp_open_lambda_dynlang. Qed.
72
73Lemma interp_open_dynlang_lambda E e mv n :
74 lambda.closed_env E → lambda.closed (dom E) e →
75 dynlang.interp n ⌜*E⌝ ⌜e⌝ = Res mv →
76 ∃ mw, lambda.interp n E e = Res mw ∧ mv = ⌜*mw⌝.
77Proof.
78 revert E e mv. induction n as [|n IH]; [done|]; intros E e mv HE He Hinterp.
79 rewrite dynlang.interp_S in Hinterp. destruct e as [s|z|ex e|e1 e2]; simplify_res.
80 - (* EString *) rewrite lambda.interp_S /=. by eexists.
81 - (* EId *)
82 destruct n as [|n]; [done|].
83 rewrite dynlang.interp_S /= -dynlang.interp_S in Hinterp.
84 apply elem_of_dom in He as [[Et et] Hz].
85 pose proof (f_equal (fmap lift) Hz) as Hz'.
86 rewrite -lookup_fmap /= in Hz'. rewrite Hz' lookup_empty /= {Hz'} in Hinterp.
87 pose proof Hz as Hz'.
88 apply lambda.closed_env_lookup in Hz' as [HEt Het]; simpl in *; last done.
89 apply IH in Hinterp as (mw & Hinterp & ->); [|done..].
90 exists mw. rewrite lambda.interp_S /= Hz /=. done.
91 - (* EAbs *)
92 destruct n as [|n]; [done|].
93 rewrite dynlang.interp_S /= in Hinterp; simplify_res.
94 rewrite lambda.interp_S /=. by eexists.
95 - (* EApp *)
96 destruct He as [He1 He2].
97 destruct (dynlang.interp _ _ _) as [mw1|] eqn:Hinterp1; simplify_res.
98 eapply IH in Hinterp1 as (mv1 & Hinterp1 & ->); [|done..].
99 destruct mv1 as [v1|]; simplify_res; last first.
100 { exists None. by rewrite lambda.interp_S /= Hinterp1. }
101 destruct (maybe3 dynlang.VClo _) eqn:?; simplify_res; last first.
102 { exists None. rewrite lambda.interp_S /= Hinterp1 /=. by destruct v1. }
103 destruct v1; simplify_res.
104 change (dynlang.Thunk ⌜*E⌝ ⌜e2⌝) with ⌜lambda.Thunk E e2⌝ in Hinterp.
105 rewrite -fmap_insert in Hinterp.
106 apply lambda.interp_closed in Hinterp1 as Hmw; [|done..].
107 apply IH in Hinterp as (mv2 & Hinterp2 & ->).
108 + exists mv2. rewrite lambda.interp_S /= Hinterp1 /=. done.
109 + apply lambda.closed_env_insert; [by split|]. naive_solver.
110 + rewrite dom_insert_L. set_solver.
111Qed.
112Lemma interp_dynlang_lambda e mv n :
113 lambda.closed ∅ e →
114 dynlang.interp n ∅ ⌜e⌝ = Res mv →
115 ∃ mw, lambda.interp n ∅ e = Res mw ∧ mv = ⌜*mw⌝.
116Proof. intros. by apply interp_open_dynlang_lambda. Qed.
117
118(* The following equivalences about the semantics trivially follow: *)
119
120Theorem interp_equiv_ret_string e s :
121 lambda.closed ∅ e →
122 rtc lambda.step e (lambda.EString s)
123 ↔ rtc dynlang.step ⌜e⌝ (dynlang.EString s).
124Proof.
125 intros. rewrite -lambda.interp_sound_complete_ret_string //.
126 rewrite -dynlang.interp_sound_complete_ret_string. split; intros [n Hinterp].
127 + by apply interp_lambda_dynlang in Hinterp.
128 + apply interp_dynlang_lambda in Hinterp as ([[]|] & ?); naive_solver.
129Qed.
130
131Theorem interp_equiv_fail e :
132 lambda.closed ∅ e →
133 (∃ e', rtc lambda.step e e' ∧ lambda.stuck e')
134 ↔ (∃ e', rtc dynlang.step ⌜e⌝ e' ∧ dynlang.stuck e').
135Proof.
136 intros. rewrite -lambda.interp_sound_complete_fail //.
137 rewrite -dynlang.interp_sound_complete_fail. split; intros [n Hinterp].
138 + by apply interp_lambda_dynlang in Hinterp.
139 + apply interp_dynlang_lambda in Hinterp as ([] & ?); naive_solver.
140Qed.
141
142Theorem interp_equiv_no_fuel e :
143 lambda.closed ∅ e →
144 all_loop lambda.step e ↔ all_loop dynlang.step ⌜e⌝.
145Proof.
146 intros He. rewrite -lambda.interp_sound_complete_no_fuel; last done.
147 rewrite -dynlang.interp_sound_complete_no_fuel. split; intros Hnofuel n.
148 - destruct (dynlang.interp n ∅ _) as [mv|] eqn:Hinterp; [|done].
149 apply interp_dynlang_lambda in Hinterp as (? & Hinterp & _); [|done].
150 by rewrite Hnofuel in Hinterp.
151 - destruct (lambda.interp n ∅ _) as [mv|] eqn:Hinterp; [|done].
152 apply interp_lambda_dynlang in Hinterp as [m Hinterp]; [|done..].
153 by rewrite Hnofuel in Hinterp.
154Qed.