Library iris.proofmode.pstepshifts

From iris.proofmode Require Import coq_tactics spec_patterns pviewshifts.
From iris.proofmode Require Export tactics.
From iris.program_logic Require Export pviewshifts pstepshifts.
Import uPred.

Section psvs.
Context {Λ : language} {Σ : iFunctor}.
Implicit Types P Q : iProp Λ Σ.

Global Instance or_split_psvs E1 E2 P Q1 Q2 :
  FromOr P Q1 Q2 FromOr (|={E1,E2}=>> P) (|={E1,E2}=>> Q1) (|={E1,E2}=>> Q2).
Proof. rewrite /FromOr=><-. apply or_elim; apply psvs_mono; auto with I. Qed.
Global Instance exists_split_psvs {A} E1 E2 P (Φ : A iProp Λ Σ) :
  FromExist P Φ FromExist (|={E1,E2}=>> P) (λ a, |={E1,E2}=>> Φ a)%I.
Proof.
  rewrite /FromExist=><-. apply exist_elima. by rewrite -(exist_intro a).
Qed.
Global Instance aframe_psvs E1 E2 R P Q :
  AffineP R
  Frame R P Q
  Frame R (|={E1,E2}=>> P) (|={E1,E2}=>> Q)%I.
Proof. rewrite /FrameHA <-. rewrite -(affine_affine R). by rewrite psvs_frame_l. Qed.

Global Instance fsa_split_psvs E P :
  IsAFSA (|={E}=>> P)%I E psvs_fsa True (λ _, P).
Proof. split. done. apply _. Qed.

Lemma tac_psvs_elim Δ Δ' E1 E2 E3 i p P Q :
  envs_lookup i Δ = Some (p, |={E1,E2}=>> P)%I
  envs_replace i p false (Esnoc Enil i P) Δ = Some Δ'
  (envs_delete i p Δ (envs_delete i p Δ))
  E2 E1 E3
  (Δ' (|={E2,E3}=> Q)) Δ |={E1,E3}=>> Q.
Proof.
  intros ?? Haff ? HQ. rewrite envs_replace_sound_affine //; simpl. destruct p.
  - rewrite relevant_elim right_id psvs_frame_r affine_elim wand_elim_r HQ psvs_pvs //=.
  - by rewrite right_id psvs_frame_r affine_elim wand_elim_r HQ psvs_pvs.
Qed.

Lemma tac_psvs_timeless Δ Δ' E1 E2 i P Q :
  envs_lookup i Δ = Some (false, P)%I TimelessP P
  envs_simple_replace i false (Esnoc Enil i P) Δ = Some Δ'
  (Δ' |={E1,E2}=>> Q) Δ (|={E1,E2}=>> Q).
Proof.
  intros ??? HQ.
  etransitivity; last apply (pvs_psvs E1 E1 E2); last set_solver.
  eapply tac_pvs_timeless; eauto.
Qed.

End psvs.

Tactic Notation "iPsvsCore" constr(H) :=
  match goal with
  | |- _ |={_,_}=>> _
    eapply tac_psvs_elim with _ _ H _ _;
      [env_cbv; reflexivity || fail "iPsvs:" H "not found"
      |env_cbv; reflexivity
      |env_cbv; apply affine_intro; first apply _; auto || fail "iPsvs: couldn't prove ctxt affine."
      |try (rewrite (idemp_L (∪)); reflexivity)|]
  end.

Tactic Notation "iPsvsCore" constr(H) constr(HP) :=
  match goal with
  | |- _ |={_,_}=>> _
    eapply tac_psvs_elim with _ _ H _ HP;
      [env_cbv; reflexivity || fail "iPsvs:" H "not found"
      |env_cbv; reflexivity
      |env_cbv; apply affine_intro; first apply _; auto || fail "iPsvs: couldn't prove ctxt affine."
      |try (rewrite (idemp_L (∪)); reflexivity)|]
  end.

Tactic Notation "iPsvs" open_constr(lem) :=
  iDestructCore lem as (fun HiPsvsCore H; last iDestruct H as "?").