Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
20242c2
Add B3 to SMT converter with interactive test
MikaelMayer Dec 31, 2025
40727c6
Fix B3 to SMT converter to match B3's SMT generation
MikaelMayer Dec 31, 2025
4414ed7
Add top-level check declarations and if-then-else support
MikaelMayer Dec 31, 2025
19a0bf4
Fix check statement to verify provability instead of asserting
MikaelMayer Dec 31, 2025
466f586
Add support for functions with bodies
MikaelMayer Dec 31, 2025
f8af0a1
Refactor to two-pass approach for mutually recursive functions
MikaelMayer Dec 31, 2025
aaec9a3
Add quantifier pattern support and implies operator
MikaelMayer Dec 31, 2025
c150aba
Complete core expression support for B3 to SMT converter
MikaelMayer Jan 2, 2026
d73cd24
Fix function definition triggers to use function call pattern
MikaelMayer Jan 2, 2026
6153a2c
Add incremental verification API with Z3 solver integration
MikaelMayer Jan 2, 2026
8c4933f
Reorganize B3 verifier into modular structure
MikaelMayer Jan 2, 2026
700c645
Rename Verifier/Verifier.lean to Verifier/Core.lean
MikaelMayer Jan 2, 2026
b7c5e14
Document why we use custom formatter instead of SMT Encoder
MikaelMayer Jan 2, 2026
29908bf
Add statement-to-VC conversion (VCG foundation)
MikaelMayer Jan 2, 2026
f96d23b
Implement parameter-free procedure verification
MikaelMayer Jan 2, 2026
6ca219d
Merge and clean up test files
MikaelMayer Jan 2, 2026
95f8c12
Add source location tracking and error reporting
MikaelMayer Jan 2, 2026
b8fd1d6
Add counterexample display with source location and statement
MikaelMayer Jan 2, 2026
3a27145
Complete B3 verifier with error reporting and model indication
MikaelMayer Jan 2, 2026
5859f6e
Remove checkDecl and add conjunction refinement strategy
MikaelMayer Jan 2, 2026
38e53a8
Add conjunction refinement with proper API separation
MikaelMayer Jan 2, 2026
5119550
Implement general automatic refinement verification
MikaelMayer Jan 2, 2026
6e94e24
Polish error messages and remove model placeholder
MikaelMayer Jan 2, 2026
41119a7
Implement efficient solver reuse with push/pop
MikaelMayer Jan 2, 2026
c757d12
Rename Refinement to Diagnosis and expose push/pop API
MikaelMayer Jan 2, 2026
ae44cab
Update documentation to reflect current API
MikaelMayer Jan 2, 2026
48abe84
Improve API naming and add reach support
MikaelMayer Jan 2, 2026
a03f0cc
Add unified addDeclaration API and move tests to proper location
MikaelMayer Jan 2, 2026
fb71f14
Fix namespace scope for high-level API functions
MikaelMayer Jan 2, 2026
8febeb2
Add reach test and fix test file organization
MikaelMayer Jan 2, 2026
b5f6939
Fix reach statement semantics and output
MikaelMayer Jan 2, 2026
d31b140
Complete reach semantics with precondition checking examples
MikaelMayer Jan 2, 2026
bf8eed9
WIP: Implement streaming translation (NOT batch VCG)
MikaelMayer Jan 2, 2026
b3d6006
Replace SMT Decision with B3-level result types
MikaelMayer Jan 2, 2026
309bec8
Use separate result types for check and reach
MikaelMayer Jan 2, 2026
2905a07
WIP: Major refactoring to streaming translation and unified API
MikaelMayer Jan 2, 2026
bc57e12
Implement unified API with solver as parameter
MikaelMayer Jan 2, 2026
1a6e5f8
Split state into SMTSolverState and B3VerificationState
MikaelMayer Jan 2, 2026
54ba932
Improve result formatting and fix test expectations
MikaelMayer Jan 2, 2026
5029d10
Complete B3 verifier with comprehensive documentation
MikaelMayer Jan 2, 2026
f8bfc43
Complete B3 verifier with comprehensive documentation
MikaelMayer Jan 2, 2026
7848fd3
Reorganize documentation into unified implementation status
MikaelMayer Jan 2, 2026
a822591
Final documentation: add incremental API and old values
MikaelMayer Jan 2, 2026
0971a6e
Remove old values from TODO - already handled via de Bruijn indices
MikaelMayer Jan 2, 2026
9c40158
refactor(B3): Improve verifier with transformation, error handling, a…
MikaelMayer Jan 5, 2026
7f6c312
refactor(B3): Reorganize verifier modules for clarity
MikaelMayer Jan 5, 2026
8517321
refactor(B3): Clean up empty section dividers in Batch.lean
MikaelMayer Jan 5, 2026
c4bca29
refactor(B3): Remove redundant API.lean and legacy functions
MikaelMayer Jan 5, 2026
053b54c
docs(B3): Add architecture diagram and clarify implementation status
MikaelMayer Jan 5, 2026
d7b2b64
chore(B3): Remove test artifact and document result type hierarchy
MikaelMayer Jan 5, 2026
b7b2ae9
refactor(B3): Improve naming clarity and consolidate diagnosis code
MikaelMayer Jan 5, 2026
975d604
refactor(B3): Consolidate diagnosis code and improve naming
MikaelMayer Jan 5, 2026
3515e53
Reorganize B3 verifier tests and improve output formatting
MikaelMayer Jan 5, 2026
647058f
feat(B3): Complete error accumulation refactoring with enhanced diagn…
MikaelMayer Jan 7, 2026
56b8d7e
refactor(B3): Improve verification report structure and output format…
MikaelMayer Jan 7, 2026
388018f
refactor(B3): Rename modules and improve API design
MikaelMayer Jan 7, 2026
b6f0f26
docs(B3): Show full pipeline with B3CST.Program in example
MikaelMayer Jan 7, 2026
f24cd73
docs(B3): Simplify example to use programToB3AST helper
MikaelMayer Jan 7, 2026
8d1b12e
docs(B3): Add diagnosis behavior explanation
MikaelMayer Jan 7, 2026
b517ee5
fix(B3): Fix path condition display in diagnosis and add formatStatement
MikaelMayer Jan 7, 2026
1a245e0
feat(B3): Use formatStatement from Statements.lean in Verifier.lean
MikaelMayer Jan 7, 2026
25ac46e
chore: Remove local development files from tracking
MikaelMayer Jan 7, 2026
17cee51
feat(B3): Add StrataVerifyB3 CLI tool
MikaelMayer Jan 9, 2026
8bffd3c
Merge branch 'main' into b3-to-smt-converter
MikaelMayer Jan 9, 2026
b8747dc
Use SMT dialect pretty-printer instead of custom string interpolation
MikaelMayer Jan 9, 2026
d3d3a9e
Fix SMT equality operator to use '=' instead of 'eq'
MikaelMayer Jan 13, 2026
c00df60
Extract pure logic from IO functions in Diagnosis
MikaelMayer Jan 13, 2026
838a3c6
Extract pure logic from IO functions in Program
MikaelMayer Jan 13, 2026
5ef6fd9
Extract pure logic from IO functions in Statements and Diagnosis
MikaelMayer Jan 13, 2026
5a55ab8
Rename getStatementMetadata to B3AST.Statement.metadata
MikaelMayer Jan 13, 2026
085078e
Update documentation per review comments
MikaelMayer Jan 13, 2026
a24f3d4
Integrate B3 verification into StrataVerify
MikaelMayer Jan 14, 2026
9279956
Rename verification functions to emphasize SMT translation
MikaelMayer Jan 14, 2026
e217e99
Unify statement translation return types with optional diagnosis
MikaelMayer Jan 15, 2026
04c0bb9
Merge branch 'main' into b3-to-smt-converter
MikaelMayer Jan 15, 2026
2f02069
Add SMT pattern support and fix formatting issues
MikaelMayer Jan 15, 2026
8c231cf
Remove accidentally committed test file
MikaelMayer Jan 15, 2026
85dcc23
Switch to CVC5 and update test expectations
MikaelMayer Jan 15, 2026
1620932
Fix solver lifecycle - don't call exit in tests
MikaelMayer Jan 15, 2026
ee80e24
Remove action plan file
MikaelMayer Jan 15, 2026
9c11a05
Merge main into b3-to-smt-converter
MikaelMayer Jan 15, 2026
060244c
Address Josh's review comments
MikaelMayer Jan 15, 2026
bca2f06
Address additional Josh review comments
MikaelMayer Jan 15, 2026
fcb2194
Prove termination for termToSExpr
Jan 16, 2026
e81132a
Merge branch 'main' into b3-to-smt-converter
Jan 16, 2026
aff081e
Fix if-then-else expressions
Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions JOSH_REVIEW_COMMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Josh's Review Comments on PR #307
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be committed to the repo.


