-
Notifications
You must be signed in to change notification settings - Fork 440
Introduce if/switch expressions #1228
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
Conversation
8c886c8
to
fdab7ef
Compare
fdab7ef
to
f1b6f0a
Compare
How's this @ahoppen? |
f1b6f0a
to
05ed3fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
4776f35
to
ba9b120
Compare
This was recently removed, but will represent an if/switch expression when used as a statement.
This replaces IfStmtSyntax, and will be wrapped in an ExpressionStmtSyntax when used as a statement.
Update the parser to support parsing IfExprSyntax. For now, this only updates the existing statement parsing, and does not attempt to parse in expression position.
This replaces SwitchStmtSyntax, and will be wrapped in an ExpressionStmtSyntax when used as a statement.
Update the parser to support parsing SwitchExprSyntax. For now, this only updates the existing statement parsing, and does not attempt to parse in expression position.
Start parsing if and switch expressions as unary expressions (as we don't allow postfix grammar for them). In addition, parse if/switch expressions in statement position if we see a `try`/`await`/`move`, or a trailing `as Type`.
Clean up some code, allow `if` and `switch` to count as the start of an expression, and add some substructure test assertions.
ba9b120
to
e072157
Compare
Hello @hamishknight, I have a question regarding the current way of what differentiates a switch expression from a switch statement:
But I found out that, looking at what swift-syntax creates, these aren't actually switch expression but statements because they are being enclosed in a If my understanding of the rule to differentiate between the two, is the above actually expected? Note: Keeping the above examples, to make them considered as switch expressions, I have to write then as follow:
Thank you in advance for your enlightenment 🙏 |
Indeed, this is because syntactically they appear in statement/expression position, and therefore are considered to be statements by swift-syntax (same as if they weren't the only element in the function body). The compiler is then responsible for determining whether they are semantically expressions, and handles converting into a single expression return. For e.g a |
I see, after your explanation it makes more sense syntactically wise 🙏 I have a follow-up question if you don't mind then: I do want to catch the cases of where switch are syntactically statements but compiled as expressions (as in my previous examples). Do you think I could kind of infer that by looking in the syntactic context of the switch ? (for example, if the switch is enclosed in a computed property and there is nothing else than this switch, etc.) Or would that be a rabbit hole and I would risk to have lots of false-positives because the syntax itself isn't enough to handle all cases ? |
For reference the checks are here and here. In principle, I think they ought to be mostly derivable from the syntax tree (modulo the result builder check), and maybe we could find a way to expose the important parts through swift-syntax one day (though we'll need to wait until at least we have a swift-syntax version of ASTScopes). I would be wary of re-implementing them yourself though, since they're not entirely trivial and you'll need to make sure you keep up-to-date with what the compiler's doing. I do wonder though if maybe the carve out you're looking for is just switches with single expression cases, even including switch statements, e.g consider if this should be allowed: func foo(_ x: Int) {
print("hello")
switch x {
case 5: print("5!")
case 10: print("10!")
default: print("some other number")
}
} (though note that we do allow nested if/switch expressions, so you'll want to decide how you want to handle those since they'll appear as statements) Conversely, you may not want to accept every same-line struct Err: Error {}
func foo() throws -> Int {
switch Bool.random() {
case true:
5
case false: print("false!")
throw Err()
}
} |
I see, indeed I'm afraid as well to dive into a big hole trying to replicate what the compiler is doing but with the syntax only. Best regards, |
Introduce IfExprSyntax and SwitchExpr syntax, which replace IfStmtSyntax and SwitchStmtSyntax, and can represent both if/switch expressions, as well as regular if/switch statements when wrapped in an ExpressionStmtSyntax. Implement the parsing logic such that we start parsing IfExprSyntax and SwitchExprSyntax in expression position.