aboutsummaryrefslogtreecommitdiffstats
path: root/theories/nix/operational_props.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/nix/operational_props.v')
-rw-r--r--theories/nix/operational_props.v680
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 @@
1From mininix Require Export utils nix.operational.
2From stdpp Require Import options.
3
4(** Properties of operational semantics *)
5Lemma float_to_bounded_Z_ok f : int_ok (float_to_bounded_Z f).
6Proof.
7 rewrite /float_to_bounded_Z.
8 destruct (Float.to_Z f); simplify_option_eq; done.
9Qed.
10
11Lemma int_ok_alt i :
12 int_ok i ↔ ∀ n, (63 ≤ n)%Z → Z.testbit i n = bool_decide (i < 0)%Z.
13Proof.
14 rewrite -Z.bounded_iff_bits //.
15 rewrite /int_ok bool_decide_spec /int_min /int_max Z.shiftl_1_l. lia.
16Qed.
17
18Lemma int_ok_land i1 i2 : int_ok i1 → int_ok i2 → int_ok (Z.land i1 i2).
19Proof.
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 //.
22Qed.
23
24Lemma int_ok_lor i1 i2 : int_ok i1 → int_ok i2 → int_ok (Z.lor i1 i2).
25Proof.
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 //.
28Qed.
29
30Lemma int_ok_lxor i1 i2 : int_ok i1 → int_ok i2 → int_ok (Z.lxor i1 i2).
31Proof.
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.
35Qed.
36
37Lemma 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.
40Proof.
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.
44Qed.
45
46Lemma sem_bin_op_string_ok {op f s1 s2} :
47 sem_bin_op_string op = Some f → base_lit_ok (f s1 s2).
48Proof. intros; destruct op; naive_solver. Qed.
49
50Global Hint Extern 0 (no_recs (_ <$> _)) => by apply map_Forall_fmap : core.
51
52Ltac 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
59Global Instance Attr_inj τ : Inj (=) (=) (Attr τ).
60Proof. by injection 1. Qed.
61
62Lemma fmap_attr_expr_Attr τ (es : gmap string expr) :
63 attr_expr <$> (Attr τ <$> es) = es.
64Proof. apply map_eq=> x. rewrite !lookup_fmap. by destruct (_ !! _). Qed.
65
66Lemma no_recs_insert αs x e : no_recs αs → no_recs (<[x:=AttrN e]> αs).
67Proof. by apply map_Forall_insert_2. Qed.
68Lemma no_recs_insert_inv αs x τ e :
69 αs !! x = None → no_recs (<[x:=Attr τ e]> αs) → no_recs αs.
70Proof. intros ??%map_Forall_insert; naive_solver. Qed.
71Lemma no_recs_lookup αs x τ e : no_recs αs → αs !! x = Some (Attr τ e) → τ = NONREC.
72Proof. intros Hall. apply Hall. Qed.
73
74Lemma no_recs_attr_subst αs ds : no_recs αs → no_recs (attr_subst ds <$> αs).
75Proof.
76 intros. eapply map_Forall_fmap, map_Forall_impl; [done|]. by intros ? [[]] [=].
77Qed.
78
79Lemma 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.
81Proof.
82 intros Hrecs. apply map_eq=> x. rewrite !lookup_fmap. specialize (Hrecs x).
83 destruct (αs !! x) as [[]|] eqn:?; naive_solver.
84Qed.
85
86Lemma sem_and_attr_empty : sem_and_attr ∅ = ELit (LitBool true).
87Proof. done. Qed.
88Lemma 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)).
91Proof. intros. by rewrite /sem_and_attr map_fold_sorted_insert. Qed.
92
93Lemma 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.
98Proof.
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.
107Qed.
108
109Lemma subst_empty e : subst ∅ e = e.
110Proof.
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 _ _)).
118Qed.
119
120Lemma subst_union ds1 ds2 e :
121 subst (union_kinded ds1 ds2) e = subst ds1 (subst ds2 e).
122Proof.
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) //.
134Qed.
135
136Lemma SAppL μ e1 e1' e2 :
137 e1 -{SHALLOW}-> e1' → EApp e1 e2 -{μ}-> EApp e1' e2.
138Proof. apply (SCtx (λ e, EApp e _)). constructor. Qed.
139Lemma SAppR μ ms strict e1 e2 e2' :
140 e2 -{SHALLOW}-> e2' →
141 EApp (EAbsMatch ms strict e1) e2 -{μ}-> EApp (EAbsMatch ms strict e1) e2'.
142Proof. apply SCtx. constructor. Qed.
143Lemma SSeq μ μ' e1 e1' e2 :
144 e1 -{μ'}-> e1' → ESeq μ' e1 e2 -{μ}-> ESeq μ' e1' e2.
145Proof. apply (SCtx (λ e, ESeq _ e _)). constructor. Qed.
146Lemma SList es1 e e' es2 :
147 Forall (final DEEP) es1 →
148 e -{DEEP}-> e' →
149 EList (es1 ++ e :: es2) -{DEEP}-> EList (es1 ++ e' :: es2).
150Proof. intros ?. apply (SCtx (λ e, EList (_ ++ e :: _))). by constructor. Qed.
151Lemma 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).
157Proof. intros ???. apply (SCtx (λ e, EAttr (<[x:=AttrN e]> _))). by constructor. Qed.
158Lemma SLetAttr μ k e1 e1' e2 :
159 e1 -{SHALLOW}-> e1' → ELetAttr k e1 e2 -{μ}-> ELetAttr k e1' e2.
160Proof. apply (SCtx (λ e, ELetAttr _ e _)). constructor. Qed.
161Lemma SBinOpL μ op e1 e1' e2 :
162 e1 -{SHALLOW}-> e1' → EBinOp op e1 e2 -{μ}-> EBinOp op e1' e2.
163Proof. apply (SCtx (λ e, EBinOp _ e _)). constructor. Qed.
164Lemma 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'.
167Proof. intros ??. apply SCtx. by econstructor. Qed.
168Lemma SIf μ e1 e1' e2 e3 :
169 e1 -{SHALLOW}-> e1' → EIf e1 e2 e3 -{μ}-> EIf e1' e2 e3.
170Proof. apply (SCtx (λ e, EIf e _ _)). constructor. Qed.
171
172Global Hint Constructors step : step.
173Global Hint Resolve SAppL SAppR SSeq SList SAttr SLetAttr SBinOpL SBinOpR SIf : step.
174
175Lemma step_not_final μ e1 e2 : e1 -{μ}-> e2 → ¬final μ e1.
176Proof.
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.
181Qed.
182Lemma final_nf μ e : final μ e → nf (step μ) e.
183Proof. by intros ? [??%step_not_final]. Qed.
184
185Lemma step_any_shallow μ e1 e2 :
186 e1 -{μ}-> e2 → e1 -{SHALLOW}-> e2 ∨ final SHALLOW e1.
187Proof.
188 induction 1; inv_step;
189 naive_solver eauto using final, no_recs_insert with step.
190Qed.
191
192Lemma step_shallow_any μ e1 e2 : e1 -{SHALLOW}-> e2 → e1 -{μ}-> e2.
193Proof.
194 remember SHALLOW as μ'. induction 1; inv_step; simplify_eq/=; eauto with step.
195Qed.
196Lemma steps_shallow_any μ e1 e2 : e1 -{SHALLOW}->* e2 → e1 -{μ}->* e2.
197Proof. induction 1; eauto using rtc, step_shallow_any. Qed.
198Lemma final_any_shallow μ e : final μ e → final SHALLOW e.
199Proof. destruct μ; [done|]. induction 1; simplify_eq/=; eauto using final. Qed.
200Lemma stuck_shallow_any μ e : stuck SHALLOW e → stuck μ e.
201Proof.
202 intros [Hnf Hfinal]. split; [|naive_solver eauto using final_any_shallow].
203 intros [e' Hstep%step_any_shallow]; naive_solver.
204Qed.
205
206Lemma step_final_shallow μ e1 e2 :
207 final SHALLOW e1 → e1 -{μ}-> e2 → final SHALLOW e2.
208Proof.
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.
214Qed.
215
216Lemma SAppL_rtc μ e1 e1' e2 :
217 e1 -{SHALLOW}->* e1' → EApp e1 e2 -{μ}->* EApp e1' e2.
218Proof. induction 1; econstructor; eauto with step. Qed.
219Lemma SAppR_rtc μ ms strict e1 e2 e2' :
220 e2 -{SHALLOW}->* e2' →
221 EApp (EAbsMatch ms strict e1) e2 -{μ}->* EApp (EAbsMatch ms strict e1) e2'.
222Proof. induction 1; econstructor; eauto with step. Qed.
223Lemma SSeq_rtc μ μ' e1 e1' e2 :
224 e1 -{μ'}->* e1' → ESeq μ' e1 e2 -{μ}->* ESeq μ' e1' e2.
225Proof. induction 1; econstructor; eauto with step. Qed.
226Lemma 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).
230Proof. induction 2; econstructor; eauto with step. Qed.
231Lemma SLetAttr_rtc μ k e1 e1' e2 :
232 e1 -{SHALLOW}->* e1' → ELetAttr k e1 e2 -{μ}->* ELetAttr k e1' e2.
233Proof. induction 1; econstructor; eauto with step. Qed.
234Lemma SBinOpL_rtc μ op e1 e1' e2 :
235 e1 -{SHALLOW}->* e1' → EBinOp op e1 e2 -{μ}->* EBinOp op e1' e2.
236Proof. induction 1; econstructor; eauto with step. Qed.
237Lemma 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'.
240Proof. induction 3; econstructor; eauto with step. Qed.
241Lemma SIf_rtc μ e1 e1' e2 e3 :
242 e1 -{SHALLOW}->* e1' → EIf e1 e2 e3 -{μ}->* EIf e1' e2 e3.
243Proof. induction 1; econstructor; eauto with step. Qed.
244
245Lemma SApp_tc μ e1 e1' e2 :
246 e1 -{SHALLOW}->+ e1' → EApp e1 e2 -{μ}->+ EApp e1' e2.
247Proof. induction 1; by econstructor; eauto with step. Qed.
248Lemma SSeq_tc μ μ' e1 e1' e2 :
249 e1 -{μ'}->+ e1' → ESeq μ' e1 e2 -{μ}->+ ESeq μ' e1' e2.
250Proof. induction 1; by econstructor; eauto with step. Qed.
251Lemma 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).
255Proof. induction 2; by econstructor; eauto with step. Qed.
256Lemma SLetAttr_tc μ k e1 e1' e2 :
257 e1 -{SHALLOW}->+ e1' → ELetAttr k e1 e2 -{μ}->+ ELetAttr k e1' e2.
258Proof. induction 1; by econstructor; eauto with step. Qed.
259Lemma SBinOpL_tc μ op e1 e1' e2 :
260 e1 -{SHALLOW}->+ e1' → EBinOp op e1 e2 -{μ}->+ EBinOp op e1' e2.
261Proof. induction 1; by econstructor; eauto with step. Qed.
262Lemma 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'.
265Proof. induction 3; by econstructor; eauto with step. Qed.
266Lemma SIf_tc μ e1 e1' e2 e3 :
267 e1 -{SHALLOW}->+ e1' → EIf e1 e2 e3 -{μ}->+ EIf e1' e2 e3.
268Proof. induction 1; by econstructor; eauto with step. Qed.
269
270Lemma 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'.
275Proof. split; intros; inv_step; naive_solver eauto using SList. Qed.
276
277Lemma List_nf_cons_final es e :
278 final DEEP e →
279 nf (step DEEP) (EList es) →
280 nf (step DEEP) (EList (e :: es)).
281Proof.
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.
286Qed.
287Lemma List_nf_cons es e :
288 ¬final DEEP e →
289 nf (step DEEP) e →
290 nf (step DEEP) (EList (e :: es)).
291Proof.
292 intros Hfinal Hnf [e' (ds1 & ds2 & e1 & e2 & ? & -> & Hds1 & Hstep)%SList_inv].
293 destruct Hds1; naive_solver.
294Qed.
295
296Lemma List_steps_cons es1 es2 e :
297 final DEEP e →
298 EList es1 -{DEEP}->* EList es2 →
299 EList (e :: es1) -{DEEP}->* EList (e :: es2).
300Proof.
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.
307Qed.
308
309Lemma SAttr_rec_rtc μ αs :
310 EAttr αs -{μ}->*
311 EAttr (AttrN ∘ from_attr (subst (indirects αs)) id <$> αs).
312Proof.
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.
317Qed.
318
319Lemma 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).
325Proof.
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.
330Qed.
331
332Lemma 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'.
339Proof.
340 split; [intros; inv_step|];
341 naive_solver eauto using SAttr, no_recs_insert_inv.
342Qed.
343
344Lemma 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)).
351Proof.
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.
365Qed.
366Lemma 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)).
373Proof.
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.
385Qed.
386
387Lemma Attr_step_dom μ αs1 e2 :
388 EAttr αs1 -{μ}-> e2 →
389 ∃ αs2, e2 = EAttr αs2 ∧ ∀ i, αs1 !! i = None ↔ αs2 !! i = None.
390Proof.
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.
394Qed.
395Lemma Attr_steps_dom μ αs1 αs2 :
396 EAttr αs1 -{μ}->* EAttr αs2 → ∀ i, αs1 !! i = None ↔ αs2 !! i = None.
397Proof.
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.
403Qed.
404
405Lemma Attr_step_recs αs1 αs2 :
406 EAttr αs1 -{DEEP}-> EAttr αs2 → no_recs αs1 → no_recs αs2.
407Proof. intros. inv_step; by eauto using no_recs_insert. Qed.
408Lemma Attr_steps_recs αs1 αs2 :
409 EAttr αs1 -{DEEP}->* EAttr αs2 → no_recs αs1 → no_recs αs2.
410Proof.
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.
417Qed.
418
419Lemma 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).
425Proof.
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.
432Qed.
433Lemma 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).
439Proof.
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.
448Qed.
449
450Reserved Infix "=D=>" (right associativity, at level 55).
451
452Inductive 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'
462where "e1 =D=> e2" := (step_delayed e1 e2).
463
464Global Instance step_delayed_po : PreOrder step_delayed.
465Proof.
466 split; [constructor|].
467 intros e1 e2 e3 Hstep. revert e3.
468 induction Hstep; inv 1; eauto using step_delayed.
469Qed.
470Hint Extern 0 (_ =D=> _) => reflexivity : core.
471
472Lemma delayed_final_l e1 e2 :
473 final SHALLOW e1 →
474 e1 =D=> e2 →
475 e1 = e2.
476Proof. intros Hfinal. induction 1; try by inv Hfinal. Qed.
477
478Lemma delayed_final_r μ e1 e2 :
479 final μ e2 →
480 e1 =D=> e2 →
481 e1 -{μ}->* e2.
482Proof.
483 intros Hfinal. induction 1; try by inv Hfinal.
484 eapply rtc_l; [constructor|]. eauto.
485Qed.
486
487Lemma delayed_step_l μ e1 e1' e2 :
488 e1 =D=> e1' →
489 e1 -{μ}-> e2 →
490 ∃ e2', e1' -{μ}->* e2' ∧ e2 =D=> e2'.
491Proof.
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.
510Qed.
511
512Lemma delayed_steps_l μ e1 e1' e2 :
513 e1 =D=> e1' →
514 e1 -{μ}->* e2 →
515 ∃ e2', e1' -{μ}->* e2' ∧ e2 =D=> e2'.
516Proof.
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|].
522Qed.
523
524Lemma delayed_step_r μ e1 e1' e2 :
525 e1' =D=> e1 →
526 e1 -{μ}-> e2 →
527 ∃ e2', e1' -{μ}->+ e2' ∧ e2' =D=> e2.
528Proof.
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.
552Qed.
553
554Lemma delayed_steps_r μ e1 e1' e2 :
555 e1' =D=> e1 →
556 e1 -{μ}->* e2 →
557 ∃ e2', e1' -{μ}->* e2' ∧ e2' =D=> e2.
558Proof.
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|].
564Qed.
565
566(** Determinism *)
567
568Lemma bin_op_det op e Φ Ψ :
569 sem_bin_op op e Φ →
570 sem_bin_op op e Ψ →
571 Φ = Ψ.
572Proof. by destruct 1; inv 1. Qed.
573
574Lemma bin_op_rel_det op e1 Φ e2 d1 d2 :
575 sem_bin_op op e1 Φ →
576 Φ e2 d1 →
577 Φ e2 d2 →
578 d1 = d2.
579Proof.
580 assert (AntiSymm eq attr_le) by apply _.
581 unfold AntiSymm in *. inv 1; repeat case_match; naive_solver.
582Qed.
583
584Lemma 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).
588Proof.
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.
592Qed.
593
594Lemma 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).
599Proof.
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.
603Qed.
604
605Lemma 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).
608Proof.
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 ]).
614Qed.
615
616Lemma matches_det es ms strict βs1 βs2 :
617 matches es ms strict βs1 →
618 matches es ms strict βs2 →
619 βs1 = βs2.
620Proof.
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.
631Qed.
632
633Lemma 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'.
640Proof.
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.
661Qed.
662
663Lemma step_det μ e d1 d2 :
664 e -{μ}-> d1 →
665 e -{μ}-> d2 →
666 d1 = d2.
667Proof.
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.
680Qed.