**Reviewer:** @joscoh (Josh)
**Date:** January 15, 2026
**Status:** Pending response

---

## Comment 1: Use List.map instead of for loop ✅ DONE

**File:** `Strata/Languages/B3/Verifier/Program.lean`
**Line:** 106
**Comment:**
> I think it's nicer to have `let results := results ++ List.map .error conversionErrors`
**Status:** ✅ Fixed

**Change Applied:**
```lean
results := results ++ conversionErrors.map .error
```

**Commit:** (pending)

---

## Comment 2: Remove unnecessary mutable variable ✅ DONE

**File:** `Strata/Languages/B3/Verifier/Program.lean`
**Line:** 94
**Comment:**
> This does not need to be mutable.
**Status:** ✅ Fixed

**Change Applied:**
```lean
let initialState ← initVerificationState solver
...
let (state, conversionErrors) ← addDeclarationsAndAxioms initialState transformedProg
```

**Commit:** (pending)

---

## Comment 3: Remove duplicate section header ✅ DONE

**File:** `Strata/Languages/B3/Verifier/Program.lean`
**Line:** 119
**Comment:**
> Repeated section
**Status:** ✅ Fixed

**Change Applied:** Removed duplicate header.

**Commit:** (pending)

---

## Comment 4: Remove unused section header ✅ DONE

