This PR adds an API for building symbolic simulation engines and verification condition generators that leverage `grind`. The API wraps `Sym` operations to work with `grind`'s `Goal` type, enabling lightweight symbolic execution while carrying `grind` state for discharge steps. New operations on `Goal`: - `mkGoal`: create a `Goal` from an `MVarId` - `introN`, `intros`: introduce binders - `apply`: apply backward rules - `simp`, `simpIgnoringNoProgress`: simplify using `Sym.Simp` - `internalize`, `internalizeAll`: add hypotheses to the E-graph - `grind`: attempt to close the goal using `grind` - `assumption`: close by matching a hypothesis A new test demonstrates the API on a stateful program with conditionals, using `grind` to discharge arithmetic side conditions.
28 lines
560 B
Text
28 lines
560 B
Text
import Lean.Meta.Tactic
|
|
import Lean.Meta.Sym
|
|
|
|
def f (x : Nat) :=
|
|
let y := x + 1
|
|
2*y
|
|
|
|
open Lean Meta Sym
|
|
/--
|
|
info: x : Nat
|
|
⊢ have y := x + 1;
|
|
x ≤ 2 * y
|
|
---
|
|
info: x : Nat
|
|
y : Nat := x + 1
|
|
⊢ x ≤ 2 * y
|
|
-/
|
|
#guard_msgs in
|
|
run_meta SymM.run do
|
|
withLocalDeclD `x Nat.mkType fun x => do
|
|
let m ← mkFreshExprMVar <| mkNatLE x (mkApp (mkConst ``f) x)
|
|
let mvarId := m.mvarId!
|
|
let mvarId ← unfoldTarget mvarId ``f
|
|
let mvarId ← mvarId.liftLets
|
|
logInfo mvarId
|
|
let .goal _ mvarId ← intros mvarId #[`y] | failure
|
|
logInfo mvarId
|
|
return ()
|