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.
37 lines
941 B
Text
37 lines
941 B
Text
import Lean
|
|
|
|
macro "gen_term" n:num : term => do
|
|
let mut stx ← `(True)
|
|
for _ in 0...n.getNat do
|
|
stx := ← `(let z : Nat := x + y; let y := y + 1; have : y >= 0 := Nat.zero_le y; forall x : Nat, $stx)
|
|
`(let z : Nat := 0 ; forall x : Nat, forall y : Nat, $stx)
|
|
|
|
open Lean Meta Sym Elab Tactic
|
|
|
|
def test (mvarId : MVarId) : MetaM MVarId := do
|
|
SymM.run do
|
|
let .goal _ mvarId ← intros mvarId | failure
|
|
return mvarId
|
|
|
|
/--
|
|
trace: z✝² : Nat := 0
|
|
x✝² y✝² : Nat
|
|
z✝¹ : Nat := x✝² + y✝²
|
|
y✝¹ : Nat := y✝² + 1
|
|
this✝¹ : y✝¹ ≥ 0 := Nat.zero_le y✝¹
|
|
x✝¹ : Nat
|
|
z✝ : Nat := x✝¹ + y✝¹
|
|
y✝ : Nat := y✝¹ + 1
|
|
this✝ : y✝ ≥ 0 := Nat.zero_le y✝
|
|
x✝ : Nat
|
|
⊢ True
|
|
-/
|
|
#guard_msgs in
|
|
example : gen_term 2 := by
|
|
run_tac liftMetaTactic1 fun mvarId => test mvarId
|
|
trace_state
|
|
constructor
|
|
|
|
example : gen_term 70 := by
|
|
run_tac liftMetaTactic1 fun mvarId => test mvarId
|
|
constructor
|