**File:** `Strata/Languages/B3/Verifier/State.lean`
**Line:** 63
**Comment:**
> Is this section header used?
**Status:** ✅ Fixed

**Change Applied:** Removed unused "Verification State" header that was immediately followed by "Verification Context and Results" header.

**Commit:** (pending)

---

## Comment 5: Use reverse list building pattern ✅ DONE

**File:** `Strata/Languages/B3/Verifier/Program.lean`
**Line:** 202
**Comment:**
> Again, it would be better to build the reverse list with `::` and reverse the whole thing at the end.
**Status:** ✅ Fixed

**Change Applied:**
```lean
let mut reportsRev := []
...
reportsRev := {procedureName := name, results := resultsWithDiag} :: reportsRev
...
return reportsRev.reverse
```

**Commit:** (pending)

---

## Comment 6: Same optimization for Statements.lean ✅ DONE

**File:** `Strata/Languages/B3/Verifier/Statements.lean`
**Line:** 98
**Comment:**
> Same as above
**Status:** ✅ Fixed

**Change Applied:** Used `::` and reverse pattern in both `statementToSMTWithoutDiagnosis` (Statements.lean) and `statementToSMT` (Diagnosis.lean).

**Commit:** (pending)

---

## Comment 7: No partial evaluation in B3? ✅ RESPONDED

**File:** `StrataTest/Languages/B3/Verifier/VerifierTests.lean`
**Line:** 485
**Comment:**
> I take it from this test this is no B3 partial evaluation, right?
**Status:** ✅ Clarified by user

