Commit 8c844e32 authored by Robbert Krebbers's avatar Robbert Krebbers

Fix issue #56.

parent 611995ee
...@@ -38,12 +38,17 @@ Context management ...@@ -38,12 +38,17 @@ Context management
the resulting goal. the resulting goal.
- `iPoseProof pm_trm as "H"` : put `pm_trm` into the context as a new hypothesis - `iPoseProof pm_trm as "H"` : put `pm_trm` into the context as a new hypothesis
`H`. `H`.
- `iAssert P with "spat" as "ipat"` : create a new goal with conclusion `P` and - `iAssert P with "spat" as "ipat"` : generates a new subgoal `P` and adds the
put `P` in the context of the original goal. The specialization pattern hypothesis `P` to the current goal. The specialization pattern `spat`
`spat` specifies which hypotheses will be consumed by proving `P`. The specifies which hypotheses will be consumed by proving `P`. The introduction
introduction pattern `ipat` specifies how to eliminate `P`. pattern `ipat` specifies how to eliminate `P`.
- `iAssert P with "spat" as %cpat` : assert `P` and eliminate it using the Coq In case all branches of `ipat` start with a `#` (which causes `P` to be moved
introduction pattern `cpat`. to the persistent context) or with an `%` (which causes `P` to be moved to the
pure Coq context), then one can use all hypotheses for proving `P` as well as
for proving the current goal.
- `iAssert P as %cpat` : assert `P` and eliminate it using the Coq introduction
pattern `cpat`. All hypotheses can be used for proving `P` as well as for
proving the current goal.
Introduction of logical connectives Introduction of logical connectives
----------------------------------- -----------------------------------
...@@ -67,13 +72,16 @@ Elimination of logical connectives ...@@ -67,13 +72,16 @@ Elimination of logical connectives
---------------------------------- ----------------------------------
- `iExFalso` : Ex falso sequitur quod libet. - `iExFalso` : Ex falso sequitur quod libet.
- `iDestruct pm_trm as (x1 ... xn) "ipat"` : elimination of existential - `iDestruct pm_trm as (x1 ... xn) "ipat"` : elimination of a series of
quantifiers using Coq introduction patterns `x1 ... xn` and elimination of existential quantifiers using Coq introduction patterns `x1 ... xn`, and
object level connectives using the proof mode introduction pattern `ipat`. elimination of an object level connective using the proof mode introduction
In case all branches of `ipat` start with an `#` (moving the hypothesis to the pattern `ipat`.
persistent context) or `%` (moving the hypothesis to the pure Coq context), In case all branches of `ipat` start with a `#` (which causes the hypothesis
one can use all hypotheses for proving the premises of `pm_trm`, as well as to be moved to the persistent context) or with an `%` (which causes the
for proving the resulting goal. hypothesis to be moved to the pure Coq context), then one can use all
hypotheses for proving the premises of `pm_trm`, as well as for proving the
resulting goal. Note that in this case the hypotheses still need to be
subdivided among the spatial premises.
- `iDestruct pm_trm as %cpat` : elimination of a pure hypothesis using the Coq - `iDestruct pm_trm as %cpat` : elimination of a pure hypothesis using the Coq
introduction pattern `cpat`. When using this tactic, all hypotheses can be introduction pattern `cpat`. When using this tactic, all hypotheses can be
used for proving the premises of `pm_trm`, as well as for proving the used for proving the premises of `pm_trm`, as well as for proving the
......
...@@ -608,13 +608,15 @@ Proof. ...@@ -608,13 +608,15 @@ Proof.
by rewrite right_id HP HQ. by rewrite right_id HP HQ.
Qed. Qed.
Lemma tac_assert_persistent Δ Δ' j P Q : Lemma tac_assert_persistent Δ Δ1 Δ2 Δ' lr js j P Q :
envs_app true (Esnoc Enil j P) Δ = Some Δ' envs_split lr js Δ = Some (Δ1,Δ2)
(Δ P) PersistentP P (Δ' Q) Δ Q. envs_app false (Esnoc Enil j P) Δ = Some Δ'
(Δ1 P) PersistentP P
(Δ' Q) Δ Q.
Proof. Proof.
intros ? HP ??. intros ?? HP ? <-. rewrite -(idemp uPred_and Δ) {1}envs_split_sound //.
rewrite -(idemp uPred_and Δ) {1}HP envs_app_sound //; simpl. rewrite HP sep_elim_l (always_and_sep_l P) envs_app_sound //; simpl.
by rewrite right_id {1}(persistentP P) always_and_sep_l wand_elim_r. by rewrite right_id wand_elim_r.
Qed. Qed.
Lemma tac_pose_proof Δ Δ' j P Q : Lemma tac_pose_proof Δ Δ' j P Q :
......
...@@ -17,14 +17,6 @@ Inductive intro_pat := ...@@ -17,14 +17,6 @@ Inductive intro_pat :=
| IAll : intro_pat | IAll : intro_pat
| IClear : list (bool * string) intro_pat. (* true = frame, false = clear *) | IClear : list (bool * string) intro_pat. (* true = frame, false = clear *)
Fixpoint intro_pat_persistent (p : intro_pat) :=
match p with
| IPureElim => true
| IAlwaysElim _ => true
| IList pps => forallb (forallb intro_pat_persistent) pps
| _ => false
end.
Module intro_pat. Module intro_pat.
Inductive token := Inductive token :=
| TName : string token | TName : string token
...@@ -186,3 +178,20 @@ Ltac parse_one s := ...@@ -186,3 +178,20 @@ Ltac parse_one s :=
end end
end. end.
End intro_pat. End intro_pat.
Fixpoint intro_pat_persistent (p : intro_pat) :=
match p with
| IPureElim => true
| IAlwaysElim _ => true
| IList pps => forallb (forallb intro_pat_persistent) pps
| _ => false
end.
Ltac intro_pat_persistent p :=
lazymatch type of p with
| intro_pat => eval cbv in (intro_pat_persistent p)
| string =>
let pat := intro_pat.parse_one p in
eval cbv in (intro_pat_persistent pat)
| _ => p
end.
...@@ -325,18 +325,11 @@ Local Tactic Notation "iSpecializePat" constr(H) constr(pat) := ...@@ -325,18 +325,11 @@ Local Tactic Notation "iSpecializePat" constr(H) constr(pat) :=
|go H1 pats] |go H1 pats]
end in let pats := spec_pat.parse pat in go H pats. end in let pats := spec_pat.parse pat in go H pats.
(* p = whether the conclusion of the specialized term is persistent. It can (* The argument [p] denotes whether the conclusion of the specialized term is
either be a Boolean or an introduction pattern, which will be coerced in true persistent. It can either be a Boolean or an introduction pattern, which will be
when it only contains `#` or `%` patterns at the top-level. *) coerced into [true] when it only contains `#` or `%` patterns at the top-level. *)
Tactic Notation "iSpecializeCore" open_constr(t) "as" constr(p) tactic(tac) := Tactic Notation "iSpecializeCore" open_constr(t) "as" constr(p) tactic(tac) :=
let p := let p := intro_pat_persistent p in
lazymatch type of p with
| intro_pat => eval cbv in (intro_pat_persistent p)
| string =>
let pat := intro_pat.parse_one p in
eval cbv in (intro_pat_persistent pat)
| _ => p
end in
lazymatch t with lazymatch t with
| ITrm ?H ?xs ?pat => | ITrm ?H ?xs ?pat =>
lazymatch type of H with lazymatch type of H with
...@@ -1122,41 +1115,61 @@ Tactic Notation "iLöb" "as" constr (IH) "forall" "(" ident(x1) ident(x2) ...@@ -1122,41 +1115,61 @@ Tactic Notation "iLöb" "as" constr (IH) "forall" "(" ident(x1) ident(x2)
iRevertIntros(x1 x2 x3 x4 x5 x6 x7 x8) Hs with (iLöbCore as IH). iRevertIntros(x1 x2 x3 x4 x5 x6 x7 x8) Hs with (iLöbCore as IH).
(** * Assert *) (** * Assert *)
Tactic Notation "iAssertCore" open_constr(Q) "with" constr(Hs) "as" tactic(tac) := (* The argument [p] denotes whether [Q] is persistent. It can either be a
Boolean or an introduction pattern, which will be coerced into [true] when it
only contains `#` or `%` patterns at the top-level. *)
Tactic Notation "iAssertCore" open_constr(Q)
"with" constr(Hs) "as" constr(p) tactic(tac) :=
iStartProof; iStartProof;
let p := intro_pat_persistent p in
let H := iFresh in let H := iFresh in
let Hs := spec_pat.parse Hs in let Hs := spec_pat.parse Hs in
lazymatch Hs with lazymatch Hs with
| [SGoalPersistent] => | [SGoalPersistent] =>
eapply tac_assert_persistent with _ H Q; eapply tac_assert_persistent with _ _ _ true [] H Q;
[env_cbv; reflexivity [env_cbv; reflexivity
|env_cbv; reflexivity
|(*goal*) |(*goal*)
|apply _ || fail "iAssert:" Q "not persistent" |apply _ || fail "iAssert:" Q "not persistent"
|tac H] |tac H]
| [SGoal (SpecGoal ?m ?lr ?Hs_frame ?Hs)] => | [SGoal (SpecGoal ?m ?lr ?Hs_frame ?Hs)] =>
let Hs' := eval cbv in (if lr then Hs else Hs_frame ++ Hs) in let Hs' := eval cbv in (if lr then Hs else Hs_frame ++ Hs) in
eapply tac_assert with _ _ _ lr Hs' H Q _; match p with
[match m with | false =>
| false => apply elim_modal_dummy eapply tac_assert with _ _ _ lr Hs' H Q _;
| true => apply _ || fail "iAssert: goal not a modality" [match m with
end | false => apply elim_modal_dummy
|env_cbv; reflexivity || fail "iAssert:" Hs "not found" | true => apply _ || fail "iAssert: goal not a modality"
|env_cbv; reflexivity end
|iFrame Hs_frame (*goal*) |env_cbv; reflexivity || fail "iAssert:" Hs "not found"
|tac H] |env_cbv; reflexivity
|iFrame Hs_frame (*goal*)
|tac H]
| true =>
eapply tac_assert_persistent with _ _ _ lr Hs' H Q;
[env_cbv; reflexivity
|env_cbv; reflexivity
|(*goal*)
|apply _ || fail "iAssert:" Q "not persistent"
|tac H]
end
| ?pat => fail "iAssert: invalid pattern" pat | ?pat => fail "iAssert: invalid pattern" pat
end. end.
Tactic Notation "iAssert" open_constr(Q) "with" constr(Hs) "as" constr(pat) := Tactic Notation "iAssert" open_constr(Q) "with" constr(Hs) "as" constr(pat) :=
iAssertCore Q with Hs as (fun H => iDestructHyp H as pat). iAssertCore Q with Hs as pat (fun H => iDestructHyp H as pat).
Tactic Notation "iAssert" open_constr(Q) "as" constr(pat) := Tactic Notation "iAssert" open_constr(Q) "as" constr(pat) :=
iAssert Q with "[]" as pat. let p := intro_pat_persistent pat in
match p with
| true => iAssert Q with "[-]" as pat
| false => iAssert Q with "[]" as pat
end.
Tactic Notation "iAssert" open_constr(Q) "with" constr(Hs) Tactic Notation "iAssert" open_constr(Q) "with" constr(Hs)
"as" "%" simple_intropattern(pat) := "as" "%" simple_intropattern(pat) :=
iAssertCore Q with Hs as (fun H => iPure H as pat). iAssertCore Q with Hs as true (fun H => iPure H as pat).
Tactic Notation "iAssert" open_constr(Q) "as" "%" simple_intropattern(pat) := Tactic Notation "iAssert" open_constr(Q) "as" "%" simple_intropattern(pat) :=
iAssert Q with "[]" as %pat. iAssert Q with "[-]" as %pat.
(** * Rewrite *) (** * Rewrite *)
Local Ltac iRewriteFindPred := Local Ltac iRewriteFindPred :=
......
...@@ -105,3 +105,13 @@ End iris. ...@@ -105,3 +105,13 @@ End iris.
Lemma demo_9 (M : ucmraT) (x y z : M) : Lemma demo_9 (M : ucmraT) (x y z : M) :
x y z - ( x x y z : uPred M). x y z - ( x x y z : uPred M).
Proof. iIntros (Hv) "Hxy". by iFrame (Hv Hv) "Hxy". Qed. Proof. iIntros (Hv) "Hxy". by iFrame (Hv Hv) "Hxy". Qed.
Lemma demo_10 (M : ucmraT) (P Q : uPred M) : P - Q - True.
Proof.
iIntros "HP HQ".
iAssert True%I as "#_". { by iClear "HP HQ". }
iAssert True%I with "[HP]" as "#_". { Fail iClear "HQ". by iClear "HP". }
iAssert True%I as %_. { by iClear "HP HQ". }
iAssert True%I with "[HP]" as %_. { Fail iClear "HQ". by iClear "HP". }
done.
Qed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment