You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

From iris.proofmode Require Import base proofmode classes.
From iris.base_logic.lib Require Export fancy_updates.
From iris.program_logic Require Export language.
From semantics.pl.program_logic Require Export notation.
From iris.prelude Require Import options.
Import uPred.
Class irisGS (Λ : language) (Σ : gFunctors) := IrisG {
iris_invGS : invGS_gen HasNoLc Σ;
(** The state interpretation is an invariant that should hold in
between each step of reduction. Here [state Λ] is the global state. *)
state_interp : state Λ iProp Σ;
}.
#[export] Existing Instance iris_invGS.
Global Opaque iris_invGS.
Definition wp_pre `{!irisGS Λ Σ} (s : stuckness)
(wp : coPset -d> expr Λ -d> (val Λ -d> iPropO Σ) -d> iPropO Σ) :
coPset -d> expr Λ -d> (val Λ -d> iPropO Σ) -d> iPropO Σ := λ E e1 Φ,
match to_val e1 with
| Some v => |={E}=> Φ v
| None => σ1,
state_interp σ1 ={E,}=
if s is NotStuck then reducible e1 σ1 else True
e2 σ2 κ efs, prim_step e1 σ1 κ e2 σ2 efs
={}= |={,E}=>
efs = [] κ = [] state_interp σ2 wp E e2 Φ
end%I.
Local Instance wp_pre_contractive `{!irisGS Λ Σ} s : Contractive (wp_pre s).
Proof.
rewrite /wp_pre /= => n wp wp' Hwp E e1 Φ.
do 22 (f_contractive || f_equiv).
apply Hwp.
Qed.
Definition wp_def `{!irisGS Λ Σ} := λ (s : stuckness), fixpoint (wp_pre s).
Definition wp_aux : seal (@wp_def). Proof. by eexists. Qed.
Definition wp' := wp_aux.(unseal).
Global Arguments wp' {Λ Σ _}.
Lemma wp_eq `{!irisGS Λ Σ} : wp' = @wp_def Λ Σ _.
Proof. rewrite -wp_aux.(seal_eq) //. Qed.
(* sequential version that allows opening invariants *)
Definition swp_def `{!irisGS Λ Σ} : Swp (iProp Σ) (expr Λ) (val Λ) stuckness := λ s E1 E2 e Φ, (|={E1, }=> wp' s e (λ v, |={, E2}=> Φ v))%I.
Definition swp_aux : seal (@swp_def). Proof. by eexists. Qed.
Definition swp := swp_aux.(unseal).
Global Arguments swp {Λ Σ _}.
Global Existing Instance swp.
Lemma swp_eq `{!irisGS Λ Σ} : swp = @swp_def Λ Σ _.
Proof. rewrite -swp_aux.(seal_eq) //. Qed.
Section wp.
Context `{!irisGS Λ Σ}.
Implicit Types s : stuckness.
Implicit Types P : iProp Σ.
Implicit Types Φ : val Λ iProp Σ.
Implicit Types v : val Λ.
Implicit Types e : expr Λ.
(* Weakest pre *)
Lemma wp'_unfold s E e Φ :
wp' s E e Φ wp_pre s (wp' s) E e Φ.
Proof. rewrite wp_eq. apply (fixpoint_unfold (wp_pre s)). Qed.
Global Instance wp'_ne s E e n :
Proper (pointwise_relation _ (dist n) ==> dist n) (wp' s E e).
Proof.
revert e. induction (lt_wf n) as [n _ IH]=> e Φ Ψ HΦ.
rewrite !wp'_unfold /wp_pre /=.
(* FIXME: figure out a way to properly automate this proof *)
(* FIXME: reflexivity, as being called many times by f_equiv and f_contractive
is very slow here *)
do 22 (f_contractive || f_equiv).
rewrite IH; [done | lia | ]. intros v. eapply dist_lt; done.
Qed.
Global Instance wp'_proper s E e :
Proper (pointwise_relation _ () ==> ()) (wp' s E e).
Proof.
by intros Φ Φ' ?; apply equiv_dist=>n; apply wp'_ne=>v; apply equiv_dist.
Qed.
Global Instance wp'_contractive s E e n :
TCEq (to_val e) None
Proper (pointwise_relation _ (dist_later n) ==> dist n) (wp' s E e).
Proof.
intros He Φ Ψ HΦ. rewrite !wp'_unfold /wp_pre He /=.
do 23 (f_contractive || f_equiv).
by do 4 f_equiv.
Qed.
Lemma wp'_value_fupd' s E Φ v : wp' s E (of_val v) Φ |={E}=> Φ v.
Proof. rewrite wp'_unfold /wp_pre to_of_val. auto. Qed.
Lemma wp'_strong_mono s1 s2 E1 E2 e Φ Ψ :
s1 s2 E1 E2
wp' s1 E1 e Φ - ( v, Φ v ={E2}= Ψ v) - wp' s2 E2 e Ψ.
Proof.
iIntros (? HE) "H HΦ". iLöb as "IH" forall (e E1 E2 HE Φ Ψ).
rewrite !wp'_unfold /wp_pre /=.
destruct (to_val e) as [v|] eqn:?.
{ iApply ("" with "[> -]"). by iApply (fupd_mask_mono E1 _). }
iIntros (σ1) "Hσ".
iMod (fupd_mask_subseteq E1) as "Hclose"; first done.
iMod ("H" with "[$]") as "[% H]".
iModIntro. iSplit; [by destruct s1, s2|]. iIntros (e2 σ2 κ efs Hstep).
iMod ("H" with "[//]") as "H". iIntros "!> !>". iMod "H". iModIntro.
iMod "H" as "($ & $ & $ & H)".
iMod "Hclose" as "_". iModIntro.
iApply ("IH" with "[//] H HΦ").
Qed.
Lemma fupd_wp' s E e Φ : (|={E}=> wp' s E e Φ) wp' s E e Φ.
Proof.
rewrite wp'_unfold /wp_pre. iIntros "H". destruct (to_val e) as [v|] eqn:?.
{ by iMod "H". }
iIntros (σ1) "Hσ1". iMod "H". by iApply "H".
Qed.
Lemma wp'_fupd s E e Φ : wp' s E e (λ v, |={E}=> Φ v) wp' s E e Φ.
Proof. iIntros "H". iApply (wp'_strong_mono s s E with "H"); auto. Qed.
Lemma wp'_bind K `{!LanguageCtx K} s E e Φ :
wp' s E e (λ v, wp' s E (K (of_val v)) Φ) wp' s E (K e) Φ.
Proof.
iIntros "H". iLöb as "IH" forall (E e Φ). rewrite wp'_unfold /wp_pre.
destruct (to_val e) as [v|] eqn:He.
{ apply of_to_val in He as <-. by iApply fupd_wp'. }
rewrite wp'_unfold /wp_pre fill_not_val /=; [|done].
iIntros (σ1) "Hσ". iMod ("H" with "[$]") as "[% H]".
iModIntro; iSplit.
{ destruct s; eauto using reducible_fill. }
iIntros (e2 σ2 κ efs Hstep).
destruct (fill_step_inv e σ1 κ e2 σ2 efs) as (e2'&->&?); auto.
iMod ("H" $! e2' σ2 κ efs with "[//]") as "H". iIntros "!>!>".
iMod "H". iModIntro. iMod "H" as "($ & $ & $ & H)". iModIntro. by iApply "IH".
Qed.
Lemma wp'_step_fupd s E1 E2 e P Φ :
TCEq (to_val e) None E2 E1
(|={E1}[E2]=> P) - wp' s E2 e (λ v, P ={E1}= Φ v) - wp' s E1 e Φ.
Proof.
iIntros (?%TCEq_eq ?) "HR H".
rewrite !wp'_unfold /wp_pre /=.
destruct (to_val e) as [v|] eqn:He.
{ apply of_to_val in He as <-. done. }
iIntros (σ1) "Hσ".
iMod "HR".
iMod ("H" with "[$]") as "[% H]".
iModIntro; iSplit.
{ destruct s; eauto. }
iIntros (e2 σ2 κ efs Hstep).
iMod ("H" $! _ _ _ with "[//]") as "H". iIntros "!>!>!>".
iMod "H". iMod "H" as "($ & $ & $ & H)". iMod "HR". iModIntro.
iApply (wp'_strong_mono with "H [HR]"); [done | done | ].
iIntros (v) "". by iApply "".
Qed.
End wp.
Section swp.
Context `{!irisGS Λ Σ}.
Implicit Types s : stuckness.
Implicit Types P : iProp Σ.
Implicit Types Φ : val Λ iProp Σ.
Implicit Types v : val Λ.
Implicit Types e : expr Λ.
(* Weakest pre *)
Global Instance wp_ne s E1 E2 e n :
Proper (pointwise_relation _ (dist n) ==> dist n) (wp s E1 E2 e).
Proof.
intros ???.
rewrite /wp swp_eq /swp_def /=.
do 2 f_equiv. intros ?. f_equiv. done.
Qed.
Global Instance wp_proper s E1 E2 e :
Proper (pointwise_relation _ () ==> ()) (wp s E1 E2 e).
Proof.
intros ???. rewrite /wp swp_eq /swp_def /=.
do 2 f_equiv. intros ?. f_equiv. done.
Qed.
Lemma wp_value_fupd' s E1 E2 Φ v : wp s E1 E2 (of_val v) Φ |={E1, E2}=> Φ v.
Proof.
rewrite /wp swp_eq /swp_def wp'_value_fupd'.
iSplit.
- iIntros "H". iMod "H". iMod "H". iMod "H". done.
- iIntros "H". iMod (fupd_mask_subseteq ) as "Hcl"; first set_solver.
iModIntro. iModIntro. iMod "Hcl" as "_". done.
Qed.
Lemma wp_strong_mono s1 s2 E1 E2 E3 e Φ Ψ :
s1 s2
wp s1 E1 E2 e Φ - ( v, Φ v ={E2, E3}= Ψ v) - wp s2 E1 E3 e Ψ.
Proof.
iIntros (?) "H HΦ".
rewrite /wp swp_eq /swp_def.
iMod "H". iModIntro.
iApply (wp'_strong_mono _ _ with "H [HΦ]"); [done | done | ].
iIntros (v) "H". iModIntro. iMod "H". by iApply "".
Qed.
Lemma fupd_wp s E1 E2 E3 e Φ : (|={E1, E2}=> wp s E2 E3 e Φ) wp s E1 E3 e Φ.
Proof.
rewrite /wp swp_eq /swp_def. iIntros "H". iApply fupd_wp'.
iMod "H". iMod "H". iModIntro. iModIntro. done.
Qed.
Lemma wp_fupd' s E1 E2 e Φ : wp s E1 E1 e (λ v, |={E1, E2}=> Φ v) wp s E1 E2 e Φ.
Proof. iIntros "H". iApply (wp_strong_mono s s E1 E1 with "H"); auto. Qed.
Lemma wp_fupd s E1 E2 e Φ : wp s E1 E2 e (λ v, |={E2}=> Φ v) wp s E1 E2 e Φ.
Proof. iIntros "H". iApply (wp_strong_mono s s E1 E2 with "H"); auto. Qed.
Lemma wp_bind K `{!LanguageCtx K} s E1 E2 E3 e Φ :
wp s E1 E2 e (λ v, wp s E2 E3 (K (of_val v)) Φ) wp s E1 E3 (K e) Φ.
Proof.
iIntros "H".
rewrite /wp swp_eq /swp_def. iMod "H". iApply wp'_bind.
iModIntro. iApply (wp'_strong_mono with "H"); [done | done | ].
iIntros (v) "H". iMod "H". iMod "H". done.
Qed.
Lemma wp_step_fupd s E1 E2 E3 e P Φ :
TCEq (to_val e) None
(|={E1}[E2]=> P) - wp s E2 E2 e (λ v, P ={E1, E3}= Φ v) - wp s E1 E3 e Φ.
Proof.
iIntros (?) "HR H".
rewrite /wp swp_eq /swp_def.
iMod "HR". iMod "H". iModIntro.
iApply (wp'_step_fupd _ _ (|={E2, E1}=> P) with "[HR] [H]"); [done | | ].
{ iApply (step_fupd_intro ); done. }
iApply (wp'_strong_mono with "H"); [done | done | ].
iIntros (v) "H1 !> H2 !>".
iMod "H1". iMod "H2". by iMod ("H1" with "H2").
Qed.
(** * Derived rules *)
Lemma wp_mono s E1 E2 e Φ Ψ : ( v, Φ v Ψ v) WP e @ s; E1; E2 {{ Φ }} WP e @ s; E1; E2 {{ Ψ }}.
Proof.
iIntros (HΦ) "H"; iApply (wp_strong_mono with "H"); auto.
iIntros (v) "?". by iApply HΦ.
Qed.
Lemma wp_stuck_mono s1 s2 E1 E2 e Φ :
s1 s2 WP e @ s1; E1; E2 {{ Φ }} WP e @ s2; E1; E2 {{ Φ }}.
Proof. iIntros (?) "H". iApply (wp_strong_mono with "H"); auto. Qed.
Lemma wp_stuck_weaken s E1 E2 e Φ :
WP e @ s; E1; E2 {{ Φ }} WP e @ E1; E2 ?{{ Φ }}.
Proof. apply wp_stuck_mono. by destruct s. Qed.
Global Instance wp_mono' s E1 E2 e :
Proper (pointwise_relation _ () ==> ()) (wp (PROP:=iProp Σ) s E1 E2 e).
Proof. by intros Φ Φ' ?; apply wp_mono. Qed.
Global Instance wp_flip_mono' s E1 E2 e :
Proper (pointwise_relation _ (flip ()) ==> (flip ())) (wp (PROP:=iProp Σ) s E1 E2 e).
Proof. by intros Φ Φ' ?; apply wp_mono. Qed.
Lemma wp_value_fupd s E1 E2 Φ e v : IntoVal e v WP e @ s; E1; E2 {{ Φ }} |={E1, E2}=> Φ v.
Proof. intros <-. by apply wp_value_fupd'. Qed.
Lemma wp_value' s E Φ v : Φ v WP (of_val v) @ s; E {{ Φ }}.
Proof. rewrite wp_value_fupd'. auto. Qed.
Lemma wp_value s E Φ e v : IntoVal e v Φ v WP e @ s; E {{ Φ }}.
Proof. intros <-. apply wp_value'. Qed.
Lemma wp_frame_l s E1 E2 e Φ R : R WP e @ s; E1; E2 {{ Φ }} WP e @ s; E1; E2 {{ v, R Φ v }}.
Proof. iIntros "[? H]". iApply (wp_strong_mono with "H"); auto with iFrame. Qed.
Lemma wp_frame_r s E1 E2 e Φ R : WP e @ s; E1; E2 {{ Φ }} R WP e @ s; E1; E2 {{ v, Φ v R }}.
Proof. iIntros "[H ?]". iApply (wp_strong_mono with "H"); auto with iFrame. Qed.
Lemma wp_frame_step_l s E1 E2 E3 e Φ R :
TCEq (to_val e) None
(|={E1}[E2]=> R) WP e @ s; E2; E2 {{ v, |={E1, E3}=> Φ v }} WP e @ s; E1; E3 {{ v, R Φ v }}.
Proof.
iIntros (?) "[Hu Hwp]". iApply (wp_step_fupd with "Hu"); try done.
iApply (wp_mono with "Hwp"). iIntros (?) "Hf $". iApply "Hf".
Qed.
Lemma wp_frame_step_r s E1 E2 E3 e Φ R :
TCEq (to_val e) None
WP e @ s; E2; E2 {{ v, |={E1, E3}=> Φ v }} (|={E1}[E2]=> R) WP e @ s; E1; E3 {{ v, Φ v R }}.
Proof.
rewrite [(WP _ @ _; _ {{ _ }} _)%I]comm; setoid_rewrite (comm _ _ R).
apply wp_frame_step_l.
Qed.
Lemma wp_frame_step_l' s E1 E2 e Φ R :
TCEq (to_val e) None E1 E2 R WP e @ s; E1; E2 {{ Φ }} WP e @ s; E1; E2 {{ v, R Φ v }}.
Proof.
iIntros (??) "[??]". iApply (wp_frame_step_l s E1 E1 E2).
iFrame. iSplitR; first eauto. iApply (wp_strong_mono with "[$]"); first done.
iIntros (v) "?". iMod (fupd_mask_subseteq E1) as "Hcl"; first done. iModIntro. iMod "Hcl". eauto.
Qed.
Lemma wp_frame_step_r' s E1 E2 e Φ R :
TCEq (to_val e) None E1 E2 WP e @ s; E1; E2 {{ Φ }} R WP e @ s; E1; E2 {{ v, Φ v R }}.
Proof.
rewrite [(WP _ @ _; _ {{ _ }} _)%I]comm; setoid_rewrite (comm _ _ R).
apply wp_frame_step_l'.
Qed.
Lemma wp_wand s E1 E2 e Φ Ψ :
WP e @ s; E1; E2 {{ Φ }} - ( v, Φ v - Ψ v) - WP e @ s; E1; E2 {{ Ψ }}.
Proof.
iIntros "Hwp H". iApply (wp_strong_mono with "Hwp"); auto.
iIntros (?) "?". by iApply "H".
Qed.
Lemma wp_wand_l s E1 E2 e Φ Ψ :
( v, Φ v - Ψ v) WP e @ s; E1; E2 {{ Φ }} WP e @ s; E1; E2 {{ Ψ }}.
Proof. iIntros "[H Hwp]". iApply (wp_wand with "Hwp H"). Qed.
Lemma wp_wand_r s E1 E2 e Φ Ψ :
WP e @ s; E1; E2 {{ Φ }} ( v, Φ v - Ψ v) WP e @ s; E1; E2 {{ Ψ }}.
Proof. iIntros "[Hwp H]". iApply (wp_wand with "Hwp H"). Qed.
Lemma wp_frame_wand s E1 E2 e Φ R :
R - WP e @ s; E1; E2 {{ v, R - Φ v }} - WP e @ s; E1; E2 {{ Φ }}.
Proof.
iIntros "HR HWP". iApply (wp_wand with "HWP").
iIntros (v) "". by iApply "".
Qed.
Lemma wp_bind' K `{!LanguageCtx K} s E1 E2 e Φ :
wp s E1 E1 e (λ v, wp s E1 E2 (K (of_val v)) Φ) wp s E1 E2 (K e) Φ.
Proof. iApply wp_bind. Qed.
End swp.
(** Proofmode class instances *)
Section proofmode_classes.
Context `{!irisGS Λ Σ}.
Implicit Types P Q : iProp Σ.
Implicit Types Φ : val Λ iProp Σ.
Implicit Types v : val Λ.
Implicit Types e : expr Λ.
Global Instance frame_wp p s E1 E2 e R Φ Ψ :
( v, Frame p R (Φ v) (Ψ v))
Frame p R (WP e @ s; E1; E2 {{ Φ }}) (WP e @ s; E1; E2 {{ Ψ }}) | 2.
Proof. rewrite /Frame=> HR. rewrite wp_frame_l. apply wp_mono, HR. Qed.
Global Instance is_except_0_wp s E1 E2 e Φ : IsExcept0 (WP e @ s; E1; E2 {{ Φ }}).
Proof. by rewrite /IsExcept0 -{2}(fupd_wp _ E1 E1) -except_0_fupd -fupd_intro. Qed.
Global Instance elim_modal_bupd_wp p s E1 E2 e P Φ :
ElimModal True p false (|==> P) P (WP e @ s; E1; E2 {{ Φ }}) (WP e @ s; E1; E2 {{ Φ }}).
Proof.
by rewrite /ElimModal intuitionistically_if_elim
(bupd_fupd E1) fupd_frame_r wand_elim_r fupd_wp.
Qed.
Global Instance elim_modal_fupd_wp p s E1 E2 e P Φ :
ElimModal True p false (|={E1}=> P) P (WP e @ s; E1; E2 {{ Φ }}) (WP e @ s; E1; E2 {{ Φ }}).
Proof.
by rewrite /ElimModal intuitionistically_if_elim
fupd_frame_r wand_elim_r fupd_wp.
Qed.
Global Instance elim_modal_fupd_wp_ne p s E1 E2 E3 e P Φ :
ElimModal True p false
(|={E1,E2}=> P) P
(WP e @ s; E1; E3 {{ Φ }}) (WP e @ s; E2; E3 {{ Φ }})%I | 100.
Proof.
intros ?. rewrite intuitionistically_if_elim fupd_frame_r wand_elim_r.
rewrite fupd_wp //.
Qed.
Global Instance add_modal_fupd_wp s E1 E2 e P Φ :
AddModal (|={E1}=> P) P (WP e @ s; E1; E2 {{ Φ }}).
Proof. by rewrite /AddModal fupd_frame_r wand_elim_r fupd_wp. Qed.
Global Instance elim_acc_wp_nonatomic {X} E0 E1 E2 α β γ e s Φ :
ElimAcc (X:=X) True (fupd E1 E0) (fupd E2 E2)
α β γ (WP e @ s; E1; E2 {{ Φ }})
(λ x, WP e @ s; E0; E2 {{ v, |={E2}=> β x (γ x -? Φ v) }})%I.
Proof.
iIntros (_) "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
iApply wp_fupd.
iApply (wp_wand with "(Hinner Hα)").
iIntros (v) ">[Hβ HΦ]". iApply "". by iApply "Hclose".
Qed.
End proofmode_classes.