Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
a47df62
Improve elab-time performance of Lean terms generated by DDM. (#221)
joehendrix Dec 1, 2025
7d87684
Refactor SemanticEval to receive only one SemanticStore (#213)
aqjune-aws Dec 1, 2025
dc17f40
Models for relevant regular expression operations (#218)
shigoel Dec 2, 2025
574e765
Andrewmwells/pyanalyze tests (#249)
andrewmwells-amazon Dec 2, 2025
7b6a572
Add datatypes to `LContext` (#238)
joscoh Dec 3, 2025
6f9330c
Update pyTranslate and pyAnalyze to use compile time Python dialect (…
joehendrix Dec 4, 2025
248c22c
feat: Create generators for well-typed LExprs. (#258)
codyroux Dec 4, 2025
e1c5e2b
Add all executables to default targets (#237)
vjjocius Dec 5, 2025
f9be351
pyanalyze burndown (#252)
andrewmwells-amazon Dec 5, 2025
6a647e4
Change `Imperative.Stmt` to remove `Block` mutual recursion (#216)
joscoh Dec 5, 2025
f3bf3a5
Add Laurel grammar and transformation
keyboardDrummer Dec 9, 2025
4589663
refactoring
keyboardDrummer Dec 9, 2025
037a7d1
Fixes
keyboardDrummer Dec 9, 2025
1c9cfd1
Moved tests
keyboardDrummer Dec 9, 2025
3a3809c
Fix grammar test
keyboardDrummer Dec 9, 2025
927b0bb
Getting there
keyboardDrummer Dec 9, 2025
faa49df
TestExamples test passes
keyboardDrummer Dec 9, 2025
4481959
Refactoring
keyboardDrummer Dec 9, 2025
c600cf1
Fix
keyboardDrummer Dec 9, 2025
9cef91e
Support Datetime (#266)
aqjune-aws Dec 9, 2025
94e1af3
Generalize reflexive transitive closure (#267)
joscoh Dec 9, 2025
25df923
Revert AdvancedMaps changes
keyboardDrummer Dec 10, 2025
3c933e5
Add missing license headers
keyboardDrummer Dec 10, 2025
f182891
Revert RealBitVector
keyboardDrummer Dec 10, 2025
5bc8abd
Tweaks
keyboardDrummer Dec 10, 2025
fe2a831
Save state
keyboardDrummer Dec 10, 2025
2cd178c
Refactoring
keyboardDrummer Dec 10, 2025
12946cf
Refactoring
keyboardDrummer Dec 10, 2025
b12d781
Cleanup
keyboardDrummer Dec 10, 2025
75cc85f
Merge branch 'main' into laurelParsing
keyboardDrummer Dec 10, 2025
84235b4
Fix Laurel/TestGrammar
keyboardDrummer Dec 10, 2025
cffb991
Merge branch 'laurelParsing' of github.com:keyboardDrummer/Strata int…
keyboardDrummer Dec 10, 2025
a3e0856
Fix alpha equivalence for Boogie programs (#265)
joscoh Dec 10, 2025
00d8b83
Minor cleanups - particularly to Python DDM code (#260)
joehendrix Dec 11, 2025
b2ae3dc
Move Boogie examples
keyboardDrummer Dec 11, 2025
ea3438f
Rename
keyboardDrummer Dec 11, 2025
977786d
Add more Laurel examples (#228)
keyboardDrummer Dec 11, 2025
4aa17a2
Update DialectMap to include closure proof (#235)
joehendrix Dec 11, 2025
77aa05a
Merge remote-tracking branch 'origin' into laurelParsing
keyboardDrummer Dec 15, 2025
fbe4de5
Move back Boogie examples
keyboardDrummer Dec 15, 2025
e827d76
Remove white line
keyboardDrummer Dec 15, 2025
79fbeb9
Remove duplication
keyboardDrummer Dec 15, 2025
0ea1bbb
Fix test
keyboardDrummer Dec 15, 2025
3160a8c
Bump lean-toolchain to v4.25.2 (#273)
joehendrix Dec 15, 2025
a496a14
Merge remote-tracking branch 'origin/main' into laurelParsing
keyboardDrummer Dec 16, 2025
245f7ad
Fix after merge
keyboardDrummer Dec 16, 2025
95bb904
Fix
keyboardDrummer Dec 16, 2025
1d19b86
Fix oops
keyboardDrummer Dec 16, 2025
125bf17
Fix warning
keyboardDrummer Dec 16, 2025
1646019
Add DDM unwrap metadata (#261)
MikaelMayer Dec 16, 2025
c27615e
Turn Strata Python bindings into native namespace package (#276)
ssomayyajula Dec 16, 2025
52c0eb0
Support for classes (#270)
andrewmwells-amazon Dec 16, 2025
872a746
Fix pyAnalyze CI (#278)
andrewmwells-amazon Dec 17, 2025
492cd53
Hide counterexamples when verbose flag is false (#271)
vjjocius Dec 17, 2025
30d59b1
Boogie lexpr gen + generator bug fix (#272)
codyroux Dec 17, 2025
9efa44a
Undo bad changes
keyboardDrummer Dec 17, 2025
e328a48
Move examples from `Strata` to `StrataTest` to reduce build time (#274)
keyboardDrummer Dec 17, 2025
5ce8f20
feat(DDM): Add Bool support to DDM core (#255)
MikaelMayer Dec 17, 2025
eae1536
Merge branch 'main' into laurelParsing
keyboardDrummer Dec 18, 2025
7e16741
Merge remote-tracking branch 'origin/main' into laurelParsing
keyboardDrummer Dec 18, 2025
f711bdc
Merge branch 'laurelParsing' of github.com:keyboardDrummer/Strata int…
keyboardDrummer Dec 18, 2025
b3c66a3
Fix
keyboardDrummer Dec 18, 2025
d5d3a57
Bump to v4.26.0 (#281)
joehendrix Dec 18, 2025
1e1be4c
Switch Z3 timeout from soft to hard (#284)
andrewmwells-amazon Dec 18, 2025
197dddb
Add more concrete evaluators for bit-vector operations in Boogie (#275)
aqjune-aws Dec 18, 2025
ee0f0f9
PyAnalyze While and FloorDiv (#283)
andrewmwells-amazon Dec 18, 2025
22e10d7
Strata language definition document (#186)
atomb Dec 18, 2025
dca53ec
Z3 -T param takes seconds (#286)
andrewmwells-amazon Dec 18, 2025
c32a3d5
Move file
keyboardDrummer Dec 19, 2025
44c4082
Merge remote-tracking branch 'origin/main' into laurelParsing
keyboardDrummer Dec 19, 2025
d803b56
Fixes
keyboardDrummer Dec 19, 2025
b0de596
Extend PythonToBoogie to use signatures database (#279)
joehendrix Dec 19, 2025
8733c69
PyAnalyze run multiple Z3 configs in parallel. (#288)
andrewmwells-amazon Dec 22, 2025
5432464
feat(DDM): Add pipe-delimited identifier support (#285)
MikaelMayer Dec 22, 2025
9856651
Fix TestGrammar
keyboardDrummer Dec 23, 2025
f6dfea9
Merge branch 'main' into laurelParsing
keyboardDrummer Dec 23, 2025
e26c206
feat(DDM): Support dots in identifiers (#293)
MikaelMayer Dec 23, 2025
f8a9a67
Merge branch 'main' into laurelParsing
shigoel Dec 24, 2025
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
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ jobs:
run: .github/scripts/checkLeanImport.sh

build_doc:
name: Build Documentation
name: Build documentation
runs-on: ubuntu-latest
permissions:
contents: read
Expand All @@ -126,10 +126,10 @@ jobs:
uses: leanprover/lean-action@v1
with:
build-args: '--wfail'
lake-package-directory: 'docs/ddm'
- name: Build Documentation
run: lake exe docs
working-directory: docs/ddm
lake-package-directory: 'docs/verso'
- name: Build documentation
run: ./generate.sh
working-directory: docs/verso

build_python:
name: Build and test Python
Expand Down
8 changes: 4 additions & 4 deletions Examples/dialects/Arith.dialect.st
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn sub_expr (a : Int, b : Int) : Int => @[prec(25), leftassoc] a " - " b;
fn mul_expr (a : Int, b : Int) : Int => @[prec(30), leftassoc] a " * " b;
fn exp_expr (a : Int, b : Int) : Int => @[prec(32), rightassoc] a " ^ " b;

fn le (a : Int, b : Int) : Bool => @[prec(15)] a " <= " b;
fn lt (a : Int, b : Int) : Bool => @[prec(15)] a " < " b;
fn ge (a : Int, b : Int) : Bool => @[prec(15)] a " >= " b;
fn gt (a : Int, b : Int) : Bool => @[prec(15)] a " > " b;
fn le (a : Int, b : Int) : BoolType => @[prec(15)] a " <= " b;
fn lt (a : Int, b : Int) : BoolType => @[prec(15)] a " < " b;
fn ge (a : Int, b : Int) : BoolType => @[prec(15)] a " >= " b;
fn gt (a : Int, b : Int) : BoolType => @[prec(15)] a " > " b;
20 changes: 10 additions & 10 deletions Examples/dialects/Bool.dialect.st
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
dialect Bool;
// Introduce Boolean type
type Bool;

// Introduce literals as constants.
fn true_lit : Bool => "true";
fn false_lit : Bool => "false";
// BoolType for use in function signatures
type BoolType;

// Function to lift Init.Bool literals to expressions
fn boolLit (b : Bool) : BoolType => b;

// Introduce basic Boolean operations.
fn not_expr (tp : Type, a : tp) : tp => "-" a;
fn and (a : Bool, b : Bool) : Bool => @[prec(10), leftassoc] a " && " b;
fn or (a : Bool, b : Bool) : Bool => @[prec(8), leftassoc] a " || " b;
fn imp (a : Bool, b : Bool) : Bool => @[prec(8), leftassoc] a " ==> " b;
fn and (a : BoolType, b : BoolType) : BoolType => @[prec(10), leftassoc] a " && " b;
fn or (a : BoolType, b : BoolType) : BoolType => @[prec(8), leftassoc] a " || " b;
fn imp (a : BoolType, b : BoolType) : BoolType => @[prec(8), leftassoc] a " ==> " b;

// Introduce equality operations that work for arbitrary types.
// The type is inferred.
fn equal (tp : Type, a : tp, b : tp) : Bool => @[prec(15)] a " == " b;
fn not_equal (tp : Type, a : tp, b : tp) : Bool => @[prec(15)] a " != " b;
fn equal (tp : Type, a : tp, b : tp) : BoolType => @[prec(15)] a " == " b;
fn not_equal (tp : Type, a : tp, b : tp) : BoolType => @[prec(15)] a " != " b;
8 changes: 0 additions & 8 deletions Strata.lean
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,8 @@ import Strata.DL.Lambda.Lambda
import Strata.DL.Imperative.Imperative

/- Boogie -/
import Strata.Languages.Boogie.Examples.Examples
import Strata.Languages.Boogie.StatementSemantics

/- CSimp -/
import Strata.Languages.C_Simp.Examples.Examples

/- Dyn -/
import Strata.Languages.Dyn.Examples.Examples


/- Code Transforms -/
import Strata.Transform.CallElimCorrect
import Strata.Transform.DetToNondetCorrect
Expand Down
2 changes: 1 addition & 1 deletion Strata/Backends/CBMC/BoogieToCBMC.lean
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ partial def blockToJson {P : Imperative.PureExpr} (I : Lambda.LExprParams) [Iden
("statement", Json.mkObj [("id", "block")]),
("type", emptyType)
]),
("sub", Json.arr (b.ss.map (stmtToJson (I:=I) · loc)).toArray)
("sub", Json.arr (b.map (stmtToJson (I:=I) · loc)).toArray)
]

partial def stmtToJson {P : Imperative.PureExpr} (I : Lambda.LExprParams) [IdentToStr (Lambda.Identifier I.IDMeta)] [HasLExpr P I]
Expand Down
2 changes: 1 addition & 1 deletion Strata/Backends/CBMC/StrataToCBMC.lean
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ partial def blockToJson (b: Imperative.Block Strata.C_Simp.Expression Strata.C_S
("statement", Json.mkObj [("id", "block")]),
("type", emptyType)
]),
("sub", Json.arr (b.ss.map (stmtToJson · loc)).toArray)
("sub", Json.arr (b.map (stmtToJson · loc)).toArray)
]

partial def stmtToJson (e : Strata.C_Simp.Statement) (loc: SourceLoc) : Json :=
Expand Down
159 changes: 127 additions & 32 deletions Strata/DDM/AST.lean
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,23 @@ import Std.Data.HashMap
import Strata.DDM.Util.Array
import Strata.DDM.Util.ByteArray
import Strata.DDM.Util.Decimal
import Std.Data.HashMap.Lemmas

set_option autoImplicit false

namespace Strata.Array

theorem mem_iff_back_or_pop {α} (a : α) {as : Array α} (p : as.size > 0 := by get_elem_tactic) :
a ∈ as ↔ (a = as.back ∨ a ∈ as.pop) := by
simp [Array.mem_iff_getElem]
grind

theorem of_mem_pop {α} {a : α} {as : Array α} : a ∈ as.pop → a ∈ as := by
simp [Array.mem_iff_getElem]
grind

end Strata.Array

namespace Strata

abbrev DialectName := String
Expand Down Expand Up @@ -175,7 +189,7 @@ inductive ArgF (α : Type) : Type where
| expr (e : ExprF α)
| type (e : TypeExprF α)
| ident (ann : α) (i : String)
| num (ann : α)(v : Nat)
| num (ann : α) (v : Nat)
| decimal (ann : α) (v : Decimal)
| strlit (ann : α) (i : String)
| bytes (ann : α) (a : ByteArray)
Expand Down Expand Up @@ -303,9 +317,9 @@ As an example, in the string `"123abc\ndef"`, the string
-/
structure SourceRange where
/-- The starting offset of the source range. -/
start : String.Pos
start : String.Pos.Raw
/-- One past the end of the range. -/
stop : String.Pos
stop : String.Pos.Raw
deriving BEq, Inhabited, Repr

namespace SourceRange
Expand Down Expand Up @@ -587,7 +601,8 @@ inductive SyntaxDefAtom
-- Surround with parenthesis if the precedence of the argument is less than `prec`.
-- Note. If `prec` is zero, then parenthesis will never be added (even with pp.parens is true).
-- This is to avoid parens in categories that do not support them.
| ident (level : Nat) (prec : Nat)
-- The unwrap parameter specifies if the value should be unwrapped to a raw type.
| ident (level : Nat) (prec : Nat) (unwrap : Bool := false)
| str (lit : String)
| indent (n : Nat) (args : Array SyntaxDefAtom)
deriving BEq, Inhabited, Repr
Expand Down Expand Up @@ -1160,12 +1175,18 @@ instance {α β} [BEq α] [Hashable α] [BEq β]: BEq (Std.HashMap α β) where

structure DialectMap where
map : Std.HashMap DialectName Dialect
deriving BEq, Inhabited
closed : ∀(d : DialectName) (p: d ∈ map), map[d].imports.all (· ∈ map)

namespace DialectMap

instance : BEq DialectMap where
beq x y := x.map == y.map

instance : EmptyCollection DialectMap where
emptyCollection := .mk {}
emptyCollection := { map := {}, closed := by simp }

instance : Inhabited DialectMap where
default := {}

instance : Membership DialectName DialectMap where
mem m d := d ∈ m.map
Expand All @@ -1178,23 +1199,61 @@ instance : GetElem? DialectMap DialectName Dialect (fun m d => d ∈ m) where
getElem? m d := m.map[d]?
getElem! m d := m.map[d]!

/--
This inserts a new dialect into the dialect map.

This requires propositions to ensure we do not change the semantics
of dialects and imports are already in dialect.
-/
def insert (m : DialectMap) (d : Dialect) (_d_new : d.name ∉ m) (d_imports_ok : d.imports.all (· ∈ m)) : DialectMap :=
{ map := m.map.insert d.name d
closed := by
intro name mem
if eq : d.name = name then
simp at d_imports_ok
simp [eq]
intro i lt
exact Or.inr (d_imports_ok i lt)
else
simp only [Std.HashMap.mem_insert, eq, beq_iff_eq, false_or] at mem
have cl := m.closed name mem
simp at cl
simp [Std.HashMap.getElem_insert, eq]
intro i lt
exact Or.inr (cl i lt)
}

/--
This inserts a dialect in to the dialect map.

It panics if a dialect with the same name is already in the map
or if the dialect imports a dialect not already in the map.
-/
def insert! (m : DialectMap) (d : Dialect) : DialectMap :=
assert! d.name ∉ m
assert! d.imports.all (· ∈ m)
{ map := m.map.insert d.name d }
if d_new : d.name ∈ m then
panic! s!"{d.name} already in map."
else
if d_imports_ok : d.imports.all (· ∈ m) then
m.insert d d_new d_imports_ok
else
panic! s!"Missing import."

def ofList! (l : List Dialect) : DialectMap :=
let m := l.foldl (init := {}) fun m d =>
assert! d.name ∉ m;
m.insert d.name d
assert! l.all fun d => d.imports.all (· ∈ m)
{ map := m }
let map : Std.HashMap DialectName Dialect :=
l.foldl (init := .emptyWithCapacity l.length) fun m d =>
m.insert d.name d
let check := map.toArray.all fun (nm, d) => d.imports.all (· ∈ map)
if p : check then
{ map := map,
closed := by
intro name name_mem
simp only [check, Array.all_eq_true_iff_forall_mem (xs := map.toArray)] at p
have mem : (name, map[name]) ∈ map.toArray := by
simp [Std.HashMap.mem_toArray_iff_getElem?_eq_some]
exact p (name, map[name]) mem
}
else
panic! "Invalid list"

def toList (m : DialectMap) : List Dialect := m.map.values

Expand All @@ -1216,24 +1275,60 @@ Return set of all dialects that are imported by `dialect`.

This includes transitive imports.
-/
partial def importedDialects! (map : DialectMap) (dialect : DialectName) : DialectMap := aux (.ofList [(d.name, d)]) [d]
where d :=
match map[dialect]? with
| none => panic! s!"Unknown dialect {dialect}"
| some d => d
aux (all : Std.HashMap DialectName Dialect) (next : List Dialect) : DialectMap :=
match next with
| d :: next =>
let (all, next) := d.imports.foldl (init := (all, next)) fun (all, next) i =>
if i ∈ all then
(all, next)
else
let d := match map[i]? with
| none => panic! s!"Unknown dialect {i}"
| some d => d
(all.insert i d, d :: next)
aux all next
| [] => DialectMap.mk all
partial def importedDialects (dm : DialectMap) (dialect : DialectName) (p : dialect ∈ dm) : DialectMap :=
aux {} #[dialect] (by simp; exact p) (by simp)
where aux (map : Std.HashMap DialectName Dialect)
(next : Array DialectName)
(nextp : ∀name, name ∈ next → name ∈ dm)
(inv : ∀name (mem : name ∈ map), map[name].imports.all (fun i => i ∈ map ∨ i ∈ next))
: DialectMap :=
if emptyP : next.isEmpty then
{ map := map,
closed := by intro d mem; grind
}
else
have next_size_pos : next.size > 0 := by
simp only [Array.isEmpty_iff] at emptyP
grind
let name := next.back (h := next_size_pos)
if name_mem : name ∈ map then
aux map next.pop
(by
intro d p
exact nextp _ (Array.of_mem_pop p))
(by
simp only [Array.all_eq_true']
intro d d_mem e e_mem
simp only [Array.all_eq_true'] at inv
have inv2 := inv d d_mem e e_mem
simp only [Array.mem_iff_back_or_pop e next_size_pos] at inv2
grind)
else
have name_in_dm : name ∈ dm := nextp name (by grind)
let d := dm[name]
aux (map.insert name d) (next.pop ++ d.imports)
(by
intro nm nm_mem
simp at nm_mem
match nm_mem with
| .inl nm_mem =>
exact nextp _ (Array.of_mem_pop nm_mem)
| .inr nm_mem =>
have inv := dm.closed name name_in_dm
simp only [Array.all_eq_true'] at inv
have inv2 := inv nm nm_mem
simp at inv2
exact inv2)
(by
intro n n_mem
if n_eq : name = n then
simp [n_eq]
else
simp [n_eq] at n_mem
simp [n_eq, Std.HashMap.getElem_insert]
intro i lt
have mem := Array.mem_iff_back_or_pop (map[n].imports[i]) next_size_pos
grind)

end DialectMap

Expand Down
14 changes: 14 additions & 0 deletions Strata/DDM/BuiltinDialects/Init.lean
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ def initDialect : Dialect := BuiltinM.create! "Init" #[] do
declareAtomicCat q`Init.Decimal
declareAtomicCat q`Init.Str

declareCat q`Init.Bool
declareOp {
name := "boolTrue",
argDecls := .empty,
category := q`Init.Bool,
syntaxDef := .ofList [.str "true"],
}
declareOp {
name := "boolFalse",
argDecls := .empty,
category := q`Init.Bool,
syntaxDef := .ofList [.str "false"],
}

declareCat q`Init.Option #["a"]

declareCat q`Init.Seq #["a"]
Expand Down
1 change: 1 addition & 0 deletions Strata/DDM/BuiltinDialects/StrataDDL.lean
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def StrataDDL : Dialect := BuiltinM.create! "StrataDDL" #[initDialect] do
declareMetadata { name := "rightassoc", args := #[] }

declareMetadata { name := "scope", args := #[.mk "scope" .ident] }
declareMetadata { name := "unwrap", args := #[] }
declareMetadata { name := "declareType", args := #[.mk "name" .ident, .mk "args" (.opt .ident)] }
declareMetadata { name := "aliasType", args := #[.mk "name" .ident, .mk "args" (.opt .ident), .mk "def" .ident] }
declareMetadata { name := "declare", args := #[.mk "name" .ident, .mk "type" .ident] }
Expand Down
Loading