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