clutch.clutch.examples.awkward_deterministic
(* Pitts & Stark's awkward example, following the ReLoC formalisation. *)
From iris.algebra Require Import csum excl.
From clutch Require Export clutch.
Set Default Proof Using "Type*".
Definition oneshotR := csumR (exclR unitR) (agreeR unitR).
Class oneshotG Σ := { oneshot_inG :: inG Σ oneshotR }.
Definition oneshotΣ : gFunctors := #[GFunctor oneshotR].
Global Instance subG_oneshotΣ {Σ} : subG oneshotΣ Σ → oneshotG Σ.
Proof. solve_inG. Qed.
Section proofs.
Context `{!clutchRGS Σ}.
Definition awkwardN := nroot.@"awkward".
Lemma refinement1 :
⊢ REL
let: "x" := ref #1 in
(λ: "f", "f" #();; !"x")
<<
(λ: "f", "f" #();; #1)
: (() → ()) → lrel_int.
Proof.
rel_alloc_l x as "Hx".
repeat rel_pure_l.
iApply (refines_na_alloc (x ↦ #1)%I awkwardN).
iSplitL => //.
iIntros "#Hinv".
rel_pures_r.
rel_arrow.
iIntros (f1 f2) "#Hff".
rel_rec_l. rel_rec_r.
iApply (refines_seq with "[Hff]").
- iApply refines_app; eauto.
rel_values; eauto.
- iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "[Hx Hclose]".
rel_load_l.
iApply (refines_na_close with "[- $Hclose $Hx]").
rel_values.
Qed.
Definition pending γ `{oneshotG Σ} := own γ (Cinl (Excl ())).
Definition shot γ `{oneshotG Σ} := own γ (Cinr (to_agree ())).
Lemma new_pending `{oneshotG Σ} : ⊢ |==> ∃ γ, pending γ.
Proof. by apply own_alloc. Qed.
Lemma shoot γ `{oneshotG Σ} : pending γ ⊢ |==> shot γ.
Proof.
apply own_update.
intros n [f |]; simpl; eauto.
destruct f; simpl; try by inversion 1.
Qed.
Definition shootN := nroot .@ "shootN".
Lemma shot_not_pending γ `{oneshotG Σ} :
shot γ -∗ pending γ -∗ False.
Proof.
iIntros "Hs Hp".
iPoseProof (own_valid_2 with "Hs Hp") as "H".
iDestruct "H" as %[].
Qed.
Lemma refinement2 `{oneshotG Σ} :
⊢ REL
let: "x" := ref #0 in
(λ: "f", "x" <- #1;; "f" #();; !"x")
<<
(let: "x" := ref #1 in
λ: "f", "f" #();; !"x")
: (() → ()) → lrel_int.
Proof.
rel_alloc_l x as "Hx".
rel_alloc_r y as "Hy".
repeat rel_pure_l; repeat rel_pure_r.
iMod new_pending as (γ) "Ht".
set (P := ((x ↦ #0 ∗ pending γ ∨ x ↦ #1 ∗ shot γ) ∗ y ↦ₛ #1)%I).
iApply (refines_na_alloc P shootN).
iSplitL ; [ iFrame ; iLeft ; iFrame |].
iIntros "#Hinv".
iApply refines_arrow.
iIntros "!#" (f1 f2) "#Hf".
iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "(HP & Hclose)".
rel_let_l. rel_let_r.
unfold P.
iDestruct "HP" as "([(Hx & Hp) | (Hx & #Hs)] & Hy)" ;
rel_store_l ; rel_pures_l.
- iMod (shoot γ with "Hp") as "#Hs".
iApply (refines_na_close with "[-$Hclose]").
iSplitL. { iFrame. iRight. by iFrame. }
iApply (refines_seq with "[Hf]").
+ iApply (refines_app with "Hf").
by rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "([[[Hx >Hp] | [Hx Hs']] Hy] & Hclose)".
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
rel_load_l.
rel_load_r.
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
- iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
iApply (refines_seq with "[Hf]"); auto.
+ iApply (refines_app with "Hf").
by rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "([[[Hx >Hp] | [Hx Hs']] Hy] & Hclose)".
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
rel_load_l.
rel_load_r.
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
Qed.
Lemma refinement25 `{oneshotG Σ} :
⊢ REL
(λ: "f", "f" #();; #1)
<<
(let: "x" := ref #0 in
(λ: "f", "x" <- #1;; "f" #();; !"x"))
: (() → ()) → lrel_int.
Proof.
rel_alloc_r x as "Hx".
repeat rel_pure_r.
iMod new_pending as (γ) "Ht".
set (P := ((x ↦ₛ #0 ∗ pending γ ∨ x ↦ₛ #1 ∗ shot γ))%I).
iApply (refines_na_alloc P shootN).
iSplitL ; [ iFrame ; iLeft ; iFrame |].
iIntros "#Hinv".
rel_pure_l.
iApply refines_arrow.
iIntros "!#" (f1 f2) "#Hf".
repeat rel_pure_l. repeat rel_pure_r.
iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "(>[[Hx Hp] | [Hx #Hs]] & Hclose)" ;
rel_store_r; repeat rel_pure_r.
- iMod (shoot γ with "Hp") as "#Hs".
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
iApply (refines_seq with "[Hf]"); auto.
+ iApply (refines_app with "Hf").
rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "[[[>Hx >Hp] | [>Hx _]] Hclose]";
rel_load_r.
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
- iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
iApply (refines_seq with "[Hf]"); auto.
+ iApply (refines_app with "Hf").
rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "[[[>Hx >Hp] | [>Hx _]] Hclose]";
rel_load_r.
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
Qed.
End proofs.
From iris.algebra Require Import csum excl.
From clutch Require Export clutch.
Set Default Proof Using "Type*".
Definition oneshotR := csumR (exclR unitR) (agreeR unitR).
Class oneshotG Σ := { oneshot_inG :: inG Σ oneshotR }.
Definition oneshotΣ : gFunctors := #[GFunctor oneshotR].
Global Instance subG_oneshotΣ {Σ} : subG oneshotΣ Σ → oneshotG Σ.
Proof. solve_inG. Qed.
Section proofs.
Context `{!clutchRGS Σ}.
Definition awkwardN := nroot.@"awkward".
Lemma refinement1 :
⊢ REL
let: "x" := ref #1 in
(λ: "f", "f" #();; !"x")
<<
(λ: "f", "f" #();; #1)
: (() → ()) → lrel_int.
Proof.
rel_alloc_l x as "Hx".
repeat rel_pure_l.
iApply (refines_na_alloc (x ↦ #1)%I awkwardN).
iSplitL => //.
iIntros "#Hinv".
rel_pures_r.
rel_arrow.
iIntros (f1 f2) "#Hff".
rel_rec_l. rel_rec_r.
iApply (refines_seq with "[Hff]").
- iApply refines_app; eauto.
rel_values; eauto.
- iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "[Hx Hclose]".
rel_load_l.
iApply (refines_na_close with "[- $Hclose $Hx]").
rel_values.
Qed.
Definition pending γ `{oneshotG Σ} := own γ (Cinl (Excl ())).
Definition shot γ `{oneshotG Σ} := own γ (Cinr (to_agree ())).
Lemma new_pending `{oneshotG Σ} : ⊢ |==> ∃ γ, pending γ.
Proof. by apply own_alloc. Qed.
Lemma shoot γ `{oneshotG Σ} : pending γ ⊢ |==> shot γ.
Proof.
apply own_update.
intros n [f |]; simpl; eauto.
destruct f; simpl; try by inversion 1.
Qed.
Definition shootN := nroot .@ "shootN".
Lemma shot_not_pending γ `{oneshotG Σ} :
shot γ -∗ pending γ -∗ False.
Proof.
iIntros "Hs Hp".
iPoseProof (own_valid_2 with "Hs Hp") as "H".
iDestruct "H" as %[].
Qed.
Lemma refinement2 `{oneshotG Σ} :
⊢ REL
let: "x" := ref #0 in
(λ: "f", "x" <- #1;; "f" #();; !"x")
<<
(let: "x" := ref #1 in
λ: "f", "f" #();; !"x")
: (() → ()) → lrel_int.
Proof.
rel_alloc_l x as "Hx".
rel_alloc_r y as "Hy".
repeat rel_pure_l; repeat rel_pure_r.
iMod new_pending as (γ) "Ht".
set (P := ((x ↦ #0 ∗ pending γ ∨ x ↦ #1 ∗ shot γ) ∗ y ↦ₛ #1)%I).
iApply (refines_na_alloc P shootN).
iSplitL ; [ iFrame ; iLeft ; iFrame |].
iIntros "#Hinv".
iApply refines_arrow.
iIntros "!#" (f1 f2) "#Hf".
iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "(HP & Hclose)".
rel_let_l. rel_let_r.
unfold P.
iDestruct "HP" as "([(Hx & Hp) | (Hx & #Hs)] & Hy)" ;
rel_store_l ; rel_pures_l.
- iMod (shoot γ with "Hp") as "#Hs".
iApply (refines_na_close with "[-$Hclose]").
iSplitL. { iFrame. iRight. by iFrame. }
iApply (refines_seq with "[Hf]").
+ iApply (refines_app with "Hf").
by rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "([[[Hx >Hp] | [Hx Hs']] Hy] & Hclose)".
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
rel_load_l.
rel_load_r.
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
- iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
iApply (refines_seq with "[Hf]"); auto.
+ iApply (refines_app with "Hf").
by rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "([[[Hx >Hp] | [Hx Hs']] Hy] & Hclose)".
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
rel_load_l.
rel_load_r.
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
Qed.
Lemma refinement25 `{oneshotG Σ} :
⊢ REL
(λ: "f", "f" #();; #1)
<<
(let: "x" := ref #0 in
(λ: "f", "x" <- #1;; "f" #();; !"x"))
: (() → ()) → lrel_int.
Proof.
rel_alloc_r x as "Hx".
repeat rel_pure_r.
iMod new_pending as (γ) "Ht".
set (P := ((x ↦ₛ #0 ∗ pending γ ∨ x ↦ₛ #1 ∗ shot γ))%I).
iApply (refines_na_alloc P shootN).
iSplitL ; [ iFrame ; iLeft ; iFrame |].
iIntros "#Hinv".
rel_pure_l.
iApply refines_arrow.
iIntros "!#" (f1 f2) "#Hf".
repeat rel_pure_l. repeat rel_pure_r.
iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "(>[[Hx Hp] | [Hx #Hs]] & Hclose)" ;
rel_store_r; repeat rel_pure_r.
- iMod (shoot γ with "Hp") as "#Hs".
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
iApply (refines_seq with "[Hf]"); auto.
+ iApply (refines_app with "Hf").
rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "[[[>Hx >Hp] | [>Hx _]] Hclose]";
rel_load_r.
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
- iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
iApply (refines_seq with "[Hf]"); auto.
+ iApply (refines_app with "Hf").
rel_values.
+ iApply (refines_na_inv with "[$Hinv]"); [done|].
iIntros "[[[>Hx >Hp] | [>Hx _]] Hclose]";
rel_load_r.
{ iExFalso. iApply (shot_not_pending with "Hs Hp"). }
iApply (refines_na_close with "[-$Hclose]"). iSplitL.
{ iModIntro. iFrame. iRight; by iFrame. }
rel_values.
Qed.
End proofs.