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.

149 lines
5.7 KiB

11 months ago
(** The "lifting lemmas" in this file serve to lift the rules of the operational
semantics to the program logic. *)
From iris.proofmode Require Import proofmode.
From semantics.pl.program_logic Require Export sequential_wp.
From iris.prelude Require Import options.
Section lifting.
Context `{!irisGS Λ Σ}.
Implicit Types s : stuckness.
Implicit Types v : val Λ.
Implicit Types e : expr Λ.
Implicit Types σ : state Λ.
Implicit Types P Q : iProp Σ.
Implicit Types Φ : val Λ iProp Σ.
Local Hint Resolve reducible_no_obs_reducible : core.
Lemma wp_lift_step_fupd s E1 E2 Φ e1 :
to_val e1 = None
(|={E1, }=> σ1, state_interp σ1 ={}=
if s is NotStuck then reducible e1 σ1 else True
e2 σ2 κ efs, prim_step e1 σ1 κ e2 σ2 efs
={}= efs = [] κ = [] state_interp σ2 WP e2 @ s; ; E2 {{ Φ }})
WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
rewrite /wp swp_eq /swp_def wp'_unfold /wp_pre=>->.
iIntros ">Hs !>" (σ1). iIntros "Hstate".
iDestruct ("Hs" with "Hstate") as ">($ & Hs)".
iIntros "!>" (e2 σ2 κ efs Hstep). iApply (step_fupd_wand with "(Hs [//]) []").
iIntros "(-> & -> & $ & >Hwp)". eauto.
Qed.
(*
Lemma wp_lift_stuck E1 E2 Φ e :
to_val e = None
( σ, state_interp σ ={E1,}= stuck e σ)
WP e @ E1; E2 ?{{ Φ }}.
Proof.
rewrite /wp swp_eq /swp_def wp'_unfold /wp_pre=>->. iIntros "H" (σ1). "Hσ".
iMod ("H" with "Hσ") as %[? Hirr]. iModIntro. iSplit; first done.
iIntros (e2 σ2 efs ?). by case: (Hirr κ e2 σ2 efs).
Qed.
*)
(** Derived lifting lemmas. *)
Lemma wp_lift_step s E1 E2 Φ e1 :
to_val e1 = None
(|={E1, }=> σ1, state_interp σ1 ={}=
if s is NotStuck then reducible e1 σ1 else True
e2 σ2 κ efs, prim_step e1 σ1 κ e2 σ2 efs ={}=
efs = [] κ = [] state_interp σ2
WP e2 @ s; ; E2 {{ Φ }})
WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
iIntros (?) "H". iApply wp_lift_step_fupd; [done|].
iMod "H" as "H". iIntros "!>" (σ1) "Hσ". iMod ("H" with "Hσ") as "($ & Hstep)".
iIntros "!> * % !> !>". by iApply "Hstep".
Qed.
Lemma wp_lift_pure_step `{!Inhabited (state Λ)} s E1 E2 E' Φ e1 :
( σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None)
( κ σ1 e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs κ = [] σ2 = σ1 efs = [])
(|={E1}[E']=> κ e2 efs σ, prim_step e1 σ κ e2 σ efs WP e2 @ s; E1; E2 {{ Φ }})
WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
iIntros (Hsafe Hstep) "H". iApply wp_lift_step.
{ specialize (Hsafe inhabitant). destruct s; eauto using reducible_not_val. }
iMod "H" as "H".
iApply fupd_mask_intro; first set_solver. iIntros "Hclose".
iIntros (σ1) "Hσ !>". iSplit.
{ iPureIntro. destruct s; done. }
iNext. iIntros (e2 σ2 κ efs ?).
destruct (Hstep κ σ1 e2 σ2 efs) as (-> & <- & ->); auto.
iFrame "Hσ". iSplitR; first done. iSplitR; first done.
iModIntro.
iMod "Hclose". iMod "H". by iApply "H".
Qed.
(*
Lemma wp_lift_pure_stuck `{!Inhabited (state Λ)} E Φ e :
( σ, stuck e σ)
True WP e @ E ?{{ Φ }}.
Proof.
iIntros (Hstuck) "_". iApply wp_lift_stuck.
- destruct(to_val e) as [v|] eqn:He; last done.
rewrite -He. by case: (Hstuck inhabitant).
- iIntros (σ ns κs nt) "_". iApply fupd_mask_intro; auto with set_solver.
Qed.
*)
Lemma wp_lift_step_fupd_nomask {s E1 E2 E3 Φ} e1 :
to_val e1 = None
( σ1, state_interp σ1 ={E1}=
if s is NotStuck then reducible e1 σ1 else True
e2 σ2 κ efs, prim_step e1 σ1 κ e2 σ2 efs ={E1}[E3]=
state_interp σ2 efs = [] κ = []
WP e2 @ s; E1; E2 {{ Φ }})
WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
iIntros (?) "H".
iApply (wp_lift_step_fupd s E1 _ _ e1)=>//.
iApply fupd_mask_intro; first set_solver. iIntros "Hcl".
iIntros (σ1) "Hσ1". iMod "Hcl" as "_".
iMod ("H" with "Hσ1") as "($ & H)".
iApply fupd_mask_intro; first set_solver.
iIntros "Hclose" (e2 σ2 κ efs ?). iMod "Hclose" as "_".
iMod ("H" $! e2 σ2 κ efs with "[#]") as "H"; [done|].
iApply fupd_mask_intro; first set_solver. iIntros "Hclose !>".
iMod "Hclose" as "_". iMod "H" as "($ & $ & $ & ?)".
iApply fupd_mask_intro; first set_solver. iIntros "Hcl".
iMod "Hcl" as "_". done.
Qed.
Lemma wp_lift_pure_det_step `{!Inhabited (state Λ)} {s E1 E2 E' Φ} e1 e2 :
( σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None)
( σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs'
κ = [] σ2 = σ1 e2' = e2 efs' = [])
(|={E1}[E']=> WP e2 @ s; E1; E2 {{ Φ }}) WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
iIntros (? Hpuredet) "H". iApply (wp_lift_pure_step s E1 E2 E'); try done.
{ naive_solver. }
iApply (step_fupd_wand with "H"); iIntros "H".
iIntros (κ e' efs' σ (_&?&->&?)%Hpuredet); auto.
Qed.
Lemma wp_pure_step_fupd `{!Inhabited (state Λ)} s E1 E2 E' e1 e2 φ n Φ :
PureExec φ n e1 e2
φ
(|={E1}[E']=>^n WP e2 @ s; E1; E2 {{ Φ }}) WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
iIntros (Hexec Hφ) "Hwp". specialize (Hexec Hφ).
iInduction Hexec as [e|n e1 e2 e3 [Hsafe ?]] "IH"; simpl; first done.
iApply wp_lift_pure_det_step.
- intros σ. specialize (Hsafe σ). destruct s; eauto using reducible_not_val.
- done.
- by iApply (step_fupd_wand with "Hwp").
Qed.
Lemma wp_pure_step_later `{!Inhabited (state Λ)} s E1 E2 e1 e2 φ n Φ :
PureExec φ n e1 e2
φ
^n WP e2 @ s; E1; E2 {{ Φ }} WP e1 @ s; E1; E2 {{ Φ }}.
Proof.
intros Hexec ?. rewrite -wp_pure_step_fupd //. clear Hexec.
induction n as [|n IH]; by rewrite //= -step_fupd_intro // IH.
Qed.
End lifting.