Abstract Solver Interface: Decouple Term Construction from SMT-LIB Encoding#935
Merged
Merged
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Switch from E.deferred to ObligationExtraction-produced obligations for actual verification. The pipeline now: 1. obligationsToProgram converts E.deferred to Core program 2. ObligationExtraction extracts obligations from the program 3. Extracted obligations are used for verification Fix: don't include axiom declarations in the obligations program. Each obligation already has the correct axioms in its path conditions from E.deferred. Adding axiom declarations would cause ObligationExtraction to add them again, potentially including axioms that shouldn't be in scope (e.g. a procedure's own invokeOn axiom proving its own postcondition). All tests pass with extracted obligations.
This comment has been minimized.
This comment has been minimized.
- Add sort type parameter σ to AbstractSolver (τ σ m) so backends can have their own sort representation - Add sort constructors: boolSort, intSort, realSort, stringSort, bitvecSort, arraySort - Add mkAbs (absolute value) - Add mkSelect/mkStore (array operations) - Add mkApp (uninterpreted function application) - Update IncrementalSolver: σ = TermType, implement all new operations
This comment has been minimized.
This comment has been minimized.
typeCheckAndEval now returns List (Program × Env) where each Program has the procedure body replaced with the obligations tree (assume/assert blocks combined with if *). Axioms are inlined into each procedure's obligations from E.deferred path conditions. Type/datatype declarations are preserved. verifySingleEnv takes (Program × Env) and uses ObligationExtraction on the obligations program. The Env is still needed for E.distinct and E.datatypes in the SMT encoder. This makes the symbolic evaluation phase produce a Core program as output, moving toward the reviewer's vision of Core-to-Core pipeline phases.
typeCheckAndEval now returns one Program containing all procedures' obligations (one procedure per evaluation environment). The Program has type/datatype declarations plus obligation procedures. The List Env is still returned alongside for SMT encoding context (distinct, datatypes) — these will be moved into the Program in a future step. verify() uses the first Env as sample for SMT encoding.
verifySingleEnv now takes (Program, Env) where the Env is reconstructed internally from the evaluation phase. The Env carries distinct constraints and datatypes needed by the SMT encoder — these will be extracted from the Program in a future step to fully eliminate Env dependency. The evaluation phase (typeCheckAndEval) returns Program as the primary output. The List Env is returned alongside for internal use only.
The evaluation phase (typeCheckAndEval) returns Program as primary output. Env is still passed internally to verifySingleEnv for SMT encoding (distinct, datatypes, factory) but is not part of the public pipeline. The Env dependency in SMT encoding requires the full evaluation context (factory with all function declarations, datatype constructors, type aliases). Eliminating it requires refactoring the SMT encoder to reconstruct this context from the Program declarations.
The evaluation phase (typeCheckAndEval) returns Program as the primary output. The List Env is returned alongside as an internal detail for the SMT encoder — verify() extracts the first Env and passes it to verifySingleEnv. Add buildSMTEnv helper in Core.lean that constructs an Env from program declarations (factory, datatypes, distinct) without running procedure evaluation. Used by MetaVerifier. The PE/evaluation phase is now a Program → Program transformation. The Env dependency is isolated to the SMT encoding stage.
…ypeCheckAndEval Split the pipeline into distinct phases: 1. typeCheck: Program → Program (type checking) 2. symbolicEval: Program → Program (symbolic execution → obligations tree) 3. ANFEncoder: Program → Program (available, not yet wired) 4. ObligationExtraction + SMT encoding (verification) typeCheckAndEval is now a convenience wrapper calling typeCheck then symbolicEval, returning (Program, Statistics) with no Env. The SMT encoder builds its own Env internally via buildEvalEnv + Program.eval in verify(). This is isolated from the pipeline phases. buildSMTEnv helper available for lightweight Env construction (used by MetaVerifier).
aqjune-aws
previously approved these changes
May 15, 2026
MikaelMayer
commented
May 15, 2026
aqjune-aws
previously approved these changes
May 15, 2026
…lver-interface-decouple-term
…lver-interface-decouple-term
…lver-interface-decouple-term
…lver-interface-decouple-term # Conflicts: # Strata/Languages/Core/SMTEncoder.lean
aqjune-aws
approved these changes
May 18, 2026
atomb
approved these changes
May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #917
Summary
Introduces an abstract solver interface (
AbstractSolver τ σ m) that decouples term construction and session operations from the SMT-LIB string encoding pipeline. The interface is parameterized by a term typeτ, sort typeσ, and monadm(with[Monad m] [MonadExceptOf IO.Error m]constraints), so a non-SMT-LIB backend (e.g., cvc5 FFI) can be plugged in by implementingAbstractSolverwithout touching the encoding logic. All methods throwIO.Errordirectly (noExcept Stringlayer).A new incremental backend communicates with a live solver process via stdin/stdout. It is opt-in via
--incremental(batch remains the default).What the interface provides
All operations are monadic (
m), throwing on error:setLogic,setOption,commentboolSort,intSort,realSort,stringSort,regexSort,bitvecSort,arraySort,constrSort,termTypeToSortmkPrim,mkBool,mkAnd,mkOr,mkNot,mkImplies,mkEq,mkIte,mkAdd,mkSub,mkMul,mkDiv,mkMod,mkNeg,mkAbs,mkLt,mkLe,mkGt,mkGe,mkSelect,mkStore,mkApp,mkAppOp,mkForall,mkExistsdeclareNew,declareFun,defineFun,declareSort,declareDatatype,declareDatatypesassert,checkSat,checkSatAssuming,getUnsatAssumptions,getModel,getValue,reset,closetermToSMTLibStringTerms (
τ) are opaque handles whose meaning is backend-specific.Other changes
AbstractEncoder.encodeTermparameterized overτ/σ, caches handles inAbstractEncoderState τ.Imperative.SMT.dischargeObligationIncrementalinSMTUtils.leanis parameterized overPureExpr, so any Imperative-level language can use the incremental solver.CoreSMTSolverandMkDischargeFnthreaded throughCore.verifyProgram,Core.verify, andStrata.verify.encodeDeclarationsAbstractskipsdeclareSortfor datatype names and validates datatype fields.--incrementalflag to opt in to the incremental backend.Testing
All tests pass with both batch (default) and incremental modes.
Follow-ups