diff --git a/tests/atomic.ref b/tests/atomic.ref new file mode 100644 index 0000000000000000000000000000000000000000..864ff13700f6a594c1fc9049be4ba2fd06b537a5 --- /dev/null +++ b/tests/atomic.ref @@ -0,0 +1,340 @@ +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + P : val → iProp Σ + ============================ + <<< ∀ x : val, P x >>> code @ ⊤ <<< ∃ y : val, P y, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + P : val → iProp Σ + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << ∀ x : val, P x >> @ ⊤, ∅ << ∃ y : val, P y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + P : val → iProp Σ + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + _ : AACC << ∀ x : val, P x + ABORT AU << ∀ x : val, P x >> @ ⊤, ∅ + << ∃ y : val, P y, COMM Q -∗ Φ #() >> >> @ ⊤, ∅ + << ∃ y : val, P y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< ∀ x : val, l ↦ x >>> code @ ⊤ <<< l ↦ x, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << ∀ x : val, l ↦ x >> @ ⊤, ∅ << l ↦ x, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + _ : AACC << ∀ x : val, l ↦ x + ABORT AU << ∀ x : val, l ↦ x >> @ ⊤, ∅ + << l ↦ x, COMM Q -∗ Φ #() >> >> @ ⊤, ∅ + << l ↦ x, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< l ↦ #() >>> code @ ⊤ <<< ∃ y : val, l ↦ y, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << l ↦ #() >> @ ⊤, ∅ << ∃ y : val, l ↦ y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + _ : AACC << l ↦ #() + ABORT AU << l ↦ #() >> @ ⊤, ∅ + << ∃ y : val, l ↦ y, COMM Q -∗ Φ #() >> >> @ ⊤, ∅ + << ∃ y : val, l ↦ y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< l ↦ #() >>> code @ ⊤ <<< l ↦ #(), RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << l ↦ #() >> @ ⊤, ∅ << l ↦ #(), COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + _ : AACC << l ↦ #() + ABORT AU << l ↦ #() >> @ ⊤, ∅ << l ↦ #(), COMM Q -∗ Φ #() >> >> + @ ⊤, ∅ << l ↦ #(), COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +"Now come the long pre/post tests" + : string +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< ∀ x : val, l ↦ x ∗ l ↦ x >>> code @ ⊤ <<< ∃ y : val, l ↦ y, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << ∀ x : val, l ↦ x ∗ l ↦ x >> @ ⊤, ∅ + << ∃ y : val, l ↦ y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< ∀ x : val, l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> + code @ ⊤ + <<< ∃ y : val, l ↦ y, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << ∀ x : val, l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >> + @ ⊤, ∅ << ∃ y : val, l ↦ y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< ∀ xx : val, l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >>> + code @ ⊤ + <<< ∃ yyyy : val, l ↦ yyyy ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx, + RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + _ : AU << ∀ xx : val, l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >> @ ⊤, ∅ + << ∃ yyyy : val, l ↦ yyyy + ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx, + COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + ============================ + <<< ∀ x : val, l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> + code @ ⊤ + <<< l ↦ x, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << ∀ x : val, l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >> @ ⊤, ∅ + << l ↦ x, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + x : val + ============================ + <<< l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> + code @ ⊤ + <<< ∃ y : val, l ↦ y, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + x : val + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >> @ ⊤, ∅ + << ∃ y : val, l ↦ y, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + x : val + ============================ + <<< l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> + code @ ⊤ + <<< l ↦ #(), RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + x : val + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >> @ ⊤, ∅ + << l ↦ #(), COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + xx, yyyy : val + ============================ + <<< l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >>> + code @ ⊤ + <<< l ↦ yyyy, RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + xx, yyyy : val + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >> + @ ⊤, ∅ << l ↦ yyyy, COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + xx, yyyy : val + ============================ + <<< l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >>> + code @ ⊤ + <<< l ↦ yyyy ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx, + RET #() >>> +1 subgoal + + Σ : gFunctors + heapG0 : heapG Σ + l : loc + xx, yyyy : val + Q : iPropI Σ + Φ : language.val heap_lang → iProp Σ + ============================ + _ : Q + "AU" : AU << l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >> @ ⊤, ∅ + << l ↦ yyyy ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx, + COMM Q -∗ Φ #() >> + --------------------------------------∗ + WP code {{ v, Φ v }} + diff --git a/tests/atomic.v b/tests/atomic.v new file mode 100644 index 0000000000000000000000000000000000000000..87efeb553794d71993524d191bd6af104b71d721 --- /dev/null +++ b/tests/atomic.v @@ -0,0 +1,91 @@ +From iris.heap_lang Require Export lifting notation. +From iris.program_logic Require Export atomic. +From iris.proofmode Require Import tactics. +From iris.heap_lang Require Import proofmode notation. +Set Default Proof Using "Type". + +(* Test if AWP and the AU obtained from AWP print. *) +Section printing. + Context `{!heapG Σ}. + + Definition code : expr := #(). + + Lemma print_both_quant (P : val → iProp Σ) : + <<< ∀ x, P x >>> code @ ⊤ <<< ∃ y, P y, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + iPoseProof (aupd_aacc with "AU") as "?". Show. + Abort. + + Lemma print_first_quant l : + <<< ∀ x, l ↦ x >>> code @ ⊤ <<< l ↦ x, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + iPoseProof (aupd_aacc with "AU") as "?". Show. + Abort. + + Lemma print_second_quant l : + <<< l ↦ #() >>> code @ ⊤ <<< ∃ y, l ↦ y, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + iPoseProof (aupd_aacc with "AU") as "?". Show. + Abort. + + Lemma print_no_quant l : + <<< l ↦ #() >>> code @ ⊤ <<< l ↦ #(), RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + iPoseProof (aupd_aacc with "AU") as "?". Show. + Abort. + + Check "Now come the long pre/post tests". + + Lemma print_both_quant_long l : + <<< ∀ x, l ↦ x ∗ l ↦ x >>> code @ ⊤ <<< ∃ y, l ↦ y, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + + Lemma print_both_quant_longpre l : + <<< ∀ x, l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> code @ ⊤ <<< ∃ y, l ↦ y, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + + Lemma print_both_quant_longpost l : + <<< ∀ xx, l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >>> code @ ⊤ <<< ∃ yyyy, l ↦ yyyy ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? ?". Show. + Abort. + + Lemma print_first_quant_long l : + <<< ∀ x, l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> code @ ⊤ <<< l ↦ x, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + + Lemma print_second_quant_long l x : + <<< l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> code @ ⊤ <<< ∃ y, l ↦ y, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + + Lemma print_no_quant_long l x : + <<< l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x ∗ l ↦ x >>> code @ ⊤ <<< l ↦ #(), RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + + Lemma print_no_quant_longpre l xx yyyy : + <<< l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >>> code @ ⊤ <<< l ↦ yyyy, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + + Lemma print_no_quant_longpost l xx yyyy : + <<< l ↦ xx ∗ l ↦ xx ∗ l ↦ xx >>> code @ ⊤ <<< l ↦ yyyy ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx ∗ l ↦ xx, RET #() >>>. + Proof. + Show. iIntros (Q Φ) "? AU". Show. + Abort. + +End printing. diff --git a/theories/bi/lib/atomic.v b/theories/bi/lib/atomic.v index 09b9ec49ce2c4b107f3732810cc774f7843df175..3ee47bfb0f10482961e6a91162d53c83a79e1161 100644 --- a/theories/bi/lib/atomic.v +++ b/theories/bi/lib/atomic.v @@ -9,24 +9,24 @@ Local Tactic Notation "iSplitWith" constr(H) := iApply (bi.and_parallel with H); iSplit; iIntros H. Section definition. - Context `{BiFUpd PROP} {A B : Type}. + Context `{BiFUpd PROP} {TA TB : tele}. Implicit Types - (Eo Em Ei : coPset) (* outside/module/inner masks *) - (α : A → PROP) (* atomic pre-condition *) + (Eo Ei : coPset) (* outer/inner masks *) + (α : TA → PROP) (* atomic pre-condition *) (P : PROP) (* abortion condition *) - (β : A → B → PROP) (* atomic post-condition *) - (Φ : A → B → PROP) (* post-condition *) + (β : TA → TB → PROP) (* atomic post-condition *) + (Φ : TA → TB → PROP) (* post-condition *) . (** atomic_acc as the "introduction form" of atomic updates: An accessor that can be aborted back to [P]. *) Definition atomic_acc Eo Ei α P β Φ : PROP := - (|={Eo, Ei}=> ∃ x, α x ∗ - ((α x ={Ei, Eo}=∗ P) ∧ (∀ y, β x y ={Ei, Eo}=∗ Φ x y)) + (|={Eo, Ei}=> ∃.. x, α x ∗ + ((α x ={Ei, Eo}=∗ P) ∧ (∀.. y, β x y ={Ei, Eo}=∗ Φ x y)) )%I. Lemma atomic_acc_wand Eo Ei α P1 P2 β Φ1 Φ2 : - ((P1 -∗ P2) ∧ (∀ x y, Φ1 x y -∗ Φ2 x y)) -∗ + ((P1 -∗ P2) ∧ (∀.. x y, Φ1 x y -∗ Φ2 x y)) -∗ (atomic_acc Eo Ei α P1 β Φ1 -∗ atomic_acc Eo Ei α P2 β Φ2). Proof. iIntros "HP12 AS". iMod "AS" as (x) "[Hα Hclose]". @@ -37,8 +37,8 @@ Section definition. iApply "HP12". iApply "Hclose". done. Qed. - Lemma atomic_acc_mask Eo Em α P β Φ : - atomic_acc Eo (Eo∖Em) α P β Φ ⊣⊢ ∀ E, ⌜Eo ⊆ E⌠→ atomic_acc E (E∖Em) α P β Φ. + Lemma atomic_acc_mask Eo Ed α P β Φ : + atomic_acc Eo (Eo∖Ed) α P β Φ ⊣⊢ ∀ E, ⌜Eo ⊆ E⌠→ atomic_acc E (E∖Ed) α P β Φ. Proof. iSplit; last first. { iIntros "Hstep". iApply ("Hstep" with "[% //]"). } @@ -51,15 +51,27 @@ Section definition. - iIntros (y) "Hβ". iApply "Hclose'". iApply "Hclose". done. Qed. + Lemma atomic_acc_mask_weaken Eo1 Eo2 Ei α P β Φ : + Eo1 ⊆ Eo2 → + atomic_acc Eo1 Ei α P β Φ -∗ atomic_acc Eo2 Ei α P β Φ. + Proof. + iIntros (HE) "Hstep". + iMod fupd_intro_mask' as "Hclose1"; first done. + iMod "Hstep" as (x) "[Hα Hclose2]". iIntros "!>". iExists x. + iFrame. iSplitWith "Hclose2". + - iIntros "Hα". iMod ("Hclose2" with "Hα") as "$". done. + - iIntros (y) "Hβ". iMod ("Hclose2" with "Hβ") as "$". done. + Qed. + (** atomic_update as a fixed-point of the equation AU = ∃ P. ▷ P ∗ □ (▷ P ==∗ α ∗ (α ==∗ AU) ∧ (β ==∗ Q)) = ∃ P. ▷ P ∗ □ (▷ P -∗ atomic_acc α AU β Q) *) - Context Eo Em α β Φ. + Context Eo Ei α β Φ. Definition atomic_update_pre (Ψ : () → PROP) (_ : ()) : PROP := (∃ (P : PROP), ▷ P ∗ - □ (▷ P -∗ atomic_acc Eo (Eo∖Em) α (Ψ ()) β Φ))%I. + □ (▷ P -∗ atomic_acc Eo Ei α (Ψ ()) β Φ))%I. Local Instance atomic_update_pre_mono : BiMonoPred atomic_update_pre. Proof. @@ -78,53 +90,177 @@ End definition. (** Seal it *) Definition atomic_update_aux : seal (@atomic_update_def). by eexists. Qed. -Definition atomic_update `{BiFUpd PROP} {A B : Type} := atomic_update_aux.(unseal) PROP _ A B. +Definition atomic_update `{BiFUpd PROP} {TA TB : tele} := atomic_update_aux.(unseal) PROP _ TA TB. Definition atomic_update_eq : @atomic_update = @atomic_update_def := atomic_update_aux.(seal_eq). +Arguments atomic_acc {PROP _ TA TB} Eo Ei _ _ _ _ : simpl never. +Arguments atomic_update {PROP _ TA TB} Eo Ei _ _ _ : simpl never. + +(** Notation: Atomic updates *) +Notation "'AU' '<<' ∀ x1 .. xn , α '>>' @ Eo , Ei '<<' ∃ y1 .. yn , β , 'COMM' Φ '>>'" := + (atomic_update (TA:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) + (TB:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + Eo Ei + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, α%I) ..) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, β%I) .. ) + ) .. ) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, Φ%I) .. ) + ) .. ) + ) + (at level 20, Eo, Ei, α, β, Φ at level 200, x1 binder, xn binder, y1 binder, yn binder, + format "'[ ' 'AU' '<<' ∀ x1 .. xn , α '>>' '/' @ Eo , Ei '/' '[ ' '<<' ∃ y1 .. yn , β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +Notation "'AU' '<<' ∀ x1 .. xn , α '>>' @ Eo , Ei '<<' β , 'COMM' Φ '>>'" := + (atomic_update (TA:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) + (TB:=TeleO) + Eo Ei + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, α%I) ..) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, tele_app (TT:=TeleO) β%I) .. ) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, tele_app (TT:=TeleO) Φ%I) .. ) + ) + (at level 20, Eo, Ei, α, β, Φ at level 200, x1 binder, xn binder, + format "'[ ' 'AU' '<<' ∀ x1 .. xn , α '>>' '/' @ Eo , Ei '/' '[ ' '<<' β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +Notation "'AU' '<<' α '>>' @ Eo , Ei '<<' ∃ y1 .. yn , β , 'COMM' Φ '>>'" := + (atomic_update (TA:=TeleO) + (TB:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + Eo Ei + (tele_app (TT:=TeleO) α%I) + (tele_app (TT:=TeleO) $ + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, β%I) ..)) + (tele_app (TT:=TeleO) $ + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, Φ%I) ..)) + ) + (at level 20, Eo, Ei, α, β, Φ at level 200, y1 binder, yn binder, + format "'[ ' 'AU' '<<' α '>>' '/' @ Eo , Ei '/' '[ ' '<<' ∃ y1 .. yn , β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +Notation "'AU' '<<' α '>>' @ Eo , Ei '<<' β , 'COMM' Φ '>>'" := + (atomic_update (TA:=TeleO) (TB:=TeleO) Eo Ei + (tele_app (TT:=TeleO) α%I) + (tele_app (TT:=TeleO) $ tele_app (TT:=TeleO) β%I) + (tele_app (TT:=TeleO) $ tele_app (TT:=TeleO) Φ%I) + ) + (at level 20, Eo, Ei, α, β, Φ at level 200, + format "'[ ' 'AU' '<<' α '>>' '/' @ Eo , Ei '/' '[ ' '<<' β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +(** Notation: Atomic accessors *) +Notation "'AACC' '<<' ∀ x1 .. xn , α 'ABORT' P '>>' @ Eo , Ei '<<' ∃ y1 .. yn , β , 'COMM' Φ '>>'" := + (atomic_acc (TA:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) + (TB:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + Eo Ei + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, α%I) ..) + P%I + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, β%I) .. ) + ) .. ) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, Φ%I) .. ) + ) .. ) + ) + (at level 20, Eo, Ei, α, P, β, Φ at level 200, x1 binder, xn binder, y1 binder, yn binder, + format "'[ ' 'AACC' '[ ' '<<' ∀ x1 .. xn , α '/' ABORT P '>>' ']' '/' @ Eo , Ei '/' '[ ' '<<' ∃ y1 .. yn , β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +Notation "'AACC' '<<' ∀ x1 .. xn , α 'ABORT' P '>>' @ Eo , Ei '<<' β , 'COMM' Φ '>>'" := + (atomic_acc (TA:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) + (TB:=TeleO) + Eo Ei + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, α%I) ..) + P%I + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, tele_app (TT:=TeleO) β%I) .. ) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, tele_app (TT:=TeleO) Φ%I) .. ) + ) + (at level 20, Eo, Ei, α, P, β, Φ at level 200, x1 binder, xn binder, + format "'[ ' 'AACC' '[ ' '<<' ∀ x1 .. xn , α '/' ABORT P '>>' ']' '/' @ Eo , Ei '/' '[ ' '<<' β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +Notation "'AACC' '<<' α 'ABORT' P '>>' @ Eo , Ei '<<' ∃ y1 .. yn , β , 'COMM' Φ '>>'" := + (atomic_acc (TA:=TeleO) + (TB:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + Eo Ei + (tele_app (TT:=TeleO) α%I) + P%I + (tele_app (TT:=TeleO) $ + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, β%I) ..)) + (tele_app (TT:=TeleO) $ + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, Φ%I) ..)) + ) + (at level 20, Eo, Ei, α, P, β, Φ at level 200, y1 binder, yn binder, + format "'[ ' 'AACC' '[ ' '<<' α '/' ABORT P '>>' ']' '/' @ Eo , Ei '/' '[ ' '<<' ∃ y1 .. yn , β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + +Notation "'AACC' '<<' α 'ABORT' P '>>' @ Eo , Ei '<<' β , 'COMM' Φ '>>'" := + (atomic_acc (TA:=TeleO) + (TB:=TeleO) + Eo Ei + (tele_app (TT:=TeleO) α%I) + P%I + (tele_app (TT:=TeleO) $ tele_app (TT:=TeleO) β%I) + (tele_app (TT:=TeleO) $ tele_app (TT:=TeleO) Φ%I) + ) + (at level 20, Eo, Ei, α, P, β, Φ at level 200, + format "'[ ' 'AACC' '[ ' '<<' α '/' ABORT P '>>' ']' '/' @ Eo , Ei '/' '[ ' '<<' β , '/' COMM Φ '>>' ']' ']'") : bi_scope. + (** Lemmas about AU *) Section lemmas. - Context `{BiFUpd PROP} {A B : Type}. - Implicit Types (α : A → PROP) (β Φ : A → B → PROP) (P : PROP). + Context `{BiFUpd PROP} {TA TB : tele}. + Implicit Types (α : TA → PROP) (β Φ : TA → TB → PROP) (P : PROP). Local Existing Instance atomic_update_pre_mono. - Global Instance atomic_acc_ne Eo Em n : + Global Instance atomic_acc_ne Eo Ei n : Proper ( - pointwise_relation A (dist n) ==> + pointwise_relation TA (dist n) ==> dist n ==> - pointwise_relation A (pointwise_relation B (dist n)) ==> - pointwise_relation A (pointwise_relation B (dist n)) ==> + pointwise_relation TA (pointwise_relation TB (dist n)) ==> + pointwise_relation TA (pointwise_relation TB (dist n)) ==> dist n - ) (atomic_acc (PROP:=PROP) Eo Em). + ) (atomic_acc (PROP:=PROP) Eo Ei). Proof. solve_proper. Qed. - Global Instance atomic_update_ne Eo Em n : + Global Instance atomic_update_ne Eo Ei n : Proper ( - pointwise_relation A (dist n) ==> - pointwise_relation A (pointwise_relation B (dist n)) ==> - pointwise_relation A (pointwise_relation B (dist n)) ==> + pointwise_relation TA (dist n) ==> + pointwise_relation TA (pointwise_relation TB (dist n)) ==> + pointwise_relation TA (pointwise_relation TB (dist n)) ==> dist n - ) (atomic_update (PROP:=PROP) Eo Em). + ) (atomic_update (PROP:=PROP) Eo Ei). Proof. rewrite atomic_update_eq /atomic_update_def /atomic_update_pre. solve_proper. Qed. - (** The ellimination form: an accessor *) - Lemma aupd_acc Eo Em E α β Φ : - Eo ⊆ E → - atomic_update Eo Em α β Φ -∗ - atomic_acc E (E∖Em) α (atomic_update Eo Em α β Φ) β Φ. + (** The ellimination form: an atomic accessor *) + Lemma aupd_aacc Eo Ei α β Φ : + atomic_update Eo Ei α β Φ -∗ + atomic_acc Eo Ei α (atomic_update Eo Ei α β Φ) β Φ. Proof using Type*. - rewrite atomic_update_eq {1}/atomic_update_def /=. iIntros (HE) "HUpd". + rewrite atomic_update_eq {1}/atomic_update_def /=. iIntros "HUpd". iPoseProof (greatest_fixpoint_unfold_1 with "HUpd") as "HUpd". - iDestruct "HUpd" as (P) "(HP & Hshift)". - iRevert (E HE). iApply atomic_acc_mask. - iApply "Hshift". done. + iDestruct "HUpd" as (P) "(HP & Hshift)". by iApply "Hshift". Qed. - Global Instance aupd_laterable Eo Em α β Φ : - Laterable (atomic_update Eo Em α β Φ). + Global Instance aupd_laterable Eo Ei α β Φ : + Laterable (atomic_update Eo Ei α β Φ). Proof. rewrite /Laterable atomic_update_eq {1}/atomic_update_def /=. iIntros "AU". iPoseProof (greatest_fixpoint_unfold_1 with "AU") as (P) "[HP #AS]". @@ -132,10 +268,10 @@ Section lemmas. iApply greatest_fixpoint_unfold_2. iExists P. iFrame "#∗". Qed. - Lemma aupd_intro P Q α β Eo Em Φ : + Lemma aupd_intro P Q α β Eo Ei Φ : Affine P → Persistent P → Laterable Q → - (P ∗ Q -∗ atomic_acc Eo (Eo∖Em) α Q β Φ) → - P ∗ Q -∗ atomic_update Eo Em α β Φ. + (P ∗ Q -∗ atomic_acc Eo Ei α Q β Φ) → + P ∗ Q -∗ atomic_update Eo Ei α β Φ. Proof. rewrite atomic_update_eq {1}/atomic_update_def /=. iIntros (??? HAU) "[#HP HQ]". @@ -145,12 +281,12 @@ Section lemmas. iApply HAU. by iFrame. Qed. - Lemma aacc_intro x Eo Ei α P β Φ : - Ei ⊆ Eo → α x -∗ - ((α x ={Eo}=∗ P) ∧ (∀ y, β x y ={Eo}=∗ Φ x y)) -∗ - atomic_acc Eo Ei α P β Φ. + Lemma aacc_intro Eo Ei α P β Φ : + Ei ⊆ Eo → (∀.. x, α x -∗ + ((α x ={Eo}=∗ P) ∧ (∀.. y, β x y ={Eo}=∗ Φ x y)) -∗ + atomic_acc Eo Ei α P β Φ)%I. Proof. - iIntros (?) "Hα Hclose". + iIntros (? x) "Hα Hclose". iMod fupd_intro_mask' as "Hclose'"; last iModIntro; first set_solver. iExists x. iFrame. iSplitWith "Hclose". - iIntros "Hα". iMod "Hclose'" as "_". iApply "Hclose". done. @@ -161,7 +297,8 @@ Section lemmas. ElimAcc (X:=X) (fupd E1 E2) (fupd E2 E1) α' β' γ' (atomic_acc E1 Ei α Pas β Φ) (λ x', atomic_acc E2 Ei α (β' x' ∗ (γ' x' -∗? Pas))%I β - (λ x y, β' x' ∗ (γ' x' -∗? Φ x y)))%I. + (λ.. x y, β' x' ∗ (γ' x' -∗? Φ x y)) + )%I. Proof. rewrite /ElimAcc. (* FIXME: Is there any way to prevent maybe_wand from unfolding? @@ -176,21 +313,24 @@ Section lemmas. iMod ("Hclose" with "Hβ'") as "Hγ'". iModIntro. destruct (γ' x'); iApply "HPas"; done. - iIntros (y) "Hβ". iMod "Hclose''" as "_". - iMod ("Hclose'" with "Hβ") as "[Hβ' HΦ]". + iMod ("Hclose'" with "Hβ") as "Hβ'". + rewrite ->!tele_app_bind. iDestruct "Hβ'" as "[Hβ' HΦ]". iMod ("Hclose" with "Hβ'") as "Hγ'". iModIntro. destruct (γ' x'); iApply "HΦ"; done. Qed. - Lemma aacc_aacc {A' B'} E1 E2 E3 + Lemma aacc_aacc {TA' TB' : tele} E1 E1' E2 E3 α P β Φ - (α' : A' → PROP) P' (β' Φ' : A' → B' → PROP) : - atomic_acc E1 E2 α P β Φ -∗ - (∀ x, α x -∗ atomic_acc E2 E3 α' (α x ∗ (P ={E1}=∗ P')) β' - (λ x' y', (α x ∗ (P ={E1}=∗ Φ' x' y')) - ∨ ∃ y, β x y ∗ (Φ x y ={E1}=∗ Φ' x' y'))) -∗ + (α' : TA' → PROP) P' (β' Φ' : TA' → TB' → PROP) : + E1' ⊆ E1 → + atomic_acc E1' E2 α P β Φ -∗ + (∀.. x, α x -∗ atomic_acc E2 E3 α' (α x ∗ (P ={E1}=∗ P')) β' + (λ.. x' y', (α x ∗ (P ={E1}=∗ Φ' x' y')) + ∨ ∃.. y, β x y ∗ (Φ x y ={E1}=∗ Φ' x' y'))) -∗ atomic_acc E1 E3 α' P' β' Φ'. Proof. - iIntros "Hupd Hstep". iMod ("Hupd") as (x) "[Hα Hclose]". + iIntros (?) "Hupd Hstep". + iMod (atomic_acc_mask_weaken with "Hupd") as (x) "[Hα Hclose]"; first done. iMod ("Hstep" with "Hα") as (x') "[Hα' Hclose']". iModIntro. iExists x'. iFrame "Hα'". iSplit. - iIntros "Hα'". iDestruct "Hclose'" as "[Hclose' _]". @@ -198,7 +338,8 @@ Section lemmas. iDestruct "Hclose" as "[Hclose _]". iMod ("Hclose" with "Hα"). iApply "Hupd". auto. - iIntros (y') "Hβ'". iDestruct "Hclose'" as "[_ Hclose']". - iMod ("Hclose'" with "Hβ'") as "[[Hα HΦ']|Hcont]". + iMod ("Hclose'" with "Hβ'") as "Hres". + rewrite ->!tele_app_bind. iDestruct "Hres" as "[[Hα HΦ']|Hcont]". + (* Abort the step we are eliminating *) iDestruct "Hclose" as "[Hclose _]". iMod ("Hclose" with "Hα") as "HP". @@ -210,64 +351,63 @@ Section lemmas. iApply "HΦ'". done. Qed. - Lemma aacc_aupd {A' B'} E1 E2 Eo Em + Lemma aacc_aupd {TA' TB' : tele} E1 E1' E2 E3 α β Φ - (α' : A' → PROP) P' (β' Φ' : A' → B' → PROP) : - Eo ⊆ E1 → - atomic_update Eo Em α β Φ -∗ - (∀ x, α x -∗ atomic_acc (E1∖Em) E2 α' (α x ∗ (atomic_update Eo Em α β Φ ={E1}=∗ P')) β' - (λ x' y', (α x ∗ (atomic_update Eo Em α β Φ ={E1}=∗ Φ' x' y')) - ∨ ∃ y, β x y ∗ (Φ x y ={E1}=∗ Φ' x' y'))) -∗ - atomic_acc E1 E2 α' P' β' Φ'. + (α' : TA' → PROP) P' (β' Φ' : TA' → TB' → PROP) : + E1' ⊆ E1 → + atomic_update E1' E2 α β Φ -∗ + (∀.. x, α x -∗ atomic_acc E2 E3 α' (α x ∗ (atomic_update E1' E2 α β Φ ={E1}=∗ P')) β' + (λ.. x' y', (α x ∗ (atomic_update E1' E2 α β Φ ={E1}=∗ Φ' x' y')) + ∨ ∃.. y, β x y ∗ (Φ x y ={E1}=∗ Φ' x' y'))) -∗ + atomic_acc E1 E3 α' P' β' Φ'. Proof. - iIntros (?) "Hupd Hstep". iApply (aacc_aacc with "[Hupd] Hstep"). - iApply aupd_acc; done. + iIntros (?) "Hupd Hstep". iApply (aacc_aacc with "[Hupd] Hstep"); first done. + iApply aupd_aacc; done. Qed. - Lemma aacc_aupd_commit {A' B'} E1 E2 Eo Em + Lemma aacc_aupd_commit {TA' TB' : tele} E1 E1' E2 E3 α β Φ - (α' : A' → PROP) P' (β' Φ' : A' → B' → PROP) : - Eo ⊆ E1 → - atomic_update Eo Em α β Φ -∗ - (∀ x, α x -∗ atomic_acc (E1∖Em) E2 α' (α x ∗ (atomic_update Eo Em α β Φ ={E1}=∗ P')) β' - (λ x' y', ∃ y, β x y ∗ (Φ x y ={E1}=∗ Φ' x' y'))) -∗ - atomic_acc E1 E2 α' P' β' Φ'. + (α' : TA' → PROP) P' (β' Φ' : TA' → TB' → PROP) : + E1' ⊆ E1 → + atomic_update E1' E2 α β Φ -∗ + (∀.. x, α x -∗ atomic_acc E2 E3 α' (α x ∗ (atomic_update E1' E2 α β Φ ={E1}=∗ P')) β' + (λ.. x' y', ∃.. y, β x y ∗ (Φ x y ={E1}=∗ Φ' x' y'))) -∗ + atomic_acc E1 E3 α' P' β' Φ'. Proof. iIntros (?) "Hupd Hstep". iApply (aacc_aupd with "Hupd"); first done. iIntros (x) "Hα". iApply atomic_acc_wand; last first. { iApply "Hstep". done. } - iSplit; first by eauto. iIntros (??) "?". by iRight. + iSplit; first by eauto. iIntros (??) "?". rewrite ->!tele_app_bind. by iRight. Qed. - Lemma aacc_aupd_abort {A' B'} E1 E2 Eo Em + Lemma aacc_aupd_abort {TA' TB' : tele} E1 E1' E2 E3 α β Φ - (α' : A' → PROP) P' (β' Φ' : A' → B' → PROP) : - Eo ⊆ E1 → - atomic_update Eo Em α β Φ -∗ - (∀ x, α x -∗ atomic_acc (E1∖Em) E2 α' (α x ∗ (atomic_update Eo Em α β Φ ={E1}=∗ P')) β' - (λ x' y', α x ∗ (atomic_update Eo Em α β Φ ={E1}=∗ Φ' x' y'))) -∗ - atomic_acc E1 E2 α' P' β' Φ'. + (α' : TA' → PROP) P' (β' Φ' : TA' → TB' → PROP) : + E1' ⊆ E1 → + atomic_update E1' E2 α β Φ -∗ + (∀.. x, α x -∗ atomic_acc E2 E3 α' (α x ∗ (atomic_update E1' E2 α β Φ ={E1}=∗ P')) β' + (λ.. x' y', α x ∗ (atomic_update E1' E2 α β Φ ={E1}=∗ Φ' x' y'))) -∗ + atomic_acc E1 E3 α' P' β' Φ'. Proof. iIntros (?) "Hupd Hstep". iApply (aacc_aupd with "Hupd"); first done. iIntros (x) "Hα". iApply atomic_acc_wand; last first. { iApply "Hstep". done. } - iSplit; first by eauto. iIntros (??) "?". by iLeft. + iSplit; first by eauto. iIntros (??) "?". rewrite ->!tele_app_bind. by iLeft. Qed. End lemmas. (** ProofMode support for atomic updates *) - Section proof_mode. - Context `{BiFUpd PROP} {A B : Type}. - Implicit Types (α : A → PROP) (β Φ : A → B → PROP) (P : PROP). + Context `{BiFUpd PROP} {TA TB : tele}. + Implicit Types (α : TA → PROP) (β Φ : TA → TB → PROP) (P : PROP). - Lemma tac_aupd_intro Γp Γs n α β Eo Em Φ P : + Lemma tac_aupd_intro Γp Γs n α β Eo Ei Φ P : Timeless (PROP:=PROP) emp → TCForall Laterable (env_to_list Γs) → P = prop_of_env Γs → - envs_entails (Envs Γp Γs n) (atomic_acc Eo (Eo∖Em) α P β Φ) → - envs_entails (Envs Γp Γs n) (atomic_update Eo Em α β Φ). + envs_entails (Envs Γp Γs n) (atomic_acc Eo Ei α P β Φ) → + envs_entails (Envs Γp Γs n) (atomic_update Eo Ei α β Φ). Proof. intros ? HΓs ->. rewrite envs_entails_eq of_envs_eq' /atomic_acc /=. setoid_rewrite prop_of_env_sound =>HAU. diff --git a/theories/heap_lang/lib/atomic_heap.v b/theories/heap_lang/lib/atomic_heap.v index ad3f079a38ab3281c597ca7b9ed075d1ccbbcd12..33871ee90fda5cbc310a6ee80cede02c443ba485 100644 --- a/theories/heap_lang/lib/atomic_heap.v +++ b/theories/heap_lang/lib/atomic_heap.v @@ -21,29 +21,20 @@ Structure atomic_heap {Σ} `{!heapG Σ} := AtomicHeap { alloc_spec v : {{{ True }}} alloc v {{{ l, RET #l; mapsto l 1 v }}}; load_spec (l : loc) : - atomic_wp (load #l)%E - ⊤ ⊤ - (λ '(v, q), mapsto l q v) - (λ '(v, q) (_:()), mapsto l q v) - (λ '(v, q) _, v); + <<< ∀ (v : val) q, mapsto l q v >>> load #l @ ⊤ <<< mapsto l q v, RET v >>>; store_spec (l : loc) (e : expr) (w : val) : IntoVal e w → - atomic_wp (store (#l, e))%E - ⊤ ⊤ - (λ v, mapsto l 1 v) - (λ v (_:()), mapsto l 1 w) - (λ _ _, #()%V); + <<< ∀ v, mapsto l 1 v >>> store (#l, e) @ ⊤ + <<< mapsto l 1 w, RET #() >>>; (* This spec is slightly weaker than it could be: It is sufficient for [w1] *or* [v] to be unboxed. However, by writing it this way the [val_is_unboxed] is outside the atomic triple, which makes it much easier to use -- and the spec is still good enough for all our applications. *) cas_spec (l : loc) (e1 e2 : expr) (w1 w2 : val) : IntoVal e1 w1 → IntoVal e2 w2 → val_is_unboxed w1 → - atomic_wp (cas (#l, e1, e2))%E - ⊤ ⊤ - (λ v, mapsto l 1 v)%I - (λ v (_:()), if decide (v = w1) then mapsto l 1 w2 else mapsto l 1 v) - (λ v _, #(if decide (v = w1) then true else false)%V); + <<< ∀ v, mapsto l 1 v >>> cas (#l, e1, e2) @ ⊤ + <<< if decide (v = w1) then mapsto l 1 w2 else mapsto l 1 v, + RET #(if decide (v = w1) then true else false) >>>; }. Arguments atomic_heap _ {_}. @@ -67,42 +58,35 @@ Section proof. Qed. Lemma primitive_load_spec (l : loc) : - atomic_wp (primitive_load #l)%E - ⊤ ⊤ - (λ '(v, q), l ↦{q} v)%I - (λ '(v, q) (_:()), l ↦{q} v)%I - (λ '(v, q) _, v). + <<< ∀ (v : val) q, l ↦{q} v >>> primitive_load #l @ ⊤ + <<< l ↦{q} v, RET v >>>. Proof. iIntros (Q Φ) "? AU". wp_let. - iMod (aupd_acc with "AU") as ((v, q)) "[H↦ [_ Hclose]]"; first solve_ndisj. - wp_load. iMod ("Hclose" $! () with "H↦") as "HΦ". by iApply "HΦ". + iMod (aupd_aacc with "AU") as (v q) "[H↦ [_ Hclose]]". + wp_load. iMod ("Hclose" with "H↦") as "HΦ". by iApply "HΦ". Qed. Lemma primitive_store_spec (l : loc) (e : expr) (w : val) : IntoVal e w → - atomic_wp (primitive_store (#l, e))%E - ⊤ ⊤ - (λ v, l ↦ v)%I - (λ v (_:()), l ↦ w)%I - (λ _ _, #()%V). + <<< ∀ v, l ↦ v >>> primitive_store (#l, e) @ ⊤ + <<< l ↦ w, RET #() >>>. Proof. iIntros (<- Q Φ) "? AU". wp_let. wp_proj. wp_proj. - iMod (aupd_acc with "AU") as (v) "[H↦ [_ Hclose]]"; first solve_ndisj. - wp_store. iMod ("Hclose" $! () with "H↦") as "HΦ". by iApply "HΦ". + iMod (aupd_aacc with "AU") as (v) "[H↦ [_ Hclose]]". + wp_store. iMod ("Hclose" with "H↦") as "HΦ". by iApply "HΦ". Qed. Lemma primitive_cas_spec (l : loc) e1 e2 (w1 w2 : val) : IntoVal e1 w1 → IntoVal e2 w2 → val_is_unboxed w1 → - atomic_wp (primitive_cas (#l, e1, e2))%E - ⊤ ⊤ - (λ v, l ↦ v)%I - (λ v (_:()), if decide (v = w1) then l ↦ w2 else l ↦ v)%I - (λ v _, #(if decide (v = w1) then true else false)%V). + <<< ∀ (v : val), l ↦ v >>> + primitive_cas (#l, e1, e2) @ ⊤ + <<< if decide (v = w1) then l ↦ w2 else l ↦ v, + RET #(if decide (v = w1) then true else false) >>>. Proof. iIntros (<- <- ? Q Φ) "? AU". wp_let. repeat wp_proj. - iMod (aupd_acc with "AU") as (v) "[H↦ [_ Hclose]]"; first solve_ndisj. + iMod (aupd_aacc with "AU") as (v) "[H↦ [_ Hclose]]". destruct (decide (v = w1)) as [<-|Hv]; [wp_cas_suc|wp_cas_fail]; - iMod ("Hclose" $! () with "H↦") as "HΦ"; by iApply "HΦ". + iMod ("Hclose" with "H↦") as "HΦ"; by iApply "HΦ". Qed. Definition primitive_atomic_heap : atomic_heap Σ := diff --git a/theories/heap_lang/lib/increment.v b/theories/heap_lang/lib/increment.v index 4640f7c0167214e2bc091b1c408e6280dae655ae..8f6d9b12c7045bfa0be805b3f807018ec1d81038 100644 --- a/theories/heap_lang/lib/increment.v +++ b/theories/heap_lang/lib/increment.v @@ -19,31 +19,32 @@ Section increment. else "incr" "l". Lemma incr_spec (l: loc) : - atomic_wp (incr #l) - ⊤ ⊤ - (λ (v: Z), aheap.(mapsto) l 1 #v)%I - (λ v (_:()), aheap.(mapsto) l 1 #(v + 1))%I - (λ v _, #v). + <<< ∀ (v : Z), aheap.(mapsto) l 1 #v >>> incr #l @ ⊤ + <<< aheap.(mapsto) l 1 #(v + 1), RET #v >>>. Proof. iIntros (Q Φ) "HQ AU". iLöb as "IH". wp_let. wp_apply (load_spec with "[HQ]"); first by iAccu. (* Prove the atomic shift for load *) iAuIntro. iApply (aacc_aupd_abort with "AU"); first done. iIntros (x) "H↦". - iApply (aacc_intro (_, _) with "[H↦]"); [solve_ndisj|done|iSplit]. + (* FIXME: Oh wow this is bad. *) + iApply (aacc_intro $! ([tele_arg _; _] : [tele (_:val) (_:Qp)]) with "[H↦]"); [solve_ndisj|done|iSplit]. { iIntros "$ !> $ !> //". } - iIntros ([]) "$ !> AU !> HQ". + iIntros "$ !> AU !> HQ". (* Now go on *) wp_let. wp_op. wp_bind (aheap.(cas) _)%I. - wp_apply (cas_spec with "[HQ]"); first done; first by iAccu. + wp_apply (cas_spec with "[HQ]"); [done|iAccu|]. (* Prove the atomic shift for CAS *) iAuIntro. iApply (aacc_aupd with "AU"); first done. iIntros (x') "H↦". - iApply (aacc_intro with "[H↦]"); [solve_ndisj|done|iSplit]. + (* FIXME: Oh wow this is bad. *) + iApply (aacc_intro $! ([tele_arg _] : [tele (_:val)]) with "[H↦]"); [solve_ndisj|simpl; by auto with iFrame|iSplit]. { eauto 10 with iFrame. } - iIntros ([]) "H↦ !>". + (* FIXME: Manual reduction should not be needed. *) + reduction.pm_reduce. + iIntros "H↦ !>". destruct (decide (#x' = #x)) as [[= ->]|Hx]. - - iRight. iExists (). iFrame. iIntros "HΦ !> HQ". + - iRight. iFrame. iIntros "HΦ !> HQ". wp_if. by iApply "HΦ". - iLeft. iFrame. iIntros "AU !> HQ". wp_if. iApply ("IH" with "HQ"). done. @@ -69,9 +70,10 @@ Section increment_client. iAssert (□ WP incr primitive_atomic_heap #l {{ _, True }})%I as "#Aupd". { iAlways. wp_apply (incr_spec with "[]"); first by iAccu. clear x. iAuIntro. iInv nroot as (x) ">H↦". - iApply (aacc_intro with "[H↦]"); [solve_ndisj|done|iSplit]. + (* FIXME: Oh wow this is bad. *) + iApply (aacc_intro $! ([tele_arg _] : [tele (_:Z)]) with "[H↦]"); [solve_ndisj|done|iSplit]. { by eauto 10. } - iIntros ([]) "H↦ !>". iSplitL "H↦"; first by eauto 10. + iIntros "H↦ !>". iSplitL "H↦"; first by eauto 10. (* The continuation: From after the atomic triple to the postcondition of the WP *) done. } diff --git a/theories/program_logic/atomic.v b/theories/program_logic/atomic.v index b8a395fc27f0fec783b494f375b851fae292c7d5..75d33c76346e46c39763312591e634234450a102 100644 --- a/theories/program_logic/atomic.v +++ b/theories/program_logic/atomic.v @@ -1,16 +1,92 @@ From iris.program_logic Require Export weakestpre. From iris.proofmode Require Import tactics classes. From iris.bi.lib Require Export atomic. +From iris.bi Require Import telescopes. Set Default Proof Using "Type". -Definition atomic_wp `{irisG Λ Σ} {A B : Type} +(* This hard-codes the inner mask to be empty, because we have yet to find an +example where we want it to be anything else. *) +Definition atomic_wp `{irisG Λ Σ} {TA TB : tele} (e: expr Λ) (* expression *) - (Eo Em : coPset) (* outside/module masks *) - (α: A → iProp Σ) (* atomic pre-condition *) - (β: A → B → iProp Σ) (* atomic post-condition *) - (f: A → B → val Λ) (* Turn the return data into the return value *) + (Eo : coPset) (* (outer) mask *) + (α: TA → iProp Σ) (* atomic pre-condition *) + (β: TA → TB → iProp Σ) (* atomic post-condition *) + (f: TA → TB → val Λ) (* Turn the return data into the return value *) : iProp Σ := - (∀ Q Φ, Q -∗ atomic_update Eo Em α β (λ x y, Q -∗ Φ (f x y)) -∗ + (∀ Q (Φ : val Λ → iProp Σ), Q -∗ + atomic_update Eo ∅ α β (λ.. x y, Q -∗ Φ (f x y)) -∗ WP e {{ Φ }})%I. (* Note: To add a private postcondition, use - atomic_update α β Eo Em (λ x y, POST x y -∗ Φ (f x y)) *) + atomic_update α β Eo Ei (λ x y, POST x y -∗ Φ (f x y)) *) + +Notation "'<<<' ∀ x1 .. xn , α '>>>' e @ Eo '<<<' ∃ y1 .. yn , β , 'RET' v '>>>'" := + (atomic_wp (TA:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) + (TB:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + e%E + Eo + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, α%I) ..) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, β%I) .. ) + ) .. ) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, v%V) .. ) + ) .. ) + ) + (at level 20, Eo, α, β, v at level 200, x1 binder, xn binder, y1 binder, yn binder, + format "'[hv' '<<<' ∀ x1 .. xn , α '>>>' '/ ' e @ Eo '/' '[ ' '<<<' ∃ y1 .. yn , β , '/' 'RET' v '>>>' ']' ']'") + : stdpp_scope. + +Notation "'<<<' ∀ x1 .. xn , α '>>>' e @ Eo '<<<' β , 'RET' v '>>>'" := + (atomic_wp (TA:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) + (TB:=TeleO) + e%E + Eo + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, α%I) ..) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleO) β%I + ) .. ) + (tele_app (TT:=TeleS (λ x1, .. (TeleS (λ xn, TeleO)) .. )) $ + λ x1, .. (λ xn, + tele_app (TT:=TeleO) v%V + ) .. ) + ) + (at level 20, Eo, α, β, v at level 200, x1 binder, xn binder, + format "'[hv' '<<<' ∀ x1 .. xn , α '>>>' '/ ' e @ Eo '/' '[ ' '<<<' β , '/' 'RET' v '>>>' ']' ']'") + : stdpp_scope. + +Notation "'<<<' α '>>>' e @ Eo '<<<' ∃ y1 .. yn , β , 'RET' v '>>>'" := + (atomic_wp (TA:=TeleO) + (TB:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + e%E + Eo + (tele_app (TT:=TeleO) α%I) + (tele_app (TT:=TeleO) $ + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, β%I) .. )) + (tele_app (TT:=TeleO) $ + tele_app (TT:=TeleS (λ y1, .. (TeleS (λ yn, TeleO)) .. )) + (λ y1, .. (λ yn, v%V) .. )) + ) + (at level 20, Eo, α, β, v at level 200, y1 binder, yn binder, + format "'[hv' '<<<' α '>>>' '/ ' e @ Eo '/' '[ ' '<<<' ∃ y1 .. yn , β , '/' 'RET' v '>>>' ']' ']'") + : stdpp_scope. + +Notation "'<<<' α '>>>' e @ Eo '<<<' β , 'RET' v '>>>'" := + (atomic_wp (TA:=TeleO) + (TB:=TeleO) + e%E + Eo + (tele_app (TT:=TeleO) α%I) + (tele_app (TT:=TeleO) $ tele_app (TT:=TeleO) β%I) + (tele_app (TT:=TeleO) $ tele_app (TT:=TeleO) v%V) + ) + (at level 20, Eo, α, β, v at level 200, + format "'[hv' '<<<' α '>>>' '/ ' e @ Eo '/' '[ ' '<<<' β , '/' 'RET' v '>>>' ']' ']'") + : stdpp_scope.