Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
1fb0a12
Add opaque keyword to Laurel grammar
keyboardDrummer-bot Apr 19, 2026
3e8d949
Disallow transparent statement bodies on non-functional procedures
keyboardDrummer-bot Apr 19, 2026
c7ad4a9
Merge add-opaque-keyword branch and use opaque instead of ensures true
keyboardDrummer-bot Apr 19, 2026
2664cc5
Remove checkTransparentBodies option; make Python pipeline use opaque…
keyboardDrummer-bot Apr 19, 2026
63d884d
Merge main into disallow-transparent-statement-bodies
keyboardDrummer-bot Apr 19, 2026
2ac415f
Merge upstream/main into add-opaque-keyword
keyboardDrummer-bot Apr 19, 2026
037dd83
Fix CI failures: grammar formatting, parser fallback, and missing opa…
keyboardDrummer-bot Apr 19, 2026
7265e2f
Fix CI: include opaque-with-body procedures in inlinableProcedures
keyboardDrummer-bot Apr 19, 2026
976eb51
Update golden-file expected outputs for kwargs tests
keyboardDrummer-bot Apr 19, 2026
9d4c6ee
Update golden-file expected outputs for class tests
keyboardDrummer-bot Apr 19, 2026
405fd0a
Update LaurelGrammar
keyboardDrummer Apr 20, 2026
2387080
Grammar fix so ensures clauses without opaque are not dropped
keyboardDrummer Apr 20, 2026
edf5a72
Fix AbstractToConcreteTreeTranslator to nest ensures/modifies inside …
keyboardDrummer-bot Apr 20, 2026
7dbd727
Merge remote-tracking branch 'fork/add-opaque-keyword' into disallow-…
keyboardDrummer Apr 21, 2026
862d882
Undo expect file changes
keyboardDrummer Apr 21, 2026
107afed
Update comment
keyboardDrummer Apr 21, 2026
b531ee5
Add wildcard modifies clause support (`modifies *`)
keyboardDrummer-bot Apr 21, 2026
e3fe027
Update test
keyboardDrummer Apr 21, 2026
2da0f74
Merge branch 'main' into add-opaque-keyword
tautschnig Apr 22, 2026
89c6836
Add opaque keyword to StatisticsTest Laurel snippets
keyboardDrummer-bot Apr 22, 2026
cf00cb0
Make type of Assign more specific
keyboardDrummer-bot Apr 22, 2026
67e75cd
Remove multiAssign grammar rule that causes parsing ambiguity
keyboardDrummer-bot Apr 22, 2026
89e1d37
Replace LocalVariable with Variable.Declare
keyboardDrummer-bot Apr 22, 2026
27f11e4
Add multi-target assignment syntax and test for multiple returns
keyboardDrummer-bot Apr 22, 2026
76a487b
Use 'assign' keyword prefix for multi-target assignments
keyboardDrummer-bot Apr 23, 2026
4a0d5cc
Address review feedback: error on invalid assign targets, restore hea…
keyboardDrummer-bot Apr 23, 2026
f7784c1
Add heap parameterization for multi-target assign calls
keyboardDrummer-bot Apr 23, 2026
dfd8c58
Add tests for repeated assign target and field assigns from heap-modi…
keyboardDrummer-bot Apr 23, 2026
151f955
Address review: use bug-obvious name in stmtExprToVar fallback, remov…
keyboardDrummer-bot Apr 23, 2026
578d40c
Fix lint warnings in HeapParameterization termination proofs
keyboardDrummer-bot Apr 23, 2026
cf43d15
Update golden files for assertion numbering changes
keyboardDrummer-bot Apr 23, 2026
b87f0cf
start of refactoring
keyboardDrummer Apr 23, 2026
348fa33
Fix bugs
keyboardDrummer Apr 23, 2026
98fe891
Simplify LaurelToCore assign translation
keyboardDrummer Apr 23, 2026
9aa12e0
Resolve sorrys in HeapParameterization proof
keyboardDrummer-bot Apr 23, 2026
2a3da0e
Merge main into issue-21-assign-variable-type
keyboardDrummer-bot Apr 23, 2026
674fcfa
Fix HeapParameterization and LaurelToCoreTranslator for new Variable-…
keyboardDrummer-bot Apr 23, 2026
66bc82b
Fix pre-existing test failures in DictNoneTest and AnalyzeLaurelTest
keyboardDrummer-bot Apr 23, 2026
7f8ad0e
Fix CI: skip Java TestGen test 12 gracefully when javac or jar is mis…
keyboardDrummer-bot Apr 23, 2026
0feec54
Add Resolution check for assign target count, remove LaurelToCore pad…
keyboardDrummer-bot Apr 23, 2026
6f1a531
Revert "Fix Python->Laurel: Havoc callee or Heap after unmodeled Inst…
keyboardDrummer Apr 23, 2026
c253ba7
Merge branch 'issue-21-assign-variable-type' of github.com:keyboardDr…
keyboardDrummer Apr 23, 2026
fea039a
Fixes
keyboardDrummer Apr 23, 2026
2b0b010
Resolve merge conflicts in PythonToLaurel and fix test expectations
keyboardDrummer-bot Apr 23, 2026
d31c0df
:Revert "Fix pre-existing test failures in DictNoneTest and AnalyzeLa…
keyboardDrummer Apr 23, 2026
dfc8fdf
Revert "Fix CI: skip Java TestGen test 12 gracefully when javac or ja…
keyboardDrummer Apr 23, 2026
70717c3
Merge branch 'issue-21-assign-variable-type' of github.com:keyboardDr…
keyboardDrummer Apr 23, 2026
185f9da
Use Declare targets in Assign to eliminate extraDecls in HeapParamete…
keyboardDrummer-bot Apr 23, 2026
a38fd43
Fix pre-existing test failures in DictNoneTest and TestGen
keyboardDrummer-bot Apr 23, 2026
22d347b
Use Declare targets instead of extraDecls in HeapParameterization
keyboardDrummer-bot Apr 23, 2026
5c131f5
Fix DictNoneTest: handle expected error inside callback so test passe…
keyboardDrummer-bot Apr 23, 2026
779b2af
Add `modifies *` wildcard support to Laurel
keyboardDrummer-bot Apr 23, 2026
93af49b
Retry CI: all checks pass locally
keyboardDrummer-bot Apr 23, 2026
9475765
Fix pyAnalyze expected output for test_class_methods and test_class_w…
keyboardDrummer-bot Apr 23, 2026
36c7d7e
Fix doc build: add persist-credentials: false to checkout step
keyboardDrummer-bot Apr 23, 2026
3df9e8a
Merge branch 'main' into issue-21-assign-variable-type
keyboardDrummer Apr 23, 2026
d55020c
Address review comments
keyboardDrummer-bot Apr 23, 2026
29a460c
Merge branch 'main' into add-modifies-wildcard
shigoel Apr 23, 2026
b410bb7
Maintain all modifies clauses in concrete grammar translation
keyboardDrummer-bot Apr 23, 2026
6e6563a
Merge branch 'main' into issue-21-assign-variable-type and revert Dic…
keyboardDrummer-bot Apr 24, 2026
50050a5
Add test for modifies * on transparent body (no ensures)
keyboardDrummer-bot Apr 24, 2026
143c09e
Merge branch 'main' into add-opaque-keyword
robin-aws Apr 24, 2026
c5ca718
Fix
keyboardDrummer Apr 27, 2026
e836f9d
Add test combining modifies c and modifies *
keyboardDrummer-bot Apr 27, 2026
a5b17b0
Merge remote-tracking branch 'origin/main' into issue-21-assign-varia…
keyboardDrummer Apr 27, 2026
a638b8c
Merge branch 'main' into add-modifies-wildcard
thanhnguyen-aws Apr 27, 2026
70f1012
Merge branch 'main' into add-modifies-wildcard
keyboardDrummer-bot Apr 28, 2026
9584b73
Merge upstream/main into issue-21-assign-variable-type, resolve confl…
keyboardDrummer-bot Apr 28, 2026
9be587d
Fix modifies wildcard tests for opaque keyword grammar
keyboardDrummer-bot Apr 28, 2026
f3e9511
Fix issues
keyboardDrummer Apr 28, 2026
3243df4
Merge branch 'add-modifies-wildcard' of github.com:strata-org/Strata …
keyboardDrummer Apr 28, 2026
e53d5e0
Remove temp files
keyboardDrummer Apr 28, 2026
6c549bd
Fix conflicts
keyboardDrummer Apr 28, 2026
d14b93e
Remove obsolete test
keyboardDrummer Apr 28, 2026
0b90c56
Fix test
keyboardDrummer Apr 28, 2026
36ece7d
Fix T22_MultipleReturns: add missing 'opaque' keyword
keyboardDrummer-bot Apr 28, 2026
6c5dcdb
Extract StmtExprMd.isWildcard predicate to eliminate duplication
keyboardDrummer-bot Apr 28, 2026
71a4357
Merge branch 'main' into add-modifies-wildcard
tautschnig Apr 28, 2026
9f96122
Add more resolution checks
keyboardDrummer Apr 28, 2026
afff624
Add Laurel tests for resolution kind-mismatch errors
keyboardDrummer-bot Apr 28, 2026
77b18a8
Merge upstream/main into issue-21-assign-variable-type, resolve confl…
keyboardDrummer-bot Apr 28, 2026
bcfccb6
Merge branch 'main' into moreResolutionChecks
olivier-aws Apr 29, 2026
fc6c280
Merge remote-tracking branch 'origin/moreResolutionChecks' into issue…
keyboardDrummer Apr 29, 2026
ea85952
Do not generate core on pass diagnostics
keyboardDrummer Apr 29, 2026
198034b
Merge commit 'fe4578675012~1' into disallow-transparent-statement-bodies
keyboardDrummer Apr 29, 2026
c318dea
Merge remote-tracking branch 'fork/add-opaque-keyword' into disallow-…
keyboardDrummer Apr 29, 2026
6e057c9
Merge commit 'fe4578675012' into disallow-transparent-statement-bodies
keyboardDrummer Apr 29, 2026
b0ea928
Merge branch 'main' into add-modifies-wildcard
keyboardDrummer-bot Apr 29, 2026
e5d9752
Merge remote-tracking branch 'origin/main' into disallow-transparent-…
keyboardDrummer Apr 29, 2026
2c94491
Fix test
keyboardDrummer Apr 29, 2026
feaa876
Fix: don't skip core translation when pass diagnostics exist
keyboardDrummer-bot Apr 29, 2026
83c490b
Fixes
keyboardDrummer Apr 29, 2026
6a1d196
Remove gitignore addition
keyboardDrummer Apr 29, 2026
4fb9d74
Revert "Fix: don't skip core translation when pass diagnostics exist"
keyboardDrummer Apr 29, 2026
87c87f3
Fix test
keyboardDrummer Apr 29, 2026
d9404aa
update tests
keyboardDrummer Apr 29, 2026
2b9f2b0
Update tests
keyboardDrummer Apr 29, 2026
b68b31a
Merge remote-tracking branch 'origin/add-modifies-wildcard' into disa…
keyboardDrummer Apr 29, 2026
5602edc
Merge commit 'eee972e813d16~1' into disallow-transparent-statement-bo…
keyboardDrummer Apr 29, 2026
63ed7df
Merge commit 'eee972e813d16' into disallow-transparent-statement-bodies
keyboardDrummer Apr 29, 2026
71a600a
Update test
keyboardDrummer Apr 29, 2026
6efab79
Fix tests
keyboardDrummer Apr 29, 2026
51661e0
Update test
keyboardDrummer Apr 29, 2026
28cae40
Fix tests
keyboardDrummer Apr 29, 2026
541d596
Fixes
keyboardDrummer Apr 29, 2026
5914743
Improve modified diagnostic
keyboardDrummer Apr 29, 2026
ad76318
Fixes
keyboardDrummer Apr 29, 2026
fb859b8
Undo small change
keyboardDrummer Apr 29, 2026
664ab31
Update expect files
keyboardDrummer Apr 29, 2026
6694822
Undo fix to call to main, since it triggers a latent bug
keyboardDrummer Apr 29, 2026
178425c
Update tests
keyboardDrummer Apr 30, 2026
fe02be1
Merge branch 'main' into disallow-transparent-statement-bodies
keyboardDrummer Apr 30, 2026
6043f2f
Improve source location creation in InferHoleType
keyboardDrummer Apr 30, 2026
8a97cd7
More improvements to source locations
keyboardDrummer Apr 30, 2026
5cb4822
More debugging improvements
keyboardDrummer Apr 30, 2026
f22f29c
Fix bug in resolution
keyboardDrummer Apr 30, 2026
107b72a
Add compilation bug check
keyboardDrummer Apr 30, 2026
f1f783f
update commment
keyboardDrummer Apr 30, 2026
99630d7
Fix test
keyboardDrummer Apr 29, 2026
b0c1bdd
Merge branch 'disallow-transparent-statement-bodies' of github.com:st…
keyboardDrummer Apr 30, 2026
64daf7c
Merge branch 'main' into disallow-transparent-statement-bodies
keyboardDrummer Apr 30, 2026
373e6c4
Tweak in infer hole types
keyboardDrummer Apr 30, 2026
7493074
Merge branch 'disallow-transparent-statement-bodies' of github.com:st…
keyboardDrummer Apr 30, 2026
8834318
Remove unused code
keyboardDrummer Apr 30, 2026
02a895b
Add missing defineNameCheckDup
keyboardDrummer Apr 30, 2026
dbc9da8
Fixes
keyboardDrummer Apr 30, 2026
a42c339
Fixes
keyboardDrummer Apr 30, 2026
c091620
Refactoring
keyboardDrummer Apr 30, 2026
75c037c
Merge branch 'disallow-transparent-statement-bodies' of github.com:ke…
keyboardDrummer Apr 30, 2026
ee0e39b
Fix merge mistake
keyboardDrummer Apr 30, 2026
fd2988e
Revert "Fix test"
keyboardDrummer Apr 30, 2026
da915bf
Merge issue-21-assign-variable-type into disallow-transparent-stateme…
keyboardDrummer-bot May 1, 2026
942ff8d
Merge origin/main into merge-1076-1077, resolve conflicts
keyboardDrummer-bot May 1, 2026
63c492c
Fix merge conflicts between PR #1076 and PR #1077
keyboardDrummer-bot May 1, 2026
7a30a9b
Update golden files for test_class_methods and test_class_with_methods
keyboardDrummer-bot May 1, 2026
836e8d1
Add opaque keyword to CBMC Laurel test files
keyboardDrummer-bot May 1, 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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ vcs/*.smt2
*.py.ion
*.py.ion.core.st

Strata.code-workspace
Strata.code-workspace
61 changes: 37 additions & 24 deletions Strata/Languages/Laurel/ConstrainedTypeElim.lean
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def constraintCallFor (ptMap : ConstrainedTypeMap) (ty : HighType)
(varName : Identifier) (src : Option FileRange := none) : Option StmtExprMd :=
match ty with
| .UserDefined name => if ptMap.contains name.text then
some ⟨.StaticCall (mkId s!"{name.text}$constraint") [⟨.Identifier varName, src⟩], src⟩
some ⟨.StaticCall (mkId s!"{name.text}$constraint") [⟨.Var (.Local varName), src⟩], src⟩
else none
| _ => none

Expand All @@ -68,7 +68,7 @@ def mkConstraintFunc (ptMap : ConstrainedTypeMap) (ct : ConstrainedType) : Proce
if ptMap.contains parent.text then
let paramId := { ct.valueName with uniqueId := none }
let paramRef : StmtExprMd :=
{ val := .Identifier paramId, source := none }
{ val := .Var (.Local paramId), source := none }
let parentCall : StmtExprMd :=
{ val := .StaticCall (mkId s!"{parent.text}$constraint") [paramRef], source := none }
{ val := .PrimitiveOp .And [ct.constraint, parentCall], source := none }
Expand All @@ -86,14 +86,21 @@ private def wrap (stmts : List StmtExprMd) (src : Option FileRange)
: StmtExprMd :=
match stmts with | [s] => s | ss => ⟨.Block ss none, src⟩

def resolveVariable (ptMap : ConstrainedTypeMap) (v : VariableMd) : VariableMd :=
match v.val with
| .Declare param => ⟨.Declare { param with type := resolveType ptMap param.type }, v.source⟩
| _ => v

/-- Resolve constrained types in type positions and inject constraint calls into quantifier bodies.
Recursion into StmtExprMd children is handled by `mapStmtExpr`. -/
def resolveExprNode (ptMap : ConstrainedTypeMap) (expr : StmtExprMd) : StmtExprMd :=
let source := expr.source

match expr.val with
| .LocalVariable n ty init =>
⟨.LocalVariable n (resolveType ptMap ty) init, source⟩
| .Assign targets value =>
⟨.Assign (targets.map (resolveVariable ptMap)) value, source⟩
| .Var (.Declare param) =>
⟨.Var (.Declare { param with type := resolveType ptMap param.type }), source⟩
| .Quantifier mode param trigger body =>
let param' := { param with type := resolveType ptMap param.type }
-- With bottom-up traversal, `body` is already recursed into. The newly
Expand Down Expand Up @@ -122,25 +129,31 @@ def elimStmt (ptMap : ConstrainedTypeMap)
let source := stmt.source

match _h : stmt.val with
| .LocalVariable name ty init =>
let callOpt := constraintCallFor ptMap ty.val name (src := source)
if callOpt.isSome then modify fun pv => pv.insert name.text ty.val
let (init', check) : Option StmtExprMd × List StmtExprMd := match init with
| none => match callOpt with
| some c => (none, [⟨.Assume c, source⟩])
| none => (none, [])
| some _ => (init, callOpt.toList.map fun c => ⟨.Assert { condition := c }, source⟩)
pure ([⟨.LocalVariable name ty init', source⟩] ++ check)

| .Assign [target] _ => match target.val with
| .Identifier name => do
match (← get).get? name.text with
| some ty =>
let assert := (constraintCallFor ptMap ty name (src := source)).toList.map
fun c => ⟨.Assert { condition := c }, source⟩
pure ([stmt] ++ assert)
| none => pure [stmt]
| _ => pure [stmt]
| .Var (.Declare param) =>
let callOpt := constraintCallFor ptMap param.type.val param.name (src := source)
if callOpt.isSome then modify fun pv => pv.insert param.name.text param.type.val
let check := match callOpt with
| some c => [⟨.Assume c, source⟩]
| none => []
pure ([stmt] ++ check)

| .Assign targets _value =>
-- Handle Declare targets for constrained type elimination
let declareChecks ← targets.foldlM (init := ([] : List StmtExprMd)) fun acc target =>
match target.val with
| .Declare param => do
let callOpt := constraintCallFor ptMap param.type.val param.name (src := source)
if callOpt.isSome then modify fun pv => pv.insert param.name.text param.type.val
pure (acc ++ callOpt.toList.map fun c => ⟨.Assert { condition := c }, source⟩)
| .Local name => do
match (← get).get? name.text with
| some ty =>
let assert := (constraintCallFor ptMap ty name (src := source)).toList.map
fun c => ⟨.Assert { condition := c }, source⟩
pure (acc ++ assert)
| none => pure acc
| _ => pure acc
pure ([stmt] ++ declareChecks)

| .Block stmts sep =>
let stmtss ← inScope (stmts.mapM (elimStmt ptMap))
Expand Down Expand Up @@ -205,7 +218,7 @@ private def mkWitnessProc (ptMap : ConstrainedTypeMap) (ct : ConstrainedType) :

let witnessId : Identifier := mkId "$witness"
let witnessInit : StmtExprMd :=
⟨.LocalVariable witnessId (resolveType ptMap ct.base) (some ct.witness), src⟩
⟨.Assign [⟨.Declare ⟨witnessId, resolveType ptMap ct.base⟩, src⟩] ct.witness, src⟩
let assert : StmtExprMd :=
⟨.Assert { condition := (constraintCallFor ptMap (.UserDefined ct.name) witnessId (src := src)).get! }, src⟩
{ name := mkId s!"$witness_{ct.name.text}"
Expand Down
1 change: 1 addition & 0 deletions Strata/Languages/Laurel/CoreDefinitionsForLaurel.lean
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def coreDefinitionsForLaurelDDM :=
#strata
program Laurel;

datatype LaurelResolutionErrorPlaceholder {}
datatype Float64IsNotSupportedYet {}

// The types for these Map functions are incorrect.
Expand Down
18 changes: 10 additions & 8 deletions Strata/Languages/Laurel/CoreGroupingAndOrdering.lean
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,11 @@ def collectStaticCallNames (expr : StmtExprMd) : List String :=
| some eelse => collectStaticCallNames eelse
| none => []
| .Block stmts _ => stmts.flatMap (fun s => collectStaticCallNames s)
| .Assign targets v =>
targets.flatMap (fun t => collectStaticCallNames t) ++
| .Assign _targets v =>
-- Targets are Variables; Field targets can contain StmtExpr children,
-- but field-target assigns are eliminated before this pass runs,
-- so we only need to collect from the value.
collectStaticCallNames v
| .LocalVariable _ _ initOption =>
match initOption with
| some init => collectStaticCallNames init
| none => []
| .Return v =>
match v with
| some x => collectStaticCallNames x
Expand All @@ -85,7 +83,7 @@ def collectStaticCallNames (expr : StmtExprMd) : List String :=
| some t => collectStaticCallNames t
| none => []) ++
collectStaticCallNames body
| .FieldSelect t _ => collectStaticCallNames t
| .Var (.Field t _) => collectStaticCallNames t
| .PureFieldUpdate t _ v => collectStaticCallNames t ++ collectStaticCallNames v
| .InstanceCall t _ args =>
collectStaticCallNames t ++ args.flatMap (fun a => collectStaticCallNames a)
Expand All @@ -98,7 +96,11 @@ def collectStaticCallNames (expr : StmtExprMd) : List String :=
| .Assigned v => collectStaticCallNames v
| _ => []
termination_by sizeOf expr
decreasing_by all_goals (have := AstNode.sizeOf_val_lt ‹_›; term_by_mem)
decreasing_by
all_goals simp_wf
all_goals (try have := AstNode.sizeOf_val_lt expr)
all_goals (try term_by_mem)
all_goals omega

/--
Build the procedure call graph, run Tarjan's SCC algorithm, and return each SCC
Expand Down
2 changes: 1 addition & 1 deletion Strata/Languages/Laurel/EliminateHoles.lean
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ private def mkHoleCall (holeType : HighTypeMd) : ElimHoleM StmtExprMd := do
body := .Opaque [] none []
}
modify fun s => { s with generatedFunctions := s.generatedFunctions ++ [holeProc] }
return bare (.StaticCall holeName (inputs.map (fun p => bare (.Identifier p.name))))
return bare (.StaticCall holeName (inputs.map (fun p => bare (.Var (.Local p.name)))))

/-- Replace a deterministic `.Hole` with a call to a fresh uninterpreted function.
Non-hole nodes pass through unchanged; recursion is handled by `mapStmtExprM`. -/
Expand Down
2 changes: 1 addition & 1 deletion Strata/Languages/Laurel/EliminateValueReturns.lean
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private def eliminateValueReturnNode (outParam : Identifier) (stmt : StmtExprMd)
match stmt.val with
| .Return (some value) =>
-- Synthesized nodes use default metadata since no diagnostics should be reported on them
let target : StmtExprMd := { val := .Identifier outParam, source := none }
let target : VariableMd := { val := .Local outParam, source := none }
let assign : StmtExprMd := { val := .Assign [target] value, source := none }
let ret : StmtExprMd := { val := .Return none, source := stmt.source }
{ val := .Block [assign, ret] none, source := none }
Expand Down
19 changes: 11 additions & 8 deletions Strata/Languages/Laurel/FilterPrelude.lean
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private partial def collectHighTypeNames (ty : HighTypeMd) : CollectM Unit := do
| .Pure base => collectHighTypeNames base
| .Intersection types => types.forM collectHighTypeNames
| .TVoid | .TBool | .TInt | .TFloat64 | .TReal | .TString | .THeap
| .TBv _ | .Unknown => pure ()
| .TBv _ | .Unknown | .MultiValuedExpr _ => pure ()

/-- Collect all referenced names (procedure calls, type references) from a StmtExpr tree. -/
private partial def collectExprNames (expr : StmtExprMd) : CollectM Unit := do
Expand All @@ -92,16 +92,19 @@ private partial def collectExprNames (expr : StmtExprMd) : CollectM Unit := do
collectExprNames cond; collectExprNames thenB
elseB.forM collectExprNames
| .Block stmts _ => stmts.forM collectExprNames
| .LocalVariable _ ty init =>
collectHighTypeNames ty
init.forM collectExprNames
| .While cond invs dec body =>
collectExprNames cond; invs.forM collectExprNames
dec.forM collectExprNames
collectExprNames body
| .Assign targets value =>
collectExprNames value; targets.forM collectExprNames
| .FieldSelect target _ => collectExprNames target
collectExprNames value
for ⟨t, _⟩ in targets.attach do
match t.val with
| .Field target _ => collectExprNames target
| .Local _ => pure ()
| .Declare param => collectHighTypeNames param.type
| .Var (.Field target _) => collectExprNames target
| .Var (.Declare param) => collectHighTypeNames param.type
| .PureFieldUpdate target _ newVal =>
collectExprNames target; collectExprNames newVal
| .PrimitiveOp _ args => args.forM collectExprNames
Expand All @@ -120,7 +123,7 @@ private partial def collectExprNames (expr : StmtExprMd) : CollectM Unit := do
| .ReferenceEquals lhs rhs => collectExprNames lhs; collectExprNames rhs
| .Hole _ ty => ty.forM collectHighTypeNames
| .Exit _ | .LiteralInt _ | .LiteralBool _ | .LiteralString _ | .LiteralDecimal _
| .Identifier _ | .This | .Abstract | .All => pure ()
| .Var (.Local _) | .This | .Abstract | .All => pure ()

/-- Collect names from a procedure body. -/
private def collectBodyNames (body : Body) : CollectM Unit := do
Expand Down Expand Up @@ -177,7 +180,7 @@ private partial def collectInvokeOnTargets (expr : StmtExprMd)
| .StaticCall callee args =>
let rest ← args.flatMapM collectInvokeOnTargets
return callee.text :: rest
| .Identifier _ | .LiteralInt _ | .LiteralBool _ | .LiteralString _
| .Var (.Local _) | .LiteralInt _ | .LiteralBool _ | .LiteralString _
| .LiteralDecimal _ => return []
| _ =>
throw s!"FilterPrelude.collectInvokeOnTargets: unexpected node in invokeOn expression"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ partial def highTypeValToArg : HighType → Arg
| [] => laurelOp "compositeType" #[ident "Unknown"]
| t :: _ => highTypeToArg t
| .Unknown => laurelOp "compositeType" #[ident "Unknown"]
| .MultiValuedExpr _ => laurelOp "compositeType" #[ident "Unknown"]

end

Expand All @@ -80,6 +81,10 @@ private def operationName : Operation → String
partial def stmtExprToArg (s : StmtExprMd) : Arg :=
stmtExprValToArg s.val
where
variableToArg : Variable → Arg
| .Local name => laurelOp "identifier" #[ident name.text]
| .Field target field => laurelOp "fieldAccess" #[stmtExprToArg target, ident field.text]
| .Declare param => laurelOp "identifier" #[ident param.name.text]
stmtExprValToArg : StmtExpr → Arg
| .LiteralBool b => laurelOp "literalBool" #[boolToArg b]
| .LiteralInt n =>
Expand All @@ -90,23 +95,37 @@ where
| .LiteralString s => laurelOp "string" #[.strlit sr s]
| .Hole true _ => laurelOp "hole"
| .Hole false _ => laurelOp "nondetHole"
| .Identifier name => laurelOp "identifier" #[ident name.text]
| .Var (.Local name) => laurelOp "identifier" #[ident name.text]
| .Block stmts label =>
let stmtArgs := stmts.map stmtExprToArg |>.toArray
match label with
| none => laurelOp "block" #[semicolonSep stmtArgs]
| some l => laurelOp "labelledBlock" #[semicolonSep stmtArgs, ident l]
| .LocalVariable name ty init =>
let typeOpt := optionArg (some (laurelOp "typeAnnotation" #[highTypeToArg ty]))
let initOpt := optionArg (init.map fun e => laurelOp "initializer" #[stmtExprToArg e])
laurelOp "varDecl" #[ident name.text, typeOpt, initOpt]
| .Var (.Declare param) =>
let typeOpt := optionArg (some (laurelOp "typeAnnotation" #[highTypeToArg param.type]))
let initOpt := optionArg none
laurelOp "varDecl" #[ident param.name.text, typeOpt, initOpt]
| .Assign [⟨.Declare param, _⟩] value =>
let typeOpt := optionArg (some (laurelOp "typeAnnotation" #[highTypeToArg param.type]))
let initOpt := optionArg (some (laurelOp "initializer" #[stmtExprToArg value]))
laurelOp "varDecl" #[ident param.name.text, typeOpt, initOpt]
| .Assign targets value =>
-- Grammar only supports single-target assign; use first target or placeholder
let targetArg := match targets with
| t :: _ => stmtExprToArg t
| [] => laurelOp "identifier" #[ident "_"]
laurelOp "assign" #[targetArg, stmtExprToArg value]
| .FieldSelect target field =>
if targets.length > 1 then
let targetArgs := targets.map fun t =>
match t.val with
| .Declare param => laurelOp "assignTargetDecl" #[ident param.name.text, highTypeToArg param.type]
| .Local name => laurelOp "assignTargetVar" #[ident name.text]
| .Field target _ =>
match target.val with
| .Var (.Local name) => laurelOp "assignTargetField" #[ident name.text, ident (match t.val with | .Field _ f => f.text | _ => "_")]
| _ => laurelOp "assignTargetVar" #[ident "_"]
laurelOp "multiAssign" #[commaSep targetArgs.toArray, stmtExprToArg value]
else
let targetArg := match targets with
| t :: _ => variableToArg t.val
| [] => laurelOp "identifier" #[ident "_"]
laurelOp "assign" #[targetArg, stmtExprToArg value]
| .Var (.Field target field) =>
laurelOp "fieldAccess" #[stmtExprToArg target, ident field.text]
| .StaticCall callee args =>
let calleeArg := laurelOp "identifier" #[ident callee.text]
Expand Down Expand Up @@ -358,6 +377,12 @@ def formatTypeDefinition : TypeDefinition → Format
| .Datatype ty => formatDatatypeDefinition ty
| .Alias ta => "type " ++ format ta.name ++ " = " ++ formatHighType ta.target

def formatVariable (v : Variable) : Format :=
formatArg (stmtExprToArg ⟨.Var v, none⟩)

def formatVariableMd (v : VariableMd) : Format :=
formatArg (stmtExprToArg ⟨.Var v.val, v.source⟩)

def formatConstant (c : Constant) : Format :=
"const " ++ format c.name ++ ": " ++ formatHighType c.type ++
match c.initializer with
Expand All @@ -375,6 +400,8 @@ instance : Std.ToFormat CompositeType where format := formatCompositeType
instance : Std.ToFormat ConstrainedType where format := formatConstrainedType
instance : Std.ToFormat DatatypeConstructor where format := formatDatatypeConstructor
instance : Std.ToFormat DatatypeDefinition where format := formatDatatypeDefinition
instance : Std.ToFormat Variable where format := formatVariable
instance : Std.ToFormat VariableMd where format := formatVariableMd
instance : Std.ToFormat Constant where format := formatConstant
instance : Std.ToFormat TypeDefinition where format := formatTypeDefinition
instance : Std.ToFormat Program where format := formatProgram
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def translateBool (arg : Arg) : TransM Bool := do
| x => TransM.error s!"translateBool expects expression or operation, got {repr x}"

instance : Inhabited Parameter where
default := { name := "" , type := { val := .Unknown, source := none } }
default := { name := "" , type := default }

def mkHighTypeMd (t : HighType) (source : Option FileRange) : HighTypeMd := { val := t, source := source }
def mkStmtExprMd (e : StmtExpr) (source : Option FileRange) : StmtExprMd := { val := e, source := source }
Expand Down Expand Up @@ -240,15 +240,42 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExprMd := do
| _ => TransM.error s!"assignArg {repr assignArg} didn't match expected pattern for variable {name}"
| .option _ none => pure none
| _ => TransM.error s!"assignArg {repr assignArg} didn't match expected pattern for variable {name}"
return mkStmtExprMd (.LocalVariable name varType value) src
match value with
| some init => return mkStmtExprMd (.Assign [⟨.Declare ⟨name, varType⟩, src⟩] init) src
| none => return mkStmtExprMd (.Var (.Declare ⟨name, varType⟩)) src
| q`Laurel.identifier, #[arg0] =>
let name ← translateIdent arg0
return mkStmtExprMd (.Identifier name) src
return mkStmtExprMd (.Var (.Local name)) src
| q`Laurel.parenthesis, #[arg0] => translateStmtExpr arg0
| q`Laurel.assign, #[arg0, arg1] =>
let target ← translateStmtExpr arg0
let targetVar : VariableMd ← match target.val with
| .Var v => pure ⟨v, target.source⟩
| _ => TransM.error s!"assign target must be a variable or field access"
let value ← translateStmtExpr arg1
return mkStmtExprMd (.Assign [target] value) src
return mkStmtExprMd (.Assign [targetVar] value) src
| q`Laurel.multiAssign, #[targetsSeq, valueArg] =>
let targets ← match targetsSeq with
| .seq _ .comma args => args.toList.mapM fun targ => do
let tSrc ← getArgFileRange targ
let .op top := targ
| TransM.error s!"multiAssign target expects operation"
match top.name, top.args with
| q`Laurel.assignTargetDecl, #[nameArg, typeArg] =>
let name ← translateIdent nameArg
let ty ← translateHighType typeArg
pure (⟨.Declare ⟨name, ty⟩, tSrc⟩ : VariableMd)
| q`Laurel.assignTargetVar, #[nameArg] =>
let name ← translateIdent nameArg
pure (⟨.Local name, tSrc⟩ : VariableMd)
| q`Laurel.assignTargetField, #[objArg, fieldArg] =>
let obj ← translateIdent objArg
let field ← translateIdent fieldArg
pure (⟨.Field ⟨.Var (.Local obj), tSrc⟩ field, tSrc⟩ : VariableMd)
| _, _ => TransM.error s!"multiAssign: unexpected target {repr top.name}"
| _ => pure []
let value ← translateStmtExpr valueArg
return mkStmtExprMd (.Assign targets value) src
| q`Laurel.new, #[nameArg] =>
let name ← translateIdent nameArg
return mkStmtExprMd (.New name) src
Expand All @@ -263,7 +290,7 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExprMd := do
| q`Laurel.call, #[arg0, argsSeq] =>
let callee ← translateStmtExpr arg0
let calleeName := match callee.val with
| .Identifier name => name
| .Var (.Local name) => name
| _ => ""
let argsList ← match argsSeq with
| .seq _ .comma args => args.toList.mapM translateStmtExpr
Expand All @@ -285,7 +312,7 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExprMd := do
let obj ← translateStmtExpr objArg
let field ← translateIdent fieldArg
let fieldSrc ← getArgFileRange fieldArg
return mkStmtExprMd (.FieldSelect obj field) fieldSrc
return mkStmtExprMd (.Var (.Field obj field)) fieldSrc
| q`Laurel.while, #[condArg, invSeqArg, bodyArg] =>
let cond ← translateStmtExpr condArg
let invariants ← match invSeqArg with
Expand Down
Loading
Loading