diff options
Diffstat (limited to 'theories/nix/operational_props.v')
-rw-r--r-- | theories/nix/operational_props.v | 680 |
1 files changed, 680 insertions, 0 deletions
diff --git a/theories/nix/operational_props.v b/theories/nix/operational_props.v new file mode 100644 index 0000000..4041bfe --- /dev/null +++ b/theories/nix/operational_props.v | |||
@@ -0,0 +1,680 @@ | |||
1 | From mininix Require Export utils nix.operational. | ||
2 | From stdpp Require Import options. | ||
3 | |||
4 | (** Properties of operational semantics *) | ||
5 | Lemma float_to_bounded_Z_ok f : int_ok (float_to_bounded_Z f). | ||
6 | Proof. | ||
7 | rewrite /float_to_bounded_Z. | ||
8 | destruct (Float.to_Z f); simplify_option_eq; done. | ||
9 | Qed. | ||
10 | |||
11 | Lemma int_ok_alt i : | ||
12 | int_ok i ↔ ∀ n, (63 ≤ n)%Z → Z.testbit i n = bool_decide (i < 0)%Z. | ||
13 | Proof. | ||
14 | rewrite -Z.bounded_iff_bits //. | ||
15 | rewrite /int_ok bool_decide_spec /int_min /int_max Z.shiftl_1_l. lia. | ||
16 | Qed. | ||
17 | |||
18 | Lemma int_ok_land i1 i2 : int_ok i1 → int_ok i2 → int_ok (Z.land i1 i2). | ||
19 | Proof. | ||
20 | rewrite !int_ok_alt=> Hi1 Hi2 n ?. rewrite Z.land_spec Hi1 // Hi2 //. | ||
21 | apply eq_bool_prop_intro. rewrite andb_True !bool_decide_spec Z.land_neg //. | ||
22 | Qed. | ||
23 | |||
24 | Lemma int_ok_lor i1 i2 : int_ok i1 → int_ok i2 → int_ok (Z.lor i1 i2). | ||
25 | Proof. | ||
26 | rewrite !int_ok_alt=> Hi1 Hi2 n ?. rewrite Z.lor_spec Hi1 // Hi2 //. | ||
27 | apply eq_bool_prop_intro. rewrite orb_True !bool_decide_spec Z.lor_neg //. | ||
28 | Qed. | ||
29 | |||
30 | Lemma int_ok_lxor i1 i2 : int_ok i1 → int_ok i2 → int_ok (Z.lxor i1 i2). | ||
31 | Proof. | ||
32 | rewrite !int_ok_alt=> Hi1 Hi2 n ?. rewrite Z.lxor_spec Hi1 // Hi2 //. | ||
33 | apply eq_bool_prop_intro. rewrite xorb_True !bool_decide_spec. | ||
34 | rewrite !Z.lt_nge Z.lxor_nonneg. lia. | ||
35 | Qed. | ||
36 | |||
37 | Lemma sem_bin_op_num_ok {op f n1 n2 bl} : | ||
38 | num_ok n1 → num_ok n2 → | ||
39 | sem_bin_op_num op n1 = Some f → f n2 = Some bl → base_lit_ok bl. | ||
40 | Proof. | ||
41 | intros; destruct op, n1, n2; simplify_option_eq; | ||
42 | try (by apply (bool_decide_pack _)); | ||
43 | auto using int_ok_land, int_ok_lor, int_ok_lxor. | ||
44 | Qed. | ||
45 | |||
46 | Lemma sem_bin_op_string_ok {op f s1 s2} : | ||
47 | sem_bin_op_string op = Some f → base_lit_ok (f s1 s2). | ||
48 | Proof. intros; destruct op; naive_solver. Qed. | ||
49 | |||
50 | Global Hint Extern 0 (no_recs (_ <$> _)) => by apply map_Forall_fmap : core. | ||
51 | |||
52 | Ltac inv_step := repeat | ||
53 | match goal with | ||
54 | | H : ¬no_recs (_ <$> _) |- _ => destruct H; by apply map_Forall_fmap | ||
55 | | H : ?e -{_}-> _ |- _ => assert_succeeds (is_app_constructor e); inv H | ||
56 | | H : ctx1 _ _ ?K |- _ => is_var K; inv H | ||
57 | end. | ||
58 | |||
59 | Global Instance Attr_inj τ : Inj (=) (=) (Attr τ). | ||
60 | Proof. by injection 1. Qed. | ||
61 | |||
62 | Lemma fmap_attr_expr_Attr τ (es : gmap string expr) : | ||
63 | attr_expr <$> (Attr τ <$> es) = es. | ||
64 | Proof. apply map_eq=> x. rewrite !lookup_fmap. by destruct (_ !! _). Qed. | ||
65 | |||
66 | Lemma no_recs_insert αs x e : no_recs αs → no_recs (<[x:=AttrN e]> αs). | ||
67 | Proof. by apply map_Forall_insert_2. Qed. | ||
68 | Lemma no_recs_insert_inv αs x τ e : | ||
69 | αs !! x = None → no_recs (<[x:=Attr τ e]> αs) → no_recs αs. | ||
70 | Proof. intros ??%map_Forall_insert; naive_solver. Qed. | ||
71 | Lemma no_recs_lookup αs x τ e : no_recs αs → αs !! x = Some (Attr τ e) → τ = NONREC. | ||
72 | Proof. intros Hall. apply Hall. Qed. | ||
73 | |||
74 | Lemma no_recs_attr_subst αs ds : no_recs αs → no_recs (attr_subst ds <$> αs). | ||
75 | Proof. | ||
76 | intros. eapply map_Forall_fmap, map_Forall_impl; [done|]. by intros ? [[]] [=]. | ||
77 | Qed. | ||
78 | |||
79 | Lemma from_attr_no_recs {A} (f g : expr → A) (αs : gmap string attr) : | ||
80 | no_recs αs → from_attr f g <$> αs = g ∘ attr_expr <$> αs. | ||
81 | Proof. | ||
82 | intros Hrecs. apply map_eq=> x. rewrite !lookup_fmap. specialize (Hrecs x). | ||
83 | destruct (αs !! x) as [[]|] eqn:?; naive_solver. | ||
84 | Qed. | ||
85 | |||
86 | Lemma sem_and_attr_empty : sem_and_attr ∅ = ELit (LitBool true). | ||
87 | Proof. done. Qed. | ||
88 | Lemma sem_and_attr_insert es x e : | ||
89 | es !! x = None → (∀ y, is_Some (es !! y) → attr_le x y) → | ||
90 | sem_and_attr (<[x:=e]> es) = EIf e (sem_and_attr es) (ELit (LitBool false)). | ||
91 | Proof. intros. by rewrite /sem_and_attr map_fold_sorted_insert. Qed. | ||
92 | |||
93 | Lemma matches_strict es ms ds x e : | ||
94 | es !! x = None → | ||
95 | ms !! x = None → | ||
96 | matches es ms false ds → | ||
97 | matches (<[x:=e]> es) ms false ds. | ||
98 | Proof. | ||
99 | remember false as strict. | ||
100 | induction 3; simplify_eq/=; | ||
101 | repeat match goal with | ||
102 | | H : <[ _ := _ ]> _ !! _ = None |- _ => apply lookup_insert_None in H as [??] | ||
103 | | _ => rewrite (insert_commute _ x) // | ||
104 | | _ => constructor | ||
105 | | _ => apply lookup_insert_None | ||
106 | end; eauto. | ||
107 | Qed. | ||
108 | |||
109 | Lemma subst_empty e : subst ∅ e = e. | ||
110 | Proof. | ||
111 | induction e; repeat destruct select (option _); do 2 f_equal/=; auto. | ||
112 | - apply map_eq=> x. rewrite lookup_fmap. | ||
113 | destruct (_ !! x) as [[e'|]|] eqn:Hx; do 2 f_equal/=. apply (H _ _ Hx). | ||
114 | - induction H; f_equal/=; auto. | ||
115 | - apply map_eq; intros i. rewrite lookup_fmap. | ||
116 | destruct (_ !! i) as [[τ e]|] eqn:?; do 2 f_equal/=. | ||
117 | by eapply (H _ (Attr _ _)). | ||
118 | Qed. | ||
119 | |||
120 | Lemma subst_union ds1 ds2 e : | ||
121 | subst (union_kinded ds1 ds2) e = subst ds1 (subst ds2 e). | ||
122 | Proof. | ||
123 | revert ds1 ds2. induction e; intros ds1 ds2; f_equal/=; auto. | ||
124 | - rewrite lookup_union_with. | ||
125 | destruct mkd as [[[]]|], | ||
126 | (ds1 !! x) as [[[] t1]|], (ds2 !! x) as [[[] t2]|]; naive_solver. | ||
127 | - apply map_eq=> y. rewrite !lookup_fmap. | ||
128 | destruct (_ !! y) as [[e'|]|] eqn:Hy; do 2 f_equal/=. | ||
129 | rewrite -(H _ _ Hy) //. | ||
130 | - induction H; f_equal/=; auto. | ||
131 | - apply map_eq=> y. rewrite !lookup_fmap. | ||
132 | destruct (_ !! y) as [[τ e]|] eqn:Hy; do 2 f_equal/=. | ||
133 | rewrite -(H _ _ Hy) //. | ||
134 | Qed. | ||
135 | |||
136 | Lemma SAppL μ e1 e1' e2 : | ||
137 | e1 -{SHALLOW}-> e1' → EApp e1 e2 -{μ}-> EApp e1' e2. | ||
138 | Proof. apply (SCtx (λ e, EApp e _)). constructor. Qed. | ||
139 | Lemma SAppR μ ms strict e1 e2 e2' : | ||
140 | e2 -{SHALLOW}-> e2' → | ||
141 | EApp (EAbsMatch ms strict e1) e2 -{μ}-> EApp (EAbsMatch ms strict e1) e2'. | ||
142 | Proof. apply SCtx. constructor. Qed. | ||
143 | Lemma SSeq μ μ' e1 e1' e2 : | ||
144 | e1 -{μ'}-> e1' → ESeq μ' e1 e2 -{μ}-> ESeq μ' e1' e2. | ||
145 | Proof. apply (SCtx (λ e, ESeq _ e _)). constructor. Qed. | ||
146 | Lemma SList es1 e e' es2 : | ||
147 | Forall (final DEEP) es1 → | ||
148 | e -{DEEP}-> e' → | ||
149 | EList (es1 ++ e :: es2) -{DEEP}-> EList (es1 ++ e' :: es2). | ||
150 | Proof. intros ?. apply (SCtx (λ e, EList (_ ++ e :: _))). by constructor. Qed. | ||
151 | Lemma SAttr αs x e e' : | ||
152 | no_recs αs → | ||
153 | αs !! x = None → | ||
154 | (∀ y α, αs !! y = Some α → final DEEP (attr_expr α) ∨ attr_le x y) → | ||
155 | e -{DEEP}-> e' → | ||
156 | EAttr (<[x:=AttrN e]> αs) -{DEEP}-> EAttr (<[x:=AttrN e']> αs). | ||
157 | Proof. intros ???. apply (SCtx (λ e, EAttr (<[x:=AttrN e]> _))). by constructor. Qed. | ||
158 | Lemma SLetAttr μ k e1 e1' e2 : | ||
159 | e1 -{SHALLOW}-> e1' → ELetAttr k e1 e2 -{μ}-> ELetAttr k e1' e2. | ||
160 | Proof. apply (SCtx (λ e, ELetAttr _ e _)). constructor. Qed. | ||
161 | Lemma SBinOpL μ op e1 e1' e2 : | ||
162 | e1 -{SHALLOW}-> e1' → EBinOp op e1 e2 -{μ}-> EBinOp op e1' e2. | ||
163 | Proof. apply (SCtx (λ e, EBinOp _ e _)). constructor. Qed. | ||
164 | Lemma SBinOpR μ op e1 Φ e2 e2' : | ||
165 | final SHALLOW e1 → sem_bin_op op e1 Φ → | ||
166 | e2 -{SHALLOW}-> e2' → EBinOp op e1 e2 -{μ}-> EBinOp op e1 e2'. | ||
167 | Proof. intros ??. apply SCtx. by econstructor. Qed. | ||
168 | Lemma SIf μ e1 e1' e2 e3 : | ||
169 | e1 -{SHALLOW}-> e1' → EIf e1 e2 e3 -{μ}-> EIf e1' e2 e3. | ||
170 | Proof. apply (SCtx (λ e, EIf e _ _)). constructor. Qed. | ||
171 | |||
172 | Global Hint Constructors step : step. | ||
173 | Global Hint Resolve SAppL SAppR SSeq SList SAttr SLetAttr SBinOpL SBinOpR SIf : step. | ||
174 | |||
175 | Lemma step_not_final μ e1 e2 : e1 -{μ}-> e2 → ¬final μ e1. | ||
176 | Proof. | ||
177 | assert (∀ (αs : gmap string attr) x μ e, | ||
178 | map_Forall (λ _, final DEEP ∘ attr_expr) (<[x:=Attr μ e]> αs) → final DEEP e). | ||
179 | { intros αs x μ' e Hall. eapply (Hall _ (Attr _ _)), lookup_insert. } | ||
180 | induction 1; inv 1; inv_step; decompose_Forall; naive_solver. | ||
181 | Qed. | ||
182 | Lemma final_nf μ e : final μ e → nf (step μ) e. | ||
183 | Proof. by intros ? [??%step_not_final]. Qed. | ||
184 | |||
185 | Lemma step_any_shallow μ e1 e2 : | ||
186 | e1 -{μ}-> e2 → e1 -{SHALLOW}-> e2 ∨ final SHALLOW e1. | ||
187 | Proof. | ||
188 | induction 1; inv_step; | ||
189 | naive_solver eauto using final, no_recs_insert with step. | ||
190 | Qed. | ||
191 | |||
192 | Lemma step_shallow_any μ e1 e2 : e1 -{SHALLOW}-> e2 → e1 -{μ}-> e2. | ||
193 | Proof. | ||
194 | remember SHALLOW as μ'. induction 1; inv_step; simplify_eq/=; eauto with step. | ||
195 | Qed. | ||
196 | Lemma steps_shallow_any μ e1 e2 : e1 -{SHALLOW}->* e2 → e1 -{μ}->* e2. | ||
197 | Proof. induction 1; eauto using rtc, step_shallow_any. Qed. | ||
198 | Lemma final_any_shallow μ e : final μ e → final SHALLOW e. | ||
199 | Proof. destruct μ; [done|]. induction 1; simplify_eq/=; eauto using final. Qed. | ||
200 | Lemma stuck_shallow_any μ e : stuck SHALLOW e → stuck μ e. | ||
201 | Proof. | ||
202 | intros [Hnf Hfinal]. split; [|naive_solver eauto using final_any_shallow]. | ||
203 | intros [e' Hstep%step_any_shallow]; naive_solver. | ||
204 | Qed. | ||
205 | |||
206 | Lemma step_final_shallow μ e1 e2 : | ||
207 | final SHALLOW e1 → e1 -{μ}-> e2 → final SHALLOW e2. | ||
208 | Proof. | ||
209 | induction 1; intros; inv_step; decompose_Forall; | ||
210 | eauto using step, final, no_recs_insert; try done. | ||
211 | - by odestruct step_not_final. | ||
212 | - apply map_Forall_insert in H0 as [??]; simpl in *; last done. | ||
213 | by odestruct step_not_final. | ||
214 | Qed. | ||
215 | |||
216 | Lemma SAppL_rtc μ e1 e1' e2 : | ||
217 | e1 -{SHALLOW}->* e1' → EApp e1 e2 -{μ}->* EApp e1' e2. | ||
218 | Proof. induction 1; econstructor; eauto with step. Qed. | ||
219 | Lemma SAppR_rtc μ ms strict e1 e2 e2' : | ||
220 | e2 -{SHALLOW}->* e2' → | ||
221 | EApp (EAbsMatch ms strict e1) e2 -{μ}->* EApp (EAbsMatch ms strict e1) e2'. | ||
222 | Proof. induction 1; econstructor; eauto with step. Qed. | ||
223 | Lemma SSeq_rtc μ μ' e1 e1' e2 : | ||
224 | e1 -{μ'}->* e1' → ESeq μ' e1 e2 -{μ}->* ESeq μ' e1' e2. | ||
225 | Proof. induction 1; econstructor; eauto with step. Qed. | ||
226 | Lemma SList_rtc es1 e e' es2 : | ||
227 | Forall (final DEEP) es1 → | ||
228 | e -{DEEP}->* e' → | ||
229 | EList (es1 ++ e :: es2) -{DEEP}->* EList (es1 ++ e' :: es2). | ||
230 | Proof. induction 2; econstructor; eauto with step. Qed. | ||
231 | Lemma SLetAttr_rtc μ k e1 e1' e2 : | ||
232 | e1 -{SHALLOW}->* e1' → ELetAttr k e1 e2 -{μ}->* ELetAttr k e1' e2. | ||
233 | Proof. induction 1; econstructor; eauto with step. Qed. | ||
234 | Lemma SBinOpL_rtc μ op e1 e1' e2 : | ||
235 | e1 -{SHALLOW}->* e1' → EBinOp op e1 e2 -{μ}->* EBinOp op e1' e2. | ||
236 | Proof. induction 1; econstructor; eauto with step. Qed. | ||
237 | Lemma SBinOpR_rtc μ op e1 Φ e2 e2' : | ||
238 | final SHALLOW e1 → sem_bin_op op e1 Φ → | ||
239 | e2 -{SHALLOW}->* e2' → EBinOp op e1 e2 -{μ}->* EBinOp op e1 e2'. | ||
240 | Proof. induction 3; econstructor; eauto with step. Qed. | ||
241 | Lemma SIf_rtc μ e1 e1' e2 e3 : | ||
242 | e1 -{SHALLOW}->* e1' → EIf e1 e2 e3 -{μ}->* EIf e1' e2 e3. | ||
243 | Proof. induction 1; econstructor; eauto with step. Qed. | ||
244 | |||
245 | Lemma SApp_tc μ e1 e1' e2 : | ||
246 | e1 -{SHALLOW}->+ e1' → EApp e1 e2 -{μ}->+ EApp e1' e2. | ||
247 | Proof. induction 1; by econstructor; eauto with step. Qed. | ||
248 | Lemma SSeq_tc μ μ' e1 e1' e2 : | ||
249 | e1 -{μ'}->+ e1' → ESeq μ' e1 e2 -{μ}->+ ESeq μ' e1' e2. | ||
250 | Proof. induction 1; by econstructor; eauto with step. Qed. | ||
251 | Lemma SList_tc es1 e e' es2 : | ||
252 | Forall (final DEEP) es1 → | ||
253 | e -{DEEP}->+ e' → | ||
254 | EList (es1 ++ e :: es2) -{DEEP}->+ EList (es1 ++ e' :: es2). | ||
255 | Proof. induction 2; by econstructor; eauto with step. Qed. | ||
256 | Lemma SLetAttr_tc μ k e1 e1' e2 : | ||
257 | e1 -{SHALLOW}->+ e1' → ELetAttr k e1 e2 -{μ}->+ ELetAttr k e1' e2. | ||
258 | Proof. induction 1; by econstructor; eauto with step. Qed. | ||
259 | Lemma SBinOpL_tc μ op e1 e1' e2 : | ||
260 | e1 -{SHALLOW}->+ e1' → EBinOp op e1 e2 -{μ}->+ EBinOp op e1' e2. | ||
261 | Proof. induction 1; by econstructor; eauto with step. Qed. | ||
262 | Lemma SBinOpR_tc μ op e1 Φ e2 e2' : | ||
263 | final SHALLOW e1 → sem_bin_op op e1 Φ → | ||
264 | e2 -{SHALLOW}->+ e2' → EBinOp op e1 e2 -{μ}->+ EBinOp op e1 e2'. | ||
265 | Proof. induction 3; by econstructor; eauto with step. Qed. | ||
266 | Lemma SIf_tc μ e1 e1' e2 e3 : | ||
267 | e1 -{SHALLOW}->+ e1' → EIf e1 e2 e3 -{μ}->+ EIf e1' e2 e3. | ||
268 | Proof. induction 1; by econstructor; eauto with step. Qed. | ||
269 | |||
270 | Lemma SList_inv es1 e2 : | ||
271 | EList es1 -{DEEP}-> e2 ↔ ∃ ds1 ds2 e e', | ||
272 | es1 = ds1 ++ e :: ds2 ∧ e2 = EList (ds1 ++ e' :: ds2) ∧ | ||
273 | Forall (final DEEP) ds1 ∧ | ||
274 | e -{DEEP}-> e'. | ||
275 | Proof. split; intros; inv_step; naive_solver eauto using SList. Qed. | ||
276 | |||
277 | Lemma List_nf_cons_final es e : | ||
278 | final DEEP e → | ||
279 | nf (step DEEP) (EList es) → | ||
280 | nf (step DEEP) (EList (e :: es)). | ||
281 | Proof. | ||
282 | intros Hfinal Hnf [e' (ds1 & ds2 & e1 & e2 & ? & -> & Hds1 & Hstep)%SList_inv]. | ||
283 | destruct Hds1; simplify_eq/=. | ||
284 | - by apply step_not_final in Hstep. | ||
285 | - naive_solver eauto with step. | ||
286 | Qed. | ||
287 | Lemma List_nf_cons es e : | ||
288 | ¬final DEEP e → | ||
289 | nf (step DEEP) e → | ||
290 | nf (step DEEP) (EList (e :: es)). | ||
291 | Proof. | ||
292 | intros Hfinal Hnf [e' (ds1 & ds2 & e1 & e2 & ? & -> & Hds1 & Hstep)%SList_inv]. | ||
293 | destruct Hds1; naive_solver. | ||
294 | Qed. | ||
295 | |||
296 | Lemma List_steps_cons es1 es2 e : | ||
297 | final DEEP e → | ||
298 | EList es1 -{DEEP}->* EList es2 → | ||
299 | EList (e :: es1) -{DEEP}->* EList (e :: es2). | ||
300 | Proof. | ||
301 | intros ? Hstep. | ||
302 | remember (EList es1) as e1 eqn:He1; remember (EList es2) as e2 eqn:He2. | ||
303 | revert es1 es2 He1 He2. | ||
304 | induction Hstep as [|e1 e2 e3 Hstep Hstep' IH]; | ||
305 | intros es1 es3 ??; simplify_eq/=; [done|]. | ||
306 | inv_step. eapply rtc_l; [apply (SList (_ :: _))|]; naive_solver. | ||
307 | Qed. | ||
308 | |||
309 | Lemma SAttr_rec_rtc μ αs : | ||
310 | EAttr αs -{μ}->* | ||
311 | EAttr (AttrN ∘ from_attr (subst (indirects αs)) id <$> αs). | ||
312 | Proof. | ||
313 | destruct (decide (no_recs αs)) as [Hαs|]; [|by eauto using rtc_once, step]. | ||
314 | eapply reflexive_eq. f_equal. apply map_eq=> x. rewrite lookup_fmap. | ||
315 | destruct (αs !! x) as [[τ e]|] eqn:?; [|done]. | ||
316 | assert (τ = NONREC) as -> by eauto using no_recs_lookup. done. | ||
317 | Qed. | ||
318 | |||
319 | Lemma SAttr_lookup_rtc αs x e e' : | ||
320 | no_recs αs → | ||
321 | αs !! x = None → | ||
322 | (∀ y α, αs !! y = Some α → final DEEP (attr_expr α) ∨ attr_le x y) → | ||
323 | e -{DEEP}->* e' → | ||
324 | EAttr (<[x:=AttrN e]> αs) -{DEEP}->* EAttr (<[x:=AttrN e']> αs). | ||
325 | Proof. | ||
326 | intros Hrecs Hx Hfirst He. revert αs Hrecs Hx Hfirst. | ||
327 | induction He as [e|e1 e2 e3 He12 He23 IH]; intros eτs Hrec Hx Hfirst; [done|]. | ||
328 | eapply rtc_l; first by eapply SAttr. apply IH; [done..|]. | ||
329 | apply step_not_final in He12. naive_solver. | ||
330 | Qed. | ||
331 | |||
332 | Lemma SAttr_inv αs1 e2 : | ||
333 | no_recs αs1 → | ||
334 | EAttr αs1 -{DEEP}-> e2 ↔ ∃ αs x e e', | ||
335 | αs1 = <[x:=AttrN e]> αs ∧ e2 = EAttr (<[x:=AttrN e']> αs) ∧ | ||
336 | αs !! x = None ∧ | ||
337 | (∀ y α, αs !! y = Some α → final DEEP (attr_expr α) ∨ attr_le x y) ∧ | ||
338 | e -{DEEP}-> e'. | ||
339 | Proof. | ||
340 | split; [intros; inv_step|]; | ||
341 | naive_solver eauto using SAttr, no_recs_insert_inv. | ||
342 | Qed. | ||
343 | |||
344 | Lemma Attr_nf_insert_final αs x e : | ||
345 | no_recs αs → | ||
346 | αs !! x = None → | ||
347 | final DEEP e → | ||
348 | (∀ y, is_Some (αs !! y) → attr_le x y) → | ||
349 | nf (step DEEP) (EAttr αs) → | ||
350 | nf (step DEEP) (EAttr (<[x:=AttrN e]> αs)). | ||
351 | Proof. | ||
352 | intros Hrecs Hx Hfinal Hleast Hnf | ||
353 | [? (αs'&x'&e'&e''&Hαs&->&Hx'&?&Hstep)%SAttr_inv]; | ||
354 | last by eauto using no_recs_insert. | ||
355 | assert (x ≠ x'). | ||
356 | { intros ->. apply (f_equal (.!! x')) in Hαs. rewrite !lookup_insert in Hαs. | ||
357 | apply step_not_final in Hstep. naive_solver. } | ||
358 | destruct Hnf. exists (EAttr (<[x':=AttrN e'']> (delete x αs'))). | ||
359 | rewrite -(delete_insert αs x (AttrN e)) // Hαs delete_insert_ne //. | ||
360 | refine (SCtx _ _ _ _ _ (CAttr _ _ _ _ _) _); | ||
361 | [|by rewrite lookup_delete_ne| |done]. | ||
362 | - apply (no_recs_insert _ x e) in Hrecs. rewrite Hαs in Hrecs. | ||
363 | apply no_recs_insert_inv in Hrecs; last done. by apply map_Forall_delete. | ||
364 | - intros ?? ?%lookup_delete_Some; naive_solver. | ||
365 | Qed. | ||
366 | Lemma Attr_nf_insert αs x e : | ||
367 | no_recs αs → | ||
368 | αs !! x = None → | ||
369 | ¬final DEEP e → | ||
370 | (∀ y, is_Some (αs !! y) → attr_le x y) → | ||
371 | nf (step DEEP) e → | ||
372 | nf (step DEEP) (EAttr (<[x:=AttrN e]> αs)). | ||
373 | Proof. | ||
374 | intros Hrecs Hx ?? Hnf [? (αs'&x'&e'&e''&Hαs&->&Hx'&Hleast'&Hstep)%SAttr_inv]; | ||
375 | last eauto using no_recs_insert. | ||
376 | assert (x ≠ x') as Hxx'. | ||
377 | { intros ->. apply (f_equal (.!! x')) in Hαs. rewrite !lookup_insert in Hαs. | ||
378 | naive_solver. } | ||
379 | odestruct (Hleast' x (AttrN e)); [|done|]. | ||
380 | - apply (f_equal (.!! x)) in Hαs. | ||
381 | by rewrite lookup_insert lookup_insert_ne in Hαs. | ||
382 | - apply (f_equal (.!! x')) in Hαs. | ||
383 | rewrite lookup_insert lookup_insert_ne // in Hαs. | ||
384 | destruct Hxx'. apply (anti_symm attr_le); naive_solver. | ||
385 | Qed. | ||
386 | |||
387 | Lemma Attr_step_dom μ αs1 e2 : | ||
388 | EAttr αs1 -{μ}-> e2 → | ||
389 | ∃ αs2, e2 = EAttr αs2 ∧ ∀ i, αs1 !! i = None ↔ αs2 !! i = None. | ||
390 | Proof. | ||
391 | intros; inv_step; (eexists; split; [done|]). | ||
392 | - intros i. by rewrite lookup_fmap fmap_None. | ||
393 | - intros i. rewrite !lookup_insert_None; naive_solver. | ||
394 | Qed. | ||
395 | Lemma Attr_steps_dom μ αs1 αs2 : | ||
396 | EAttr αs1 -{μ}->* EAttr αs2 → ∀ i, αs1 !! i = None ↔ αs2 !! i = None. | ||
397 | Proof. | ||
398 | intros Hstep. | ||
399 | remember (EAttr αs1) as e1 eqn:He1; remember (EAttr αs2) as e2 eqn:He2. | ||
400 | revert αs1 αs2 He1 He2. induction Hstep as [|e1 e2 e3 Hstep Hstep' IH]; | ||
401 | intros αs1 αs3 ??; simplify_eq/=; [done|]. | ||
402 | apply Attr_step_dom in Hstep; naive_solver. | ||
403 | Qed. | ||
404 | |||
405 | Lemma Attr_step_recs αs1 αs2 : | ||
406 | EAttr αs1 -{DEEP}-> EAttr αs2 → no_recs αs1 → no_recs αs2. | ||
407 | Proof. intros. inv_step; by eauto using no_recs_insert. Qed. | ||
408 | Lemma Attr_steps_recs αs1 αs2 : | ||
409 | EAttr αs1 -{DEEP}->* EAttr αs2 → no_recs αs1 → no_recs αs2. | ||
410 | Proof. | ||
411 | intros Hstep. | ||
412 | remember (EAttr αs1) as e1 eqn:He1; remember (EAttr αs2) as e2 eqn:He2. | ||
413 | revert αs1 αs2 He1 He2. induction Hstep as [|e1 e2 e3 Hstep Hstep' IH]; | ||
414 | intros αs1 αs3 ???; simplify_eq/=; [done|]. | ||
415 | pose proof (Attr_step_dom _ _ _ Hstep) as (es2 & -> & ?). | ||
416 | apply Attr_step_recs in Hstep; naive_solver. | ||
417 | Qed. | ||
418 | |||
419 | Lemma Attr_step_insert αs1 αs2 x e : | ||
420 | no_recs αs1 → | ||
421 | αs1 !! x = None → | ||
422 | final DEEP e → | ||
423 | EAttr αs1 -{DEEP}-> EAttr αs2 → | ||
424 | EAttr (<[x:=AttrN e]> αs1) -{DEEP}-> EAttr (<[x:=AttrN e]> αs2). | ||
425 | Proof. | ||
426 | intros Hrecs Hx ? | ||
427 | (αs' & x' & e1 & e1' & ? & ? & ? & ? & ?)%SAttr_inv; [|done]; simplify_eq. | ||
428 | apply lookup_insert_None in Hx as [??]. rewrite !(insert_commute _ x) //. | ||
429 | eapply SAttr; [|by rewrite lookup_insert_ne| |done]. | ||
430 | - by eapply no_recs_insert, no_recs_insert_inv. | ||
431 | - intros y e' ?%lookup_insert_Some; naive_solver. | ||
432 | Qed. | ||
433 | Lemma Attr_steps_insert αs1 αs2 x e : | ||
434 | no_recs αs1 → | ||
435 | αs1 !! x = None → | ||
436 | final DEEP e → | ||
437 | EAttr αs1 -{DEEP}->* EAttr αs2 → | ||
438 | EAttr (<[x:=AttrN e]> αs1) -{DEEP}->* EAttr (<[x:=AttrN e]> αs2). | ||
439 | Proof. | ||
440 | intros Hrecs Hx ? Hstep. | ||
441 | remember (EAttr αs1) as e1 eqn:He1; remember (EAttr αs2) as e2 eqn:He2. | ||
442 | revert αs1 αs2 Hx Hrecs He1 He2. | ||
443 | induction Hstep as [|e1 e2 e3 Hstep Hstep' IH]; | ||
444 | intros αs1 αs3 ????; simplify_eq/=; [done|]. | ||
445 | pose proof (Attr_step_dom _ _ _ Hstep) as (αs2 & -> & Hdom). | ||
446 | eapply rtc_l; first by eapply Attr_step_insert. | ||
447 | eapply IH; naive_solver eauto using Attr_step_recs. | ||
448 | Qed. | ||
449 | |||
450 | Reserved Infix "=D=>" (right associativity, at level 55). | ||
451 | |||
452 | Inductive step_delayed : relation expr := | ||
453 | | RDrefl e : | ||
454 | e =D=> e | ||
455 | | RDId x e1 e2 : | ||
456 | e1 =D=> e2 → | ||
457 | EId x (Some (ABS, e1)) =D=> e2 | ||
458 | | RDBinOp op e1 e1' e2 e2' : | ||
459 | e1 =D=> e1' → e2 =D=> e2' → EBinOp op e1 e2 =D=> EBinOp op e1' e2' | ||
460 | | RDIf e1 e1' e2 e2' e3 e3' : | ||
461 | e1 =D=> e1' → e2 =D=> e2' → e3 =D=> e3' → EIf e1 e2 e3 =D=> EIf e1' e2' e3' | ||
462 | where "e1 =D=> e2" := (step_delayed e1 e2). | ||
463 | |||
464 | Global Instance step_delayed_po : PreOrder step_delayed. | ||
465 | Proof. | ||
466 | split; [constructor|]. | ||
467 | intros e1 e2 e3 Hstep. revert e3. | ||
468 | induction Hstep; inv 1; eauto using step_delayed. | ||
469 | Qed. | ||
470 | Hint Extern 0 (_ =D=> _) => reflexivity : core. | ||
471 | |||
472 | Lemma delayed_final_l e1 e2 : | ||
473 | final SHALLOW e1 → | ||
474 | e1 =D=> e2 → | ||
475 | e1 = e2. | ||
476 | Proof. intros Hfinal. induction 1; try by inv Hfinal. Qed. | ||
477 | |||
478 | Lemma delayed_final_r μ e1 e2 : | ||
479 | final μ e2 → | ||
480 | e1 =D=> e2 → | ||
481 | e1 -{μ}->* e2. | ||
482 | Proof. | ||
483 | intros Hfinal. induction 1; try by inv Hfinal. | ||
484 | eapply rtc_l; [constructor|]. eauto. | ||
485 | Qed. | ||
486 | |||
487 | Lemma delayed_step_l μ e1 e1' e2 : | ||
488 | e1 =D=> e1' → | ||
489 | e1 -{μ}-> e2 → | ||
490 | ∃ e2', e1' -{μ}->* e2' ∧ e2 =D=> e2'. | ||
491 | Proof. | ||
492 | intros Hrem. revert μ e2. | ||
493 | induction Hrem; intros μ ? Hstep. | ||
494 | - eauto using rtc_once. | ||
495 | - inv_step. by exists e2. | ||
496 | - inv_step. | ||
497 | + eapply delayed_final_l in Hrem1 as ->, Hrem2 as ->; [|by eauto..]. | ||
498 | eexists; split; [|done]. eapply rtc_once. by econstructor. | ||
499 | + apply IHHrem1 in H2 as (e1'' & ? & ?). | ||
500 | eexists; split; [by eapply SBinOpL_rtc|]. by constructor. | ||
501 | + eapply delayed_final_l in Hrem1 as ->; [|by eauto..]. | ||
502 | apply IHHrem2 in H2 as (e2'' & ? & ?). | ||
503 | eexists (EBinOp _ e1' e2''); split; [|by constructor]. | ||
504 | by eapply SBinOpR_rtc. | ||
505 | - inv_step. | ||
506 | + eapply delayed_final_l in Hrem1 as <-; [|by repeat constructor]. | ||
507 | eexists; split; [eapply rtc_once; constructor|]. by destruct b. | ||
508 | + apply IHHrem1 in H2 as (e1'' & ? & ?). | ||
509 | eexists; split; [by eapply SIf_rtc|]. by constructor. | ||
510 | Qed. | ||
511 | |||
512 | Lemma delayed_steps_l μ e1 e1' e2 : | ||
513 | e1 =D=> e1' → | ||
514 | e1 -{μ}->* e2 → | ||
515 | ∃ e2', e1' -{μ}->* e2' ∧ e2 =D=> e2'. | ||
516 | Proof. | ||
517 | intros Hdel Hsteps. revert e1' Hdel. | ||
518 | induction Hsteps as [e|e1 e2 e3 Hstep Hsteps IH]; intros e1' Hdel. | ||
519 | { eexists; by split. } | ||
520 | eapply delayed_step_l in Hstep as (e2' & Hstep2 & Hdel2); [|done]. | ||
521 | apply IH in Hdel2 as (e3' & ? & ?). eexists; by split; [etrans|]. | ||
522 | Qed. | ||
523 | |||
524 | Lemma delayed_step_r μ e1 e1' e2 : | ||
525 | e1' =D=> e1 → | ||
526 | e1 -{μ}-> e2 → | ||
527 | ∃ e2', e1' -{μ}->+ e2' ∧ e2' =D=> e2. | ||
528 | Proof. | ||
529 | intros Hrem. revert μ e2. | ||
530 | induction Hrem; intros μ ? Hstep. | ||
531 | - eauto using tc_once. | ||
532 | - apply IHHrem in Hstep as (e1' & ? & ?). | ||
533 | eexists. split; [|done]. eapply tc_l; [econstructor|done]. | ||
534 | - inv_step. | ||
535 | + exists e0; split; [|done]. | ||
536 | eapply tc_rtc_l; [by eapply SBinOpL_rtc, delayed_final_r, Hrem1|]. | ||
537 | eapply tc_rtc_l; [by eapply SBinOpR_rtc, delayed_final_r, Hrem2|]. | ||
538 | eapply tc_once. by econstructor. | ||
539 | + apply IHHrem1 in H2 as (e1'' & ? & ?). | ||
540 | eexists; split; [by eapply SBinOpL_tc|]. by constructor. | ||
541 | + apply IHHrem2 in H2 as (e2'' & ? & ?). | ||
542 | eexists (EBinOp _ e1' e2''); split; [|by apply RDBinOp]. | ||
543 | eapply tc_rtc_l; [by eapply SBinOpL_rtc, delayed_final_r, Hrem1|]. | ||
544 | by eapply SBinOpR_tc. | ||
545 | - inv_step. | ||
546 | + exists (if b then e2 else e3). split; [|by destruct b]. | ||
547 | eapply tc_rtc_l; | ||
548 | [eapply SIf_rtc, delayed_final_r, Hrem1; by repeat constructor|]. | ||
549 | eapply tc_once; constructor. | ||
550 | + apply IHHrem1 in H2 as (e1'' & ? & ?). | ||
551 | eexists; split; [by eapply SIf_tc|]. by constructor. | ||
552 | Qed. | ||
553 | |||
554 | Lemma delayed_steps_r μ e1 e1' e2 : | ||
555 | e1' =D=> e1 → | ||
556 | e1 -{μ}->* e2 → | ||
557 | ∃ e2', e1' -{μ}->* e2' ∧ e2' =D=> e2. | ||
558 | Proof. | ||
559 | intros Hdel Hsteps. revert e1' Hdel. | ||
560 | induction Hsteps as [e|e1 e2 e3 Hstep Hsteps IH]; intros e1' Hdel. | ||
561 | { eexists; by split. } | ||
562 | eapply delayed_step_r in Hstep as (e2' & Hstep2%tc_rtc & Hdel2); [|done]. | ||
563 | apply IH in Hdel2 as (e3' & ? & ?). eexists; by split; [etrans|]. | ||
564 | Qed. | ||
565 | |||
566 | (** Determinism *) | ||
567 | |||
568 | Lemma bin_op_det op e Φ Ψ : | ||
569 | sem_bin_op op e Φ → | ||
570 | sem_bin_op op e Ψ → | ||
571 | Φ = Ψ. | ||
572 | Proof. by destruct 1; inv 1. Qed. | ||
573 | |||
574 | Lemma bin_op_rel_det op e1 Φ e2 d1 d2 : | ||
575 | sem_bin_op op e1 Φ → | ||
576 | Φ e2 d1 → | ||
577 | Φ e2 d2 → | ||
578 | d1 = d2. | ||
579 | Proof. | ||
580 | assert (AntiSymm eq attr_le) by apply _. | ||
581 | unfold AntiSymm in *. inv 1; repeat case_match; naive_solver. | ||
582 | Qed. | ||
583 | |||
584 | Lemma matches_present x e md es ms strict βs : | ||
585 | es !! x = Some e → ms !! x = Some md → | ||
586 | matches es ms strict βs → | ||
587 | βs !! x = Some (AttrN e). | ||
588 | Proof. | ||
589 | intros Hes Hms. induction 1; try done. | ||
590 | - by apply lookup_insert_Some in Hes as [[]|[]]; simplify_map_eq. | ||
591 | - by simplify_map_eq. | ||
592 | Qed. | ||
593 | |||
594 | Lemma matches_default x es ms d strict βs : | ||
595 | es !! x = None → | ||
596 | ms !! x = Some (Some d) → | ||
597 | matches es ms strict βs → | ||
598 | βs !! x = Some (AttrR d). | ||
599 | Proof. | ||
600 | intros Hes Hms. induction 1; try done. | ||
601 | - by apply lookup_insert_None in Hes as []; simplify_map_eq. | ||
602 | - by apply lookup_insert_Some in Hms as [[]|[]]; simplify_map_eq. | ||
603 | Qed. | ||
604 | |||
605 | Lemma matches_weaken x es ms strict βs : | ||
606 | matches es ms strict βs → | ||
607 | matches (delete x es) (delete x ms) strict (delete x βs). | ||
608 | Proof. | ||
609 | induction 1; [constructor|constructor|..]; rename x0 into y; | ||
610 | (destruct (decide (x = y)) as [->|Hxy]; | ||
611 | [ rewrite !delete_insert_delete // | ||
612 | | rewrite !delete_insert_ne //; constructor; | ||
613 | by simplify_map_eq ]). | ||
614 | Qed. | ||
615 | |||
616 | Lemma matches_det es ms strict βs1 βs2 : | ||
617 | matches es ms strict βs1 → | ||
618 | matches es ms strict βs2 → | ||
619 | βs1 = βs2. | ||
620 | Proof. | ||
621 | intros Hβs1. revert βs2. induction Hβs1; intros βs2 Hβs2; | ||
622 | try (inv Hβs2; done || (by exfalso; eapply (insert_non_empty (M:=stringmap)))). | ||
623 | - eapply (matches_weaken x) in Hβs2 as Hβs2'. | ||
624 | rewrite !delete_insert // in Hβs2'. | ||
625 | rewrite (IHHβs1 _ Hβs2') insert_delete //. | ||
626 | eapply matches_present; eauto; apply lookup_insert. | ||
627 | - eapply (matches_weaken x) in Hβs2 as Hβs2'. | ||
628 | rewrite delete_notin // delete_insert // in Hβs2'. | ||
629 | rewrite (IHHβs1 _ Hβs2') insert_delete //. | ||
630 | eapply matches_default; eauto. apply lookup_insert. | ||
631 | Qed. | ||
632 | |||
633 | Lemma ctx_det K1 K2 e1 e2 μ μ1' μ2' : | ||
634 | K1 e1 = K2 e2 → | ||
635 | ctx1 μ1' μ K1 → | ||
636 | ctx1 μ2' μ K2 → | ||
637 | red (step μ1') e1 → | ||
638 | red (step μ2') e2 → | ||
639 | K1 = K2 ∧ e1 = e2 ∧ μ1' = μ2'. | ||
640 | Proof. | ||
641 | intros Hes HK1 HK2 Hred1 Hred2. | ||
642 | induction HK1; inv HK2; try done. | ||
643 | - apply not_elem_of_app_cons_inv_l in Hes as [<- [<- <-]]; first done. | ||
644 | + intros He1. apply (proj1 (Forall_forall _ _) H0) in He1. | ||
645 | inv Hred1. by apply step_not_final in H1. | ||
646 | + intros He2. apply (proj1 (Forall_forall _ _) H) in He2. | ||
647 | inv Hred2. by apply step_not_final in H1. | ||
648 | - destruct (decide (x = x0)) as [<-|]. | ||
649 | { by apply map_insert_inv_eq in Hes as [[= ->] [= ->]]. } | ||
650 | apply map_insert_inv_ne in Hes as (Hx0 & Hx & Hαs); try done. | ||
651 | apply H1 in Hx0 as [contra | Hxlex0]. | ||
652 | + inv Hred2. by apply step_not_final in H5. | ||
653 | + apply H4 in Hx as [contra | Hx0lex]. | ||
654 | * inv Hred1. by apply step_not_final in H5. | ||
655 | * assert (Hasym : AntiSymm eq attr_le) by apply _. | ||
656 | by pose proof (Hasym _ _ Hxlex0 Hx0lex). | ||
657 | - inv Hred1. inv_step. | ||
658 | - inv Hred2. inv_step. | ||
659 | - inv Hred1. by apply step_not_final in H1. | ||
660 | - inv Hred2. by apply step_not_final in H1. | ||
661 | Qed. | ||
662 | |||
663 | Lemma step_det μ e d1 d2 : | ||
664 | e -{μ}-> d1 → | ||
665 | e -{μ}-> d2 → | ||
666 | d1 = d2. | ||
667 | Proof. | ||
668 | intros Hred1. revert d2. | ||
669 | induction Hred1; intros d2 Hred2; inv Hred2; try by inv_step. | ||
670 | - by apply (matches_det _ _ _ _ _ H0) in H8 as <-. | ||
671 | - inv_step. by apply step_not_final in H3. | ||
672 | - inv_step. destruct H. by apply no_recs_insert. | ||
673 | - assert (Φ = Φ0) as <- by (by eapply bin_op_det). | ||
674 | by eapply bin_op_rel_det. | ||
675 | - inv_step; by apply step_not_final in H6. | ||
676 | - inv_step. by apply step_not_final in Hred1. | ||
677 | - inv_step. destruct H2. by apply no_recs_insert. | ||
678 | - inv_step; by apply step_not_final in Hred1. | ||
679 | - eapply ctx_det in H0 as (?&?&?); [|by eauto..]; naive_solver. | ||
680 | Qed. | ||