**Response:** User confirmed this is correct - B3 doesn't do partial evaluation, it translates directly to SMT terms and lets the SMT.Factory layer handle constant folding.

---

## Comment 8: Declaration ordering and dependencies ✅ RESPONDED

**File:** `Strata/Languages/B3/Transform/FunctionToAxiom.lean`
**Line:** 154
**Comment:**
> Makes sense, but it seems a little strange to me that getting things in the correct order is bound up with generating axioms for functions (with another function encoding, we would still need to make sure the order is consistent). And this doesn't even completely enforce the right order, since I don't think it deals with dependencies between e.g. two functions, one of which calls the other.
**Status:** ✅ Clarified

**Note:** The ordering is: types → function declarations → axioms → other. This is correct for SMT-LIB where sorts must come before functions, and function declarations before axioms. Function-to-function dependencies don't matter for declarations (only for axioms), and the current ordering handles this correctly.

---

## Comment 9: Remove bullet points from Formatter.lean docstring

**File:** `Strata/Languages/B3/Verifier/Formatter.lean`
**Comment:**
> I don't think we need these bullets here personally.
**Current Code:**
```lean
This module uses `SMTDDM.toString` which translates SMT terms to the SMT dialect's
AST and then uses the dialect's formatter to generate SMT-LIB strings. This approach:
- Is more efficient than string interpolation
- Produces direct, readable SMT-LIB output (no A-normal form)
- Leverages the existing SMT dialect infrastructure
- Ensures consistency with other SMT formatting in Strata
```

**Recommendation:** **Accept** - Simplify the docstring to be more concise without the bullet points.

**Effort:** Trivial

---

## Comment 9: Remove bullet points from Formatter.lean docstring ✅ DONE

**File:** `Strata/Languages/B3/Verifier/Formatter.lean`
**Comment:**
> I don't think we need these bullets here personally.
**Status:** ✅ Fixed

**Change Applied:** Simplified docstring to remove bullet points, keeping just the essential description.

**Commit:** (pending)

---

## Summary

**Total Comments:** 9

**Status:**
-**Fixed:** 6 (Comments 1, 2, 3, 4, 5, 6, 9)
-**Responded:** 2 (Comments 7, 8)

**All comments addressed!**
37 changes: 20 additions & 17 deletions Strata/DL/SMT/DDMTransform/Parse.lean
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ def specialCharsInSimpleSymbol := [
("caret", "^"),
("lt", "<"),
("gt", ">"),
("at", "@")
("at", "@"),
("le", "<="),
("ge", ">="),
("implies", "=>")
]

-- https://smt-lib.org/papers/smt-lib-reference-v2.7-r2025-07-07.pdf
Expand Down Expand Up @@ -159,7 +162,7 @@ category Symbol;
op symbol (@[unwrap] s:SimpleSymbol) : Symbol => s;

category Keyword;
op kw_symbol (@[unwrap] s:SimpleSymbol) : Keyword => ":" s;
op kw_symbol (@[unwrap] s:SimpleSymbol) : Keyword => ":" s:0;


// 2. S-expressions
Expand All @@ -180,12 +183,12 @@ op sc_numeral_neg (@[unwrap] n:Num) : SpecConstant => "-" n:0;
op sc_decimal_neg (@[unwrap] n:Decimal) : SpecConstant => "-" n:0;

category SExpr;
op se_spec_const (s:SpecConstant) : SExpr => s;
op se_symbol (s:Symbol) : SExpr => s;
op se_reserved (s:Reserved) : SExpr => s;
op se_keyword (s:Keyword) : SExpr => s;
op se_spec_const (s:SpecConstant) : SExpr => s:0;
op se_symbol (s:Symbol) : SExpr => s:0;
op se_reserved (s:Reserved) : SExpr => s:0;
op se_keyword (s:Keyword) : SExpr => s:0;

