Trailing pipe or property access should expressionize statement
edemaine opened this issue · comments
Consider:
switch @value
Value.Ace then 'A'
Value.Jack then 'J'
Value.Queen then 'Q'
Value.King then 'K'
else @value
.toString()
Currently this compiles to:
let m;if(m = this.value,m === Value.Ace) { 'A'}
else if(m === Value.Jack) { 'J'}
else if(m === Value.Queen) { 'Q'}
else if(m === Value.King) { 'K'}
else { this.value };
$ => $.toString()
It behaves the same within an arrow function too; the $ => $.toString()
gets implicitly returned but the switch
value gets dropped. The issue is that the switch
is a valid Statement
and that takes priority over expressions.
I'd propose instead that it compiles to:
(()=>{let m;if(m = this.value,m === Value.Ace) { return 'A'}
else if(m === Value.Jack) { return 'J'}
else if(m === Value.Queen) { return 'Q'}
else if(m === Value.King) { return 'K'}
else { return this.value }})()
.toString()
This is what we get with an explicit return
added, I believe via ExpressionizedStatementWithTrailingCallExpressions
. Maybe we just need to check for this before regular Statement
s, but when there's a positive number of trailing expressions?
Similar to postfix .foo
, it'd be nice to have postfix pipelines. Original motivating example from Discord:
switch @value
Value.Ace then 'A'
Value.Jack then 'J'
Value.Queen then 'Q'
Value.King then 'K'
else String @value
|> (+ @suit)
Currently this is a parse error, again because the switch
parses as a Statement
and that doesn't have postfixes available. But this one doesn't work with an explicit return
either. Probably we need to add pipelines to ExpressionizedStatementWithTrailingCallExpressions
(perhaps with a different name).
Another example I ran into today that doesn't work:
async do
await foo()
await bar()
.then =>
baz()
(trying to make the outer function not async
, but instead return a Promise)