generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 27
Support return statements in Laurel functions #486
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
Open
keyboardDrummer
wants to merge
45
commits into
main
Choose a base branch
from
remy/functionControlFlow
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
241c598
Introduce pure property for procedures
keyboardDrummer 079f5da
Rename
keyboardDrummer 4a9dad2
Add additinal tests
keyboardDrummer 6b2d31f
Parser stuck fix
keyboardDrummer fd5fdf1
Fixes
keyboardDrummer 2defa7c
Fix test
keyboardDrummer 49e0900
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer 2cd09af
Use function instead of pure procedure
keyboardDrummer ffa62ed
Fix docs
keyboardDrummer 65082fa
Add more checks to LaurelToCoreTranslator.lean
keyboardDrummer 82dd95c
Use a monad to make the code more readable
keyboardDrummer b1472a0
Update panic
keyboardDrummer 40a28ad
Fix
keyboardDrummer 2b39328
Merge branch 'main' into remy/pureProcedures
keyboardDrummer c9ed9fa
Add more test cases
keyboardDrummer 64a5ad8
Test updated and extra diagnostics
keyboardDrummer f02d1dc
Fix warnings
keyboardDrummer 4ad7c5e
Merge branch 'remy/pureProcedures' of github.com:strata-org/Strata in…
keyboardDrummer dbd4c1c
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer 21dcb9b
Hit cache
keyboardDrummer 2c83631
Merge branch 'main' into remy/pureProcedures
keyboardDrummer eefc4cd
Merge branch 'main' into remy/pureProcedures
andrewmwells-amazon 33c2b9f
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer 52ba56e
Updated comment
keyboardDrummer 616a6a0
Improve error reporting for functions
keyboardDrummer 6db50c9
Attempt at supporting lettish locals in functions
keyboardDrummer 13a9aee
Support guard pattern
keyboardDrummer 525f25c
Improve algorithm and fix test
keyboardDrummer a5a927d
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer a7fe1fc
Fixes
keyboardDrummer 5c55259
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer 9c54be8
Merge remote-tracking branch 'origin/remy/pureProcedures' into remy/f…
keyboardDrummer 9311837
Merge commit 'd4c9528772f9f~1' into remy/functionControlFlow
keyboardDrummer 06eb681
Merge commit 'd4c9528772f9f' into remy/functionControlFlow
keyboardDrummer d0deafa
Merge remote-tracking branch 'origin/main' into remy/functionControlFlow
keyboardDrummer 6b36544
Fixes and cleanup
keyboardDrummer b579857
Fail gracefully when having an if-then-else as a non-last statement i…
keyboardDrummer 0c63eee
Merge branch 'main' into remy/functionControlFlow
keyboardDrummer 97153bf
Update CodeOwners file
keyboardDrummer 7307b21
Merge branch 'main' into remy/functionControlFlow
shigoel 258762c
Move test-case
keyboardDrummer 073851b
Merge remote-tracking branch 'origin/main' into remy/functionControlFlow
keyboardDrummer 7a0530c
Fix variable capture bug
keyboardDrummer 1513481
Fix test expect files
keyboardDrummer 34c062f
Merge branch 'main' into remy/functionControlFlow
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
116 changes: 116 additions & 0 deletions
116
Strata/Languages/Laurel/EliminateReturnsInExpression.lean
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,116 @@ | ||
| /- | ||
| Copyright Strata Contributors | ||
|
|
||
| SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| -/ | ||
|
|
||
| import Strata.Languages.Laurel.Laurel | ||
| import Strata.Util.Tactics | ||
|
|
||
| /-! | ||
| # Eliminate Returns in Expression Position | ||
|
|
||
| Rewrites functional procedure bodies so that `return` statements are removed | ||
| and early-return guard patterns become if-then-else expressions. This makes | ||
| the body a pure expression tree suitable for translation to a Core function. | ||
|
|
||
| The algorithm walks a block backwards (from last statement to first), | ||
| accumulating a result expression: | ||
|
|
||
| - The last statement is converted via `lastStmtToExpr` which strips `return`, | ||
| recurses into blocks, and handles if-then-else. | ||
| - Each preceding statement wraps around the accumulated result via `stmtsToExpr`: | ||
| - `if (cond) { body }` (no else) becomes `if cond then lastStmtToExpr(body) else acc` | ||
| - Other statements are kept in a two-element block with the accumulator. | ||
|
|
||
| -/ | ||
|
|
||
| namespace Strata.Laurel | ||
|
|
||
| /-- Appending a singleton strictly increases `sizeOf`. -/ | ||
| private theorem List.sizeOf_lt_append_singleton [SizeOf α] (xs : List α) (y : α) : | ||
| sizeOf xs < sizeOf (xs ++ [y]) := by | ||
| induction xs with | ||
| | nil => simp_all; omega | ||
| | cons hd tl ih => simp_all [List.cons_append] | ||
|
|
||
| /-- `dropLast` of a non-empty list has strictly smaller `sizeOf`. -/ | ||
| private theorem List.sizeOf_dropLast_lt [SizeOf α] {l : List α} (h_ne : l ≠ []) : | ||
| sizeOf l.dropLast < sizeOf l := by | ||
| have h_concat := List.dropLast_concat_getLast h_ne | ||
| have : sizeOf l = sizeOf (l.dropLast ++ [l.getLast h_ne]) := by rw [h_concat] | ||
| rw [this] | ||
| exact List.sizeOf_lt_append_singleton l.dropLast (l.getLast h_ne) | ||
|
|
||
| mutual | ||
|
|
||
| /-- | ||
| Fold a list of preceding statements (right-to-left) around an accumulator | ||
| expression. Each `if-then` (no else) guard wraps as | ||
| `if cond then lastStmtToExpr(body) else acc`; other statements produce | ||
| `Block [stmt, acc]`. | ||
| -/ | ||
| def stmtsToExpr (stmts : List StmtExprMd) (acc : StmtExprMd) (blockMd : MetaData) | ||
| : StmtExprMd := | ||
| match stmts with | ||
| | [] => acc | ||
| | s :: rest => | ||
| let acc' := stmtsToExpr rest acc blockMd | ||
| match s with | ||
| | ⟨.IfThenElse cond thenBr none, smd⟩ => | ||
| ⟨.IfThenElse cond (lastStmtToExpr thenBr) (some acc'), smd⟩ | ||
fabiomadge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| | _ => | ||
| ⟨.Block [s, acc'] none, blockMd⟩ | ||
| termination_by (sizeOf stmts, 1) | ||
|
|
||
| /-- | ||
| Convert the last statement of a block into an expression. | ||
| - `return expr` → `expr` | ||
| - A non-empty block → process last element, fold preceding statements | ||
| - `if cond then A else B` → recurse into both branches | ||
| - Anything else → kept as-is | ||
| -/ | ||
| def lastStmtToExpr (stmt : StmtExprMd) : StmtExprMd := | ||
| match stmt with | ||
| | ⟨.Return (some val), _⟩ => val | ||
| | ⟨.Block stmts _, md⟩ => | ||
| match h_last : stmts.getLast? with | ||
| | some last => | ||
| have := List.mem_of_getLast? h_last | ||
| let lastExpr := lastStmtToExpr last | ||
| let dropped := stmts.dropLast | ||
| -- have := List.dropLast_subset stmts | ||
| have h : sizeOf stmts.dropLast < sizeOf stmts := | ||
| List.sizeOf_dropLast_lt (by intro h; simp [h] at h_last) | ||
| stmtsToExpr dropped lastExpr md | ||
| | none => stmt | ||
| | ⟨.IfThenElse cond thenBr (some elseBr), md⟩ => | ||
| ⟨.IfThenElse cond (lastStmtToExpr thenBr) (some (lastStmtToExpr elseBr)), md⟩ | ||
| | _ => stmt | ||
| termination_by (sizeOf stmt, 0) | ||
| decreasing_by | ||
| all_goals (simp_all; term_by_mem) | ||
|
|
||
| end | ||
|
|
||
| /-- | ||
| Apply return elimination to a functional procedure's body. | ||
| The entire body is treated as an expression to be converted. | ||
| -/ | ||
| def eliminateReturnsInExpression (proc : Procedure) : Procedure := | ||
| if !proc.isFunctional then proc | ||
| else | ||
| match proc.body with | ||
| | .Transparent bodyExpr => | ||
| { proc with body := .Transparent (lastStmtToExpr bodyExpr) } | ||
| | .Opaque postconds (some impl) modif => | ||
| { proc with body := .Opaque postconds (some (lastStmtToExpr impl)) modif } | ||
| | _ => proc | ||
|
|
||
| /-- | ||
| Transform a program by eliminating returns in all functional procedure bodies. | ||
| -/ | ||
| def eliminateReturnsInExpressionTransform (program : Program) : Program := | ||
| { program with staticProcedures := program.staticProcedures.map eliminateReturnsInExpression } | ||
|
|
||
| end Laurel | ||
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
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.
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.