op se_ls (s:SpaceSepBy SExpr) : SExpr => "(" s ")";
op se_ls (s:SpaceSepBy SExpr) : SExpr => "(" s:0 ")";


category SMTIdentifier;
Expand All @@ -211,12 +214,12 @@ op smtsort_param (s:SMTIdentifier, @[nonempty] sl:SpaceSepBy SMTSort) : SMTSort

// 5. Attributes
category AttributeValue;
op av_spec_constant (s:SpecConstant) : AttributeValue => s;
op av_symbol (s:Symbol) : AttributeValue => s;
op av_sel (s:Seq SExpr) : AttributeValue => "(" s ")";
op av_spec_constant (s:SpecConstant) : AttributeValue => s:0;
op av_symbol (s:Symbol) : AttributeValue => s:0;
op av_sel (s:Seq SExpr) : AttributeValue => "(" s:0 ")";

category Attribute;
op att_kw (k:Keyword, av:Option AttributeValue) : Attribute => k av;
op att_kw (k:Keyword, av:Option AttributeValue) : Attribute => k:0 " " av:0;


// 6. Terms
Expand All @@ -239,18 +242,18 @@ op sorted_var (s:Symbol, so:SMTSort) : SortedVar => "(" s " " so ")";
op spec_constant_term (sc:SpecConstant) : Term => sc;
op qual_identifier (qi:QualIdentifier) : Term => qi;
op qual_identifier_args (qi:QualIdentifier, @[nonempty] ts:SpaceSepBy Term) : Term =>
"(" qi " " ts ")";
"(" qi " " ts:0 ")";

op let_smt (@[nonempty] vbps: SpaceSepBy ValBinding, t:Term) : Term =>
"(" "let" "(" vbps ")" t ")";
"(" "let " "(" vbps ")" t ")";
op lambda_smt (@[nonempty] svs: SpaceSepBy SortedVar, t:Term) : Term =>
"(" "lambda" "(" svs ")" t ")";
"(" "lambda " "(" svs ")" t ")";
op forall_smt (@[nonempty] svs: SpaceSepBy SortedVar, t:Term) : Term =>
"(" "forall" "(" svs ")" t ")";
"(" "forall " "(" svs ") " t ")";
op exists_smt (@[nonempty] svs: SpaceSepBy SortedVar, t:Term) : Term =>
"(" "exists" "(" svs ")" t ")";
"(" "exists " "(" svs ") " t ")";
op bang (t:Term, @[nonempty] attrs:SpaceSepBy Attribute) : Term =>
"(" "!" t " " attrs ")";
"(" "! " t:0 " " attrs:0 ")";


// 7. Theories
Expand Down
64 changes: 61 additions & 3 deletions Strata/DL/SMT/DDMTransform/Translate.lean
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ private def mkSimpleSymbol (s:String):SimpleSymbol SourceRange :=
| "lt" => .simple_symbol_lt SourceRange.none
| "gt" => .simple_symbol_gt SourceRange.none
| "at" => .simple_symbol_at SourceRange.none
| "le" => .simple_symbol_le SourceRange.none
| "ge" => .simple_symbol_ge SourceRange.none
| "implies" => .simple_symbol_implies SourceRange.none
| _ => panic! s!"Unknown simple symbol: {name}")
| .none =>
.simple_symbol_qid SourceRange.none (mkQualifiedIdent s)
Expand Down Expand Up @@ -110,6 +113,35 @@ private def translateFromTermType (t:SMT.TermType):
else
return .smtsort_param srnone (mkIdentifier id) (Ann.mk srnone argtys_array)

