This PR reorganizes the monad hierarchy for symbolic computation in Lean. ## Motivation We want a clean layering where: 1. A foundational monad (`SymM`) provides maximally shared terms and structural/syntactic `isDefEq` 2. `GrindM` builds on this foundation, adding E-graphs, congruence closure, and decision procedures 3. Symbolic execution / VCGen uses `GrindM` directly without introducing a third monad ## Changes The core symbolic computation layer still lives in `Lean.Meta.Sym`. This monad (`SymM`) provides: - Maximally shared terms with pointer-based equality - Structural/syntactic `isDefEq` and matching (no reduction, predictable cost) - Monotonic local contexts (no `revert` or `clear`), enabling O(1) metavariable validation - Efficient `intro`, `apply`, and `simp` implementations The name "Sym" reflects that this is infrastructure for symbolic computation: symbolic simulation, verification condition generation, and decision procedures. ### Updated hierarchy ``` Lean.Meta.Sym -- SymM: shared terms, syntactic isDefEq, intro, apply, simp Lean.Meta.Grind -- GrindM: E-graphs, congruence closure (extends SymM) ``` Symbolic execution is a usage pattern of `GrindM` operating on `Grind.Goal`, not a separate monad. This keeps the API surface minimal: users learn two monads, and VCGen is "how you use `GrindM`" (for users that want to use `grind`) rather than a third abstraction to understand.
67 lines
1.6 KiB
Text
67 lines
1.6 KiB
Text
import Lean.Meta.Sym
|
|
set_option sym.debug true
|
|
open Lean Meta Sym
|
|
open Internal
|
|
def tst1 : SymM Unit := do
|
|
let f ← mkConstS `f
|
|
let e ← mkAppS (← mkAppS (← mkAppS f (← mkBVarS 0)) (← mkBVarS 1)) (← shareCommon (mkNatLit 1))
|
|
let a ← mkConstS `a
|
|
let b ← mkConstS `b
|
|
let r ← instantiateRevS e #[a, b]
|
|
assert! r == e.instantiateRev #[a, b]
|
|
logInfo r
|
|
let r ← instantiateS e #[a, b]
|
|
assert! r == e.instantiate #[a, b]
|
|
logInfo r
|
|
let e ← mkLambdaS `x .default (← mkConstS ``Nat) e
|
|
let r ← instantiateRevS e #[a, b]
|
|
assert! r == e.instantiateRev #[a, b]
|
|
logInfo r
|
|
let r ← instantiateS e #[a, b]
|
|
assert! r == e.instantiate #[a, b]
|
|
logInfo r
|
|
|
|
/--
|
|
info: f b a 1
|
|
---
|
|
info: f a b 1
|
|
---
|
|
info: fun x => f x b 1
|
|
---
|
|
info: fun x => f x a 1
|
|
-/
|
|
#guard_msgs in
|
|
#eval SymM.run tst1
|
|
|
|
def tst2 : SymM Unit := do
|
|
let f ← mkConstS `f
|
|
withLocalDeclD `w (← mkConstS ``Nat) fun w => do
|
|
let w ← shareCommon w
|
|
let e ← mkAppS (← mkAppS (← mkAppS f (← mkBVarS 0)) (← mkBVarS 1)) w
|
|
withLocalDeclD `x (← mkConstS ``Nat) fun x => do
|
|
withLocalDeclD `y (← mkConstS ``Nat) fun y => do
|
|
let x ← shareCommon x
|
|
let y ← shareCommon y
|
|
logInfo e
|
|
let r ← instantiateRevS e #[x, y]
|
|
logInfo r
|
|
assert! isSameExpr (← abstractFVars r #[x, y]) e
|
|
logInfo (← abstractFVars r #[x, y])
|
|
logInfo (← abstractFVarsRange r 1 #[x, y])
|
|
logInfo (← mkLambdaFVarsS #[x, y] e)
|
|
|
|
|
|
set_option pp.funBinderTypes true in
|
|
/--
|
|
info: f #0 #1 w
|
|
---
|
|
info: f y x w
|
|
---
|
|
info: f #0 #1 w
|
|
---
|
|
info: f #0 x w
|
|
---
|
|
info: fun (x y : Nat) => f y x w
|
|
-/
|
|
#guard_msgs in
|
|
#eval SymM.run tst2
|