blob: c3a4f02d90dde14a4bb1ca62bf004fbcfda6c1a4 [file] [edit]
import Std.Internal.Do
import Std.Tactic.Do
/-! Tests that `vcgen` is usable as a step inside `sym => …` blocks. -/
open Std.Internal.Do Lean.Order
set_option mvcgen.warning false
set_option warn.sorry false
/-! ## Trivial postcondition: `vcgen` closes the goal -/
axiom G : StateM Nat Unit
axiom H : StateM Nat Unit
noncomputable def F : StateM Nat Unit := do
G
H
@[spec]
axiom G_spec : ⦃ (fun (_ : Nat) => True) ⦄ G ⦃ fun _ n => n = n ⦄
@[spec]
axiom H_spec : ⦃ (fun (_ : Nat) => True) ⦄ H ⦃ fun _ n => n = n ⦄
example : ⦃ (fun (_ : Nat) => True) ⦄ F ⦃ fun _ n => n = n ⦄ := by
sym =>
vcgen [F]
/-! ## Pre-tactic dispatches the leftover VC -/
axiom G2 : StateM Nat Unit
axiom H2 : StateM Nat Unit
noncomputable def F2 : StateM Nat Unit := do
G2
H2
axiom P : Nat → Prop
@[spec]
axiom G2_spec : ⦃ (fun (_ : Nat) => True) ⦄ G2 ⦃ fun _ n => P n ⦄
@[spec]
axiom H2_spec : ⦃ (fun n => P n) ⦄ H2 ⦃ fun _ _ => True ⦄
example : ⦃ (fun (_ : Nat) => True) ⦄ F2 ⦃ fun _ _ => True ⦄ := by
sym =>
vcgen [F2] <;> finish
/-! ## VC leftover; closed by a subsequent grind step -/
axiom G3 : StateM Nat Unit
axiom H3 : StateM Nat Unit
noncomputable def F3 : StateM Nat Unit := do
G3
H3
axiom Q : Nat → Prop
axiom hPQ : ∀ n, P n → Q n
@[spec]
axiom G3_spec : ⦃ (fun (_ : Nat) => True) ⦄ G3 ⦃ fun _ n => P n ⦄
@[spec]
axiom H3_spec : ⦃ (fun n => Q n) ⦄ H3 ⦃ fun _ _ => True ⦄
example : ⦃ (fun (_ : Nat) => True) ⦄ F3 ⦃ fun _ _ => True ⦄ := by
sym =>
vcgen [F3]
finish [hPQ]
-- `sym [hPQ]` propagates to the new VC `Grind.Goal`s; no need to re-pass it.
example : ⦃ (fun (_ : Nat) => True) ⦄ F3 ⦃ fun _ _ => True ⦄ := by
sym [hPQ] =>
vcgen [F3]
finish
/-! ## VC references an fvar introduced by `vcgen` -/
axiom G4 : StateM Nat Nat
axiom Q4 : Nat → Prop
axiom hPQ4 : ∀ n, P n → Q4 n
@[spec]
axiom G4_spec : ⦃ (fun (_ : Nat) => True) ⦄ G4 ⦃ fun x _ => P x ⦄
noncomputable def F4 : StateM Nat Nat := do
let x ← G4
pure x
-- `vcgen` introduces `x` and a hypothesis `P x` into the VC's local context.
-- The subsequent `finish [hPQ4]` must see `P x` in the E-graph to derive `Q4 x`.
example : ⦃ (fun (_ : Nat) => True) ⦄ F4 ⦃ fun r _ => Q4 r ⦄ := by
sym =>
vcgen [F4]
finish [hPQ4]
/-! ## Inline invariants (bullet form) inside `sym =>` -/
example :
⦃ (True : Prop) ⦄
(do
let mut x := 0
for i in [1:5] do
x := x + i
pure x : Id Nat)
⦃ fun r => r < 30 ⦄ := by
sym =>
vcgen invariants
· fun xs r => r + xs.suffix.length * 5 ≤ 25
<;> finish
/-! ## `invariants?` (suggest mode) inside `sym =>` -/
def mySum (l : List Nat) : Nat := Id.run do
let mut acc := 0
for x in l do
acc := acc + x
return acc
/--
info: There were no suggestions for missing invariants.
-/
#guard_msgs (info) in
theorem mySum_suggest (l : List Nat) : mySum l = l.sum := by
generalize h : mySum l = r
apply Std.Internal.Do.Id.of_wp_run_eq h
sym =>
vcgen [mySum] invariants?
all_goals tactic => admit