-- Helper function to convert a SMTDDM.Term to SExpr for use in pattern attributes
def termToSExpr (t : SMTDDM.Term SourceRange) : SMTDDM.SExpr SourceRange :=
let srnone := SourceRange.none
match t with
| .qual_identifier _ qi =>
match qi with
| .qi_ident _ iden =>
match iden with
| .iden_simple _ sym => .se_symbol srnone sym
| _ => .se_symbol srnone (.symbol srnone (.simple_symbol_qid srnone (mkQualifiedIdent "term")))
| _ => .se_symbol srnone (.symbol srnone (.simple_symbol_qid srnone (mkQualifiedIdent "term")))
| .qual_identifier_args _ qi args =>
-- Function application in pattern: convert to nested S-expr
let qiSExpr := match qi with
| .qi_ident _ iden =>
match iden with
| .iden_simple _ sym => SMTDDM.SExpr.se_symbol srnone sym
| _ => .se_symbol srnone (.symbol srnone (.simple_symbol_qid srnone (mkQualifiedIdent "fn")))
| _ => .se_symbol srnone (.symbol srnone (.simple_symbol_qid srnone (mkQualifiedIdent "fn")))
-- Convert args array to SExpr list
let argsSExpr := args.val.map termToSExpr
.se_ls srnone (Ann.mk srnone ((qiSExpr :: argsSExpr.toList).toArray))
| _ => .se_symbol srnone (.symbol srnone (.simple_symbol_qid srnone (mkQualifiedIdent "term")))
decreasing_by
cases args
rename_i hargs
have := Array.sizeOf_lt_of_mem hargs
simp_all; omega

def translateFromTerm (t:SMT.Term): Except String (SMTDDM.Term SourceRange) := do
let srnone := SourceRange.none
match t with
Expand All @@ -126,7 +158,7 @@ def translateFromTerm (t:SMT.Term): Except String (SMTDDM.Term SourceRange) := d
else
return (.qual_identifier_args srnone
(.qi_ident srnone (mkIdentifier op.mkName)) (Ann.mk srnone args_array))
| .quant qkind args _tr body =>
| .quant qkind args tr body =>
let args_sorted:List (SMTDDM.SortedVar SourceRange) <-
args.mapM
(fun ⟨name,ty⟩ => do
Expand All @@ -137,11 +169,37 @@ def translateFromTerm (t:SMT.Term): Except String (SMTDDM.Term SourceRange) := d
throw "empty quantifier"
else
let body <- translateFromTerm body

-- Handle triggers/patterns
let bodyWithPattern <-
match tr with
| .app .triggers triggerTerms .trigger =>
if triggerTerms.isEmpty then
-- No patterns - return body as-is
pure body
else
-- Convert each trigger term to a SMTDDM.Term, then to SExpr
let triggerDDMTerms <- triggerTerms.mapM translateFromTerm
let triggerSExprs := triggerDDMTerms.map termToSExpr

-- Create the :pattern attribute
-- av_sel wraps the SExprs in parens, so we pass the array directly
let patternAttr : SMTDDM.Attribute SourceRange :=
.att_kw srnone
(.kw_symbol srnone (mkSimpleSymbol "pattern"))
(Ann.mk srnone (some (.av_sel srnone (Ann.mk srnone triggerSExprs.toArray))))

-- Wrap body with bang operator and pattern attribute
pure (.bang srnone body (Ann.mk srnone #[patternAttr]))
| _ =>
-- Unexpected trigger format - return body as-is
pure body

match qkind with
| .all =>
return .forall_smt srnone (Ann.mk srnone args_array) body
return .forall_smt srnone (Ann.mk srnone args_array) bodyWithPattern
| .exist =>
return .exists_smt srnone (Ann.mk srnone args_array) body
return .exists_smt srnone (Ann.mk srnone args_array) bodyWithPattern


private def dummy_prg_for_toString :=
Expand Down
2 changes: 1 addition & 1 deletion Strata/DL/SMT/Op.lean
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def Op.mkName : Op → String
| .not => "not"
| .and => "and"
| .or => "or"
| .eq => "eq"
| .eq => "="
| .ite => "ite"
| .implies => "=>"
| .distinct => "distinct"
Expand Down
Loading
Loading