generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 29
Resolve Laurel in Python pipeline #638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+1,461
−1,104
Merged
Changes from all commits
Commits
Show all changes
101 commits
Select commit
Hold shift + click to select a range
73c8cc9
Add a test for change https://github.com/strata-org/Strata/pull/609/c…
keyboardDrummer a683811
Fix soundness issue related to instance procedures not yet being impl…
keyboardDrummer 61f712f
Add new test file
keyboardDrummer f3f4d9e
Add test for string fields
keyboardDrummer 0af755c
Add missing !
keyboardDrummer df0c7d8
Move some things from CorePart to LaurelPart, and let output use prop…
keyboardDrummer aecd814
Add missing tests for destructuring boxes before assigning them
keyboardDrummer c317973
Merge branch 'main' into smallLaurelImprovement
keyboardDrummer b55db9a
Undo move off inline functions
keyboardDrummer 9108347
Some logging changes
keyboardDrummer fb639a2
Update summary messages
keyboardDrummer dbc1ee0
Update Laurel if grammar so match that of Core
keyboardDrummer 2f8614e
Draft recursive function support in Laurel
keyboardDrummer 41068c1
Any sets change
keyboardDrummer 827f7db
Update tests
keyboardDrummer 6b61230
Turn on resolution errors for Python pipeline
keyboardDrummer 80b1461
Inline functions when possible for Python
keyboardDrummer 785a498
Fixes
keyboardDrummer ded6d8e
Merge branch 'main' into smallLaurelImprovement
keyboardDrummer fb72f07
Move dbg_trace comment
keyboardDrummer 9934b6b
Move more from Core to Laurel prelude
keyboardDrummer aae162d
undo bad change
keyboardDrummer e246bac
Remove stub generating code
keyboardDrummer 894dbbc
Move almost all functinos from Core part of Python prelude to Laurel …
keyboardDrummer 86a395c
Rename PythonLaurelCorePrelude to PythonRuntimeCorePart
keyboardDrummer 1546296
Fixes
keyboardDrummer b003388
Undo rename of CorePart
keyboardDrummer dc49efc
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer c34d0aa
Merge branch 'main' into smallLaurelImprovement
keyboardDrummer 4e77197
Don't compile instance procedures
keyboardDrummer 1941fa5
Merge branch 'main' into smallLaurelImprovement
keyboardDrummer d63ac55
Fix minor issues
keyboardDrummer 21c5ec8
Merge branch 'smallLaurelImprovement' of github.com:strata-org/Strata…
keyboardDrummer e4dd00d
Move axioms to Laurel part
keyboardDrummer f21b600
Add autoInvoke featuresToProcedures
keyboardDrummer 3c0c890
Rename to invokeOn
keyboardDrummer 1f93c19
Fixes for invokeOn
keyboardDrummer 983cf3e
Add test for invokeOn
keyboardDrummer 24e6693
Update test
keyboardDrummer 8383c62
Merge branch 'smallLaurelImprovement' into resolvePythonsLaurel
keyboardDrummer 6134a74
Merge commit '16d07d31d2~1' into resolvePythonsLaurel
keyboardDrummer 614befa
Merge commit '16d07d31d2' into resolvePythonsLaurel
keyboardDrummer b4444b9
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 37b300b
Fix test
keyboardDrummer 376d825
bug fix
keyboardDrummer da5203a
Updates
keyboardDrummer 173a4ab
update test
keyboardDrummer 8042818
More fixes
keyboardDrummer 3863195
Enable default values for functions defined in Laurel part of Python …
keyboardDrummer e2f61b4
update expect files
keyboardDrummer 6e65754
Update test expectations
keyboardDrummer 61b2029
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 4c16a87
update expect files
keyboardDrummer 90c238f
Update comment
keyboardDrummer f66fe2b
Attempt to support mutual recursion as well
keyboardDrummer 4d6f8de
Fixes
keyboardDrummer 03c0748
Add mutual recursion and badPostcondition test-cases
keyboardDrummer e44d3e1
Fix
keyboardDrummer 401bb37
Update expect files
keyboardDrummer e4fc12f
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 216ad13
Update expect files
keyboardDrummer 1821191
Cleanup
keyboardDrummer 0ea8b09
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer a4d34d0
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 60fb71b
Small tweak
keyboardDrummer 70e8b23
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer a6db3f3
Fix
keyboardDrummer 9a17a20
Fix
keyboardDrummer 26fdd57
Update expect files
keyboardDrummer 2c1decc
Update comments and test expectation
keyboardDrummer 590b133
Reverse failure expectation
keyboardDrummer b682e37
update expect files
keyboardDrummer 449fa5b
Add test-case
keyboardDrummer 629cfca
Refactoring
keyboardDrummer 64ccccb
More refactoring
keyboardDrummer 7a57d71
Refactoring
keyboardDrummer 4fe114f
Add missing file
keyboardDrummer 081c173
Fix bug
keyboardDrummer d1fb01e
Update expect files
keyboardDrummer 72dbfee
Remove partial
keyboardDrummer e4ba5e4
Review fixes
keyboardDrummer efc95fc
Fix related to ||,&&,==>
keyboardDrummer a779e73
update expect files
keyboardDrummer b5e768a
Merge branch 'main' into resolvePythonsLaurel
keyboardDrummer 67d67dc
Merge branch 'main' into resolvePythonsLaurel
joscoh 74b7776
update new test
keyboardDrummer a7bb1ad
Merge branch 'main' into resolvePythonsLaurel
joscoh 9db065f
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 9c6e9ca
Update new tests
keyboardDrummer 4a1375c
Refer to GH issue for Core bug
keyboardDrummer 25e5a52
Change url
keyboardDrummer aab28d5
expect file update
keyboardDrummer 3ef5c49
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 6bc6f50
Do not verify prelude things
keyboardDrummer 14dd5ba
Add missing md
keyboardDrummer 116e393
Add missing TODO comment
keyboardDrummer 5e7f8e9
Cleanup
keyboardDrummer c644bd6
Bring back expected diagnostics for test_missing_models
keyboardDrummer 0138ef7
Merge remote-tracking branch 'origin/main' into resolvePythonsLaurel
keyboardDrummer 53d975a
Update expect files
keyboardDrummer abff845
Merge branch 'main' into resolvePythonsLaurel
keyboardDrummer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| /- | ||
| Copyright Strata Contributors | ||
|
|
||
| SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| -/ | ||
|
|
||
| module | ||
| public import Strata.Languages.Laurel.Laurel | ||
| import Strata.DL.Lambda.LExpr | ||
| import Strata.DDM.Util.Graph.Tarjan | ||
|
|
||
| /-! | ||
| ## Grouping and Ordering for Core Translation | ||
|
|
||
| Utilities for computing the grouping and topological ordering of Laurel | ||
| declarations before they are emitted as Strata Core declarations. | ||
|
|
||
| - `groupDatatypes` — groups mutually recursive datatypes into a single `.data` | ||
| declaration using Tarjan's SCC algorithm. | ||
| - `computeSccDecls` — builds the procedure call graph, runs Tarjan's SCC | ||
| algorithm, and returns each SCC as a list of procedures paired with a flag | ||
| indicating whether the SCC is recursive. The result is in reverse topological | ||
| order (dependencies before dependents), which is the order required by Core. | ||
| -/ | ||
|
|
||
| namespace Strata.Laurel | ||
|
|
||
| open Lambda (LMonoTy LExpr) | ||
|
|
||
| /-- Collect all `UserDefined` type names referenced in a `HighType`, including nested ones. -/ | ||
| def collectTypeRefs : HighTypeMd → List String | ||
| | ⟨.UserDefined name, _⟩ => [name.text] | ||
| | ⟨.TSet elem, _⟩ => collectTypeRefs elem | ||
| | ⟨.TMap k v, _⟩ => collectTypeRefs k ++ collectTypeRefs v | ||
| | ⟨.TTypedField vt, _⟩ => collectTypeRefs vt | ||
| | ⟨.Applied base args, _⟩ => | ||
| collectTypeRefs base ++ args.flatMap collectTypeRefs | ||
| | ⟨.Pure base, _⟩ => collectTypeRefs base | ||
| | ⟨.Intersection ts, _⟩ => ts.flatMap collectTypeRefs | ||
| | ⟨.TCore name, _⟩ => [name] | ||
| | _ => [] | ||
|
|
||
| /-- Get all datatype names that a `DatatypeDefinition` references in its constructor args. -/ | ||
| def datatypeRefs (dt : DatatypeDefinition) : List String := | ||
| dt.constructors.flatMap fun c => c.args.flatMap fun p => collectTypeRefs p.type | ||
|
|
||
| /-- | ||
| Group `LDatatype Unit` values by strongly connected components of their direct type references. | ||
| Datatypes in the same SCC (mutually recursive) share a single `.data` declaration. | ||
| Non-recursive datatypes each get their own singleton `.data` declaration. | ||
| The returned groups are in topological order: leaves (no dependencies) first, roots last. | ||
| -/ | ||
| public def groupDatatypes (dts : List DatatypeDefinition) | ||
| (ldts : List (Lambda.LDatatype Unit)) : List (List (Lambda.LDatatype Unit)) := | ||
| let n := dts.length | ||
| if n = 0 then [] else | ||
| let nameToIdx : Std.HashMap String Nat := | ||
| dts.foldlIdx (fun m i dt => m.insert dt.name.text i) {} | ||
| -- dt[i] references dt[j] means i depends on j (j must be declared first). | ||
| -- tarjan guarantees: if there's a path A→B, B appears after A in the output. | ||
| -- So we add edge j→i (j has a path to i), ensuring i (the dependent) appears after j (the dependency). | ||
| let edges : List (Nat × Nat) := | ||
| dts.foldlIdx (fun acc i dt => | ||
| (datatypeRefs dt).filterMap nameToIdx.get? |>.foldl (fun acc j => (j, i) :: acc) acc) [] | ||
| let g := OutGraph.ofEdges! n edges | ||
| let ldtMap : Std.HashMap String (Lambda.LDatatype Unit) := | ||
| ldts.foldl (fun m ldt => m.insert ldt.name ldt) {} | ||
| let dtsArr := dts.toArray | ||
| OutGraph.tarjan g |>.toList.filterMap fun comp => | ||
| let members := comp.toList.filterMap fun idx => | ||
| dtsArr[idx]? |>.bind fun dt => ldtMap.get? dt.name.text | ||
| if members.isEmpty then none else some members | ||
|
|
||
| /-- | ||
| Collect all `StaticCall` callee names referenced anywhere in a `StmtExpr`. | ||
| Used to build the call graph for SCC-based procedure ordering. | ||
| -/ | ||
| def collectStaticCallNames (expr : StmtExprMd) : List String := | ||
| match expr with | ||
| | WithMetadata.mk val _ => | ||
| match val with | ||
| | .StaticCall callee args => | ||
| callee.text :: args.flatMap (fun a => collectStaticCallNames a) | ||
| | .PrimitiveOp _ args => args.flatMap (fun a => collectStaticCallNames a) | ||
keyboardDrummer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| | .IfThenElse cond t e => | ||
| collectStaticCallNames cond ++ | ||
| collectStaticCallNames t ++ | ||
| match e with | ||
| | some eelse => collectStaticCallNames eelse | ||
| | none => [] | ||
| | .Block stmts _ => stmts.flatMap (fun s => collectStaticCallNames s) | ||
| | .Assign targets v => | ||
| targets.flatMap (fun t => collectStaticCallNames t) ++ | ||
| collectStaticCallNames v | ||
| | .LocalVariable _ _ initOption => | ||
| match initOption with | ||
| | some init => collectStaticCallNames init | ||
| | none => [] | ||
| | .Return v => | ||
| match v with | ||
| | some x => collectStaticCallNames x | ||
| | none => [] | ||
| | .While cond invs dec body => | ||
| collectStaticCallNames cond ++ | ||
| invs.flatMap (fun i => collectStaticCallNames i) ++ | ||
| (match dec with | ||
| | some d => collectStaticCallNames d | ||
| | none => []) ++ | ||
| collectStaticCallNames body | ||
| | .Forall _ trig body => | ||
| (match trig with | ||
| | some t => collectStaticCallNames t | ||
| | none => []) ++ | ||
| collectStaticCallNames body | ||
| | .Exists _ trig body => | ||
| (match trig with | ||
| | some t => collectStaticCallNames t | ||
| | none => []) ++ | ||
| collectStaticCallNames body | ||
| | .FieldSelect t _ => collectStaticCallNames t | ||
| | .PureFieldUpdate t _ v => collectStaticCallNames t ++ collectStaticCallNames v | ||
| | .InstanceCall t _ args => | ||
| collectStaticCallNames t ++ args.flatMap (fun a => collectStaticCallNames a) | ||
| | .Old v | .Fresh v | .Assert v | .Assume v => collectStaticCallNames v | ||
| | .ProveBy v p => collectStaticCallNames v ++ collectStaticCallNames p | ||
| | .ReferenceEquals l r => collectStaticCallNames l ++ collectStaticCallNames r | ||
| | .AsType t _ | .IsType t _ => collectStaticCallNames t | ||
| | .ContractOf _ f => collectStaticCallNames f | ||
| | .Assigned v => collectStaticCallNames v | ||
| | _ => [] | ||
| termination_by sizeOf expr | ||
|
|
||
| /-- | ||
| Build the procedure call graph, run Tarjan's SCC algorithm, and return each SCC | ||
| as a list of procedures paired with a flag indicating whether the SCC is recursive. | ||
| Results are in reverse topological order: dependencies before dependents. | ||
|
|
||
| Procedures with an `invokeOn` trigger are placed as early as possible — before | ||
| unrelated procedures without one — by stably partitioning them first before building | ||
| the graph. Tarjan then naturally assigns them lower indices, causing them to appear | ||
| earlier in the output. | ||
|
|
||
| External procedures are excluded. | ||
| -/ | ||
| public def computeSccDecls (program : Program) : List (List Procedure × Bool) := | ||
| -- External procedures are completely ignored (not translated to Core). | ||
| -- Stable partition: procedures with invokeOn come first, preserving relative | ||
| -- order within each group. Tarjan then places them earlier in the topological output. | ||
| let (withInvokeOn, withoutInvokeOn) := | ||
| (program.staticProcedures.filter (fun p => !p.body.isExternal)) | ||
| |>.partition (fun p => p.invokeOn.isSome) | ||
| let nonExternal : List Procedure := withInvokeOn ++ withoutInvokeOn | ||
|
|
||
| -- Build a call-graph over all non-external procedures. | ||
| -- An edge proc → callee means proc's body/contracts contain a StaticCall to callee. | ||
| let nonExternalArr : Array Procedure := nonExternal.toArray | ||
| let nameToIdx : Std.HashMap String Nat := | ||
| nonExternalArr.foldl (fun (acc : Std.HashMap String Nat × Nat) proc => | ||
| (acc.1.insert proc.name.text acc.2, acc.2 + 1)) ({}, 0) |>.1 | ||
|
|
||
| -- Collect all callee names from a procedure's body and contracts. | ||
| let procCallees (proc : Procedure) : List String := | ||
| let bodyExprs : List StmtExprMd := match proc.body with | ||
| | .Transparent b => [b] | ||
| | .Opaque postconds (some impl) _ => postconds ++ [impl] | ||
| | .Opaque postconds none _ => postconds | ||
| | _ => [] | ||
| let contractExprs : List StmtExprMd := | ||
| proc.preconditions ++ | ||
| proc.invokeOn.toList | ||
| (bodyExprs ++ contractExprs).flatMap collectStaticCallNames | ||
|
|
||
| -- Build the OutGraph for Tarjan. | ||
| let n := nonExternalArr.size | ||
| let graph : Strata.OutGraph n := | ||
| nonExternalArr.foldl (fun (acc : Strata.OutGraph n × Nat) proc => | ||
| let callerIdx := acc.2 | ||
| let g := acc.1 | ||
| let callees := procCallees proc | ||
| let g' := callees.foldl (fun g callee => | ||
| match nameToIdx.get? callee with | ||
| | some calleeIdx => g.addEdge! calleeIdx callerIdx | ||
| | none => g) g | ||
| (g', callerIdx + 1)) (Strata.OutGraph.empty n, 0) |>.1 | ||
|
|
||
| -- Run Tarjan's SCC algorithm. Results are in reverse topological order | ||
| -- (a node appears after all nodes that have paths to it). | ||
| let sccs := Strata.OutGraph.tarjan graph | ||
|
|
||
| sccs.toList.filterMap fun scc => | ||
| let procs := scc.toList.filterMap fun idx => | ||
| nonExternalArr[idx.val]? | ||
| if procs.isEmpty then none else | ||
| let isRecursive := procs.length > 1 || | ||
| (match scc.toList.head? with | ||
| | some node => (graph.nodesOut node).contains node | ||
| | none => false) | ||
| some (procs, isRecursive) | ||
|
|
||
| end Strata.Laurel | ||
This file was deleted.
Oops, something went wrong.
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.