diff --git a/proofmode/classes.v b/proofmode/classes.v index a88e3daf7589a50410093919cddc839a0d754576..c25740c0c9c1663c832a2ac94b72beea773ae048 100644 --- a/proofmode/classes.v +++ b/proofmode/classes.v @@ -312,4 +312,7 @@ Proof. rewrite /IntoExist=> HP ?. by rewrite HP later_exist. Qed. Global Instance into_exist_always {A} P (Φ : A → uPred M) : IntoExist P Φ → IntoExist (□ P) (λ a, □ (Φ a))%I. Proof. rewrite /IntoExist=> HP. by rewrite HP always_exist. Qed. + +Class TimelessElim (Q : uPred M) := + timeless_elim `{!TimelessP P} R : (R ⊢ Q) → ▷ P ★ (P -★ R) ⊢ Q. End classes. diff --git a/proofmode/coq_tactics.v b/proofmode/coq_tactics.v index 1ac516bbdb8313132fb8a765750b5d36be08700b..3b3bb0f129fda78c3c36315d29df4e322e46078a 100644 --- a/proofmode/coq_tactics.v +++ b/proofmode/coq_tactics.v @@ -375,6 +375,16 @@ Proof. by rewrite right_id always_and_sep_l' wand_elim_r HQ. Qed. +Lemma tac_timeless Δ Δ' i p P Q : + TimelessElim Q → + envs_lookup i Δ = Some (p, ▷ P)%I → TimelessP P → + envs_simple_replace i p (Esnoc Enil i P) Δ = Some Δ' → + (Δ' ⊢ Q) → Δ ⊢ Q. +Proof. + intros ???? HQ. rewrite envs_simple_replace_sound //; simpl. + rewrite always_if_later right_id. by apply timeless_elim. +Qed. + (** * Always *) Lemma tac_always_intro Δ Q : envs_persistent Δ = true → (Δ ⊢ Q) → Δ ⊢ □ Q. Proof. intros. by apply: always_intro. Qed. diff --git a/proofmode/pviewshifts.v b/proofmode/pviewshifts.v index e919ea13ed79a7e39039e44bd2c0b6a4d6ae6c57..8695abb15ce6943967504f3e8450b25da8c085c0 100644 --- a/proofmode/pviewshifts.v +++ b/proofmode/pviewshifts.v @@ -30,6 +30,12 @@ Global Instance into_wand_pvs E1 E2 R P Q : IntoWand R P Q → IntoWand R (|={E1,E2}=> P) (|={E1,E2}=> Q) | 100. Proof. rewrite /IntoWand=>->. apply wand_intro_l. by rewrite pvs_wand_r. Qed. +Global Instance timeless_elim_pvs E1 E2 Q : TimelessElim (|={E1,E2}=> Q). +Proof. + intros P ? R HR. rewrite (pvs_timeless E1 P) pvs_frame_r. + by rewrite wand_elim_r HR pvs_trans; last set_solver. +Qed. + Class IsFSA {A} (P : iProp Λ Σ) (E : coPset) (fsa : FSA Λ Σ A) (fsaV : Prop) (Φ : A → iProp Λ Σ) := { is_fsa : P ⊣⊢ fsa E Φ; @@ -48,6 +54,12 @@ Global Instance to_assert_pvs {A} P Q E (fsa : FSA Λ Σ A) fsaV Φ : Proof. intros. by rewrite /IntoAssert pvs_frame_r wand_elim_r (is_fsa Q) fsa_pvs_fsa. Qed. +Global Instance timeless_elim_fsa {A} Q E (fsa : FSA Λ Σ A) fsaV Φ : + IsFSA Q E fsa fsaV Φ → TimelessElim Q. +Proof. + intros ? P ? R. rewrite (is_fsa Q) -{2}fsa_pvs_fsa. intros <-. + by rewrite (pvs_timeless _ P) pvs_frame_r wand_elim_r. +Qed. Lemma tac_pvs_intro Δ E1 E2 Q : E1 = E2 → (Δ ⊢ Q) → Δ ⊢ |={E1,E2}=> Q. Proof. intros -> ->. apply pvs_intro. Qed. @@ -74,26 +86,6 @@ Proof. intros ? -> ??. rewrite (is_fsa Q) -fsa_pvs_fsa. eapply tac_pvs_elim; set_solver. Qed. - -Lemma tac_pvs_timeless Δ Δ' E1 E2 i p P Q : - envs_lookup i Δ = Some (p, ▷ P)%I → TimelessP P → - envs_simple_replace i p (Esnoc Enil i P) Δ = Some Δ' → - (Δ' ={E1,E2}=> Q) → Δ ={E1,E2}=> Q. -Proof. - intros ??? HQ. rewrite envs_simple_replace_sound //; simpl. - rewrite always_if_later (pvs_timeless E1 (□?_ P)%I) pvs_frame_r. - by rewrite right_id wand_elim_r HQ pvs_trans; last set_solver. -Qed. - -Lemma tac_pvs_timeless_fsa {A} (fsa : FSA Λ Σ A) fsaV Δ Δ' E i p P Q Φ : - IsFSA Q E fsa fsaV Φ → - envs_lookup i Δ = Some (p, ▷ P)%I → TimelessP P → - envs_simple_replace i p (Esnoc Enil i P) Δ = Some Δ' → - (Δ' ⊢ fsa E Φ) → Δ ⊢ Q. -Proof. - intros ????. rewrite (is_fsa Q) -fsa_pvs_fsa. - eauto using tac_pvs_timeless. -Qed. End pvs. Tactic Notation "iPvsIntro" := apply tac_pvs_intro; first try fast_done. @@ -161,26 +153,5 @@ Tactic Notation "iPvs" open_constr(H) "as" "(" simple_intropattern(x1) iDestructHelp H as (fun H => iPvsCore H; last iDestruct H as ( x1 x2 x3 x4 x5 x6 x7 x8 ) pat). -Tactic Notation "iTimeless" constr(H) := - match goal with - | |- _ ⊢ |={_,_}=> _ => - eapply tac_pvs_timeless with _ H _ _; - [env_cbv; reflexivity || fail "iTimeless:" H "not found" - |let P := match goal with |- TimelessP ?P => P end in - apply _ || fail "iTimeless: " P "not timeless" - |env_cbv; reflexivity|simpl] - | |- _ => - eapply tac_pvs_timeless_fsa with _ _ _ _ H _ _ _; - [let P := match goal with |- IsFSA ?P _ _ _ _ => P end in - apply _ || fail "iTimeless: " P "not a pvs" - |env_cbv; reflexivity || fail "iTimeless:" H "not found" - |let P := match goal with |- TimelessP ?P => P end in - apply _ || fail "iTimeless: " P "not timeless" - |env_cbv; reflexivity|simpl] - end. - -Tactic Notation "iTimeless" constr(H) "as" constr(Hs) := - iTimeless H; iDestruct H as Hs. - Hint Extern 2 (of_envs _ ⊢ _) => match goal with |- _ ⊢ (|={_}=> _)%I => iPvsIntro end. diff --git a/proofmode/tactics.v b/proofmode/tactics.v index 8e6a504daeeecd6610e9e955fc0f37e0fa613d72..3901386c43ad909a114baeac44a5608ad5a6b1fd 100644 --- a/proofmode/tactics.v +++ b/proofmode/tactics.v @@ -501,6 +501,15 @@ Tactic Notation "iNext":= |let P := match goal with |- FromLater ?P _ => P end in apply _ || fail "iNext:" P "does not contain laters"|]. +Tactic Notation "iTimeless" constr(H) := + eapply tac_timeless with _ H _ _; + [let Q := match goal with |- TimelessElim ?Q => Q end in + apply _ || fail "iTimeless: cannot eliminate later in goal" Q + |env_cbv; reflexivity || fail "iTimeless:" H "not found" + |let P := match goal with |- TimelessP ?P => P end in + apply _ || fail "iTimeless: " P "not timeless" + |env_cbv; reflexivity|]. + (** * Introduction tactic *) Local Tactic Notation "iIntro" "(" simple_intropattern(x) ")" := first [ (* (∀ _, _) *) apply tac_forall_intro; intros x