Skip to content

Commit 8a7a574

Browse files
authored
Add wp_if_join tactic (#532)
I add a tactic, `wp_if_join`, that allows you to 'join' both branches of an if-statement into a single assertion by showing that both branches make said assertion hold. Given the program below (and assertion `A`) ``` if b { S1; } else { S2; } // no `else` is handled trivially by Goose. // assertion `A` S3; ``` By using the tactic `wp_if_join <assertion> [with <ipat>]` (leaving off the `with` to provide no spatial hypotheses), the goal is split into three subgoals: 1. Proving that `S1` results in `A` holding, 2. Proving that `S2` results in `A` holding, and 3. Proving the remainder of the program, `S3`, assuming that `A` holds. --------- Signed-off-by: Cody Rivera <[email protected]>
1 parent 18426cb commit 8a7a574

File tree

2 files changed

+63
-0
lines changed
  • new
    • golang/theory
    • proof/github_com/goose_lang/goose/testdata/examples

2 files changed

+63
-0
lines changed

new/golang/theory/auto.v

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,28 @@ Ltac wp_if_destruct :=
343343
end
344344
end.
345345

346+
(** [wp_if_join] joins two branches of an if expression into a shared assertion
347+
[asn], which becomes available for the proof of subsequent statements.
348+
349+
Usage:
350+
wp_if_join asn with pat
351+
wp_if_join asn
352+
353+
[asn] is the join assertion (a function from value to iProp). [pat] is an
354+
optional Iris intro pattern specifying spatial hypotheses needed to prove
355+
the if expression. The goal is split into three subgoals:
356+
1) Prove [asn] in the true branch.
357+
2) Prove [asn] in the false branch.
358+
3) Prove the remainder with [asn] as an assumption.
359+
**)
360+
Tactic Notation "wp_if_join" constr(asn) "with" constr(pat) :=
361+
wp_bind (if: _ then _ else _)%E;
362+
wp_pures;
363+
iApply (wp_wand _ _ _ asn with pat)%I;
364+
[ wp_if_destruct | ].
365+
366+
Tactic Notation "wp_if_join" constr(asn) := wp_if_join asn with "[]".
367+
346368
Ltac wp_end :=
347369
wp_pures;
348370
repeat iModIntro;

new/proof/github_com/goose_lang/goose/testdata/examples/unittest.v

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,47 @@ Proof.
384384
- wp_end.
385385
Qed.
386386

387+
Lemma wp_ifJoinDemo_if_join_tactic (arg1 arg2: bool) :
388+
{{{ is_pkg_init unittest }}}
389+
@! unittest.ifJoinDemo #arg1 #arg2
390+
{{{ RET #(); True }}}.
391+
Proof.
392+
wp_start.
393+
wp_auto.
394+
iPersist "arg2".
395+
wp_if_join (λ v, ⌜v = execute_val⌝ ∗
396+
∃ (sl: slice.t) (xs: list w64),
397+
"arr" ∷ arr_ptr ↦ sl ∗
398+
"Hsl" ∷ sl ↦* xs ∗
399+
"Hsl_cap" ∷ own_slice_cap w64 sl (DfracOwn 1))%I
400+
with "[arr]".
401+
{
402+
wp_apply (wp_slice_literal (V:=w64)) as "%sl [Hsl _]".
403+
wp_apply (wp_slice_append (V:=w64) with "[Hsl]") as "%sl1 (Hsl & Hsl_cap & _)".
404+
{
405+
iFrame.
406+
iDestruct (own_slice_nil) as "$".
407+
iDestruct (own_slice_cap_nil) as "$".
408+
}
409+
iSplit; [ done | ].
410+
iFrame.
411+
}
412+
{
413+
iSplit; [ done | ].
414+
iFrame.
415+
iExists [].
416+
iDestruct (own_slice_nil) as "$".
417+
iDestruct (own_slice_cap_nil) as "$".
418+
}
419+
iIntros (v) "[% @]". subst.
420+
wp_auto.
421+
wp_if_destruct.
422+
- wp_apply (wp_slice_literal (V:=w64)) as "%sl2 [Hsl2 _]".
423+
wp_apply (wp_slice_append (V:=w64) with "[$Hsl $Hsl_cap $Hsl2]") as "%sl1 (Hsl & Hsl_cap & _)".
424+
wp_end.
425+
- wp_end.
426+
Qed.
427+
387428
Lemma wp_repeatLocalVars :
388429
{{{ is_pkg_init unittest }}}
389430
@! unittest.repeatLocalVars #()

0 commit comments

Comments
 (0)