-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Implement multiple assignments (SIP-59) #19597
Open
kyouko-taiga
wants to merge
24
commits into
scala:main
Choose a base branch
from
kyouko-taiga:multiple-assignment
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
Conversation
This file contains 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
dwijnand
reviewed
Feb 5, 2024
sjrd
reviewed
Feb 5, 2024
kyouko-taiga
force-pushed
the
multiple-assignment
branch
from
February 12, 2024 13:05
888ec39
to
6b3ea8e
Compare
mbovel
reviewed
Jun 5, 2024
kyouko-taiga
force-pushed
the
multiple-assignment
branch
from
June 18, 2024 06:48
e476be7
to
9d96531
Compare
Co-authored-by: Matt Bovel <matthieu@bovel.net>
kyouko-taiga
force-pushed
the
multiple-assignment
branch
from
July 26, 2024 12:22
1af9159
to
5dab0f6
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This PR is a proof of concept for the implementation of multiple assignments (see SIP-59).
It is still a work in progress. In particular, it doesn't satisfy Scala's left-to-right evaluation order.Design overview
The main challenge is to respect Scala's left-to-right evaluation order, which implies that all effectual operations on the left-hand side of the assignment be evaluated before the right-hand side.
An assignment generally desugars to one of two forms:
lhs = rhs
remains anAssign
tree.lhs = rhs
is rewritten as anApply
tree (e.g.,a(0) = 1
becomesa.update(0, 1)
).In the case of a single assignment, the current implementation can "simply" perform the translation in one go as it has access to the expressions of both the left-hand and the right-hand sides. In the case of a multiple-assignment, however, the right-hand side is not available during the desugaring of the left-hand side because it may be the result of an expression that we have not yet evaluated. For example:
One solution to address this issue is to assign the result of all effectful sub-expressions to some temporary definitions an construct functions
untpd.Tree => tpd.Tree
that return the assignment of some left-hand side to the value represented by their arguments. These functions will be called after the tree representing their corresponding right-hand side is evaluated. They are called "assignment builders" in this PR.Consider this example to illustrate:
x0
andx1
represent the "hoisting" of the effectful operations performed in the left-hand side of the assignment. Thenx2
stores the result of the right-hand side. Finally the two updates perform the assignment. They are the result of calling instances of the aforementioned assignment builders.Note: the evaluation order is not "strictly" left-to-right in the sense that the assignments are notionally applications of functions that occur in sources before the right-hand side has been evaluated. These semantics are nonetheless inevitable and match the way an assignment "work" in Scala.
An assignment composed of a so-called "lvalue" (borrowing from C/C++ terminology) together with a function that constructs a typed tree given an untyped right-hand side.
A lvalue notionally represents the target of an assignment. It may be a simple value (e.g., a local variable) or the partial application of some update function or setter. It also contains the definitions of the sub-expressions whose values must be hoisted, which are called "locals" in the implementation:
Partial assignments are constructed in the typer by the method
formPartialAssignmentTo
. This method is essentially a refactoring oftypedAssign
that constructs lvalues rather than desugaring left-hand sides directly while visiting the tree.Once partial assignment has been constructed, the final result is built by creating a block containing, in this order:
No value is hoisted in the case of a single assignment so that the result is equivalent to the current behavior.