tc39 / proposal-do-expressions

Proposal for `do` expressions
MIT License
1.11k stars 14 forks source link

Cover grammar due to `do { } while`? #52

Closed syg closed 4 years ago

syg commented 4 years ago

This came out with internal discussion with V8 engineers. Using do { } would require a cover grammar with do { } while and would result in parser complexity. How strongly do folks feel about the current syntax?

bakkot commented 4 years ago

The plan is to have a lookahead restriction for ExpressionStatement which prevents the leading token from being do - in other words, do in statement context always starts a do-while, and in expression context always starts a do-expression. Given that, do you think that a cover grammar would still be necessary?

syg commented 4 years ago

That seems to mostly work, but significant concerns remain for an ASI back-compat issue.

Currently, a fragment like the following gets ASI and is parsed into a ReturnStatement and then an IterationStatement:

return

do { }

while (cond)

Once do { means do-expression in expression positions, then the above seems like it'd now be parsed as a do-expression to be evaluated for the return statement.

What's worse, depending on ASI and the rest of the code, the orphaned while tail might be parsed as the head of a while loop.

Not sure how to work around this atm.

ljharb commented 4 years ago

In that example, wouldn't ASI mean that it's return; so the do would always be in a statement position?

syg commented 4 years ago

In that example, wouldn't ASI mean that it's return;

IIUC the proposal from https://github.com/tc39/proposal-do-expressions/issues/52#issuecomment-647706709 is that do { always starts a do-while statement in statement positions, and always starts a do-expression in expression positions.

Today, if the parser sees return \n do {, it'll always parse return; do { with ASI, because there are no do-expressions. If there were do-expressions, ASI wouldn't apply, and return \n do { would now parse a return-of-a-do-expression.

ljharb commented 4 years ago
(function () {
return
3
}()) === undefined; // true

you can't return anything if there's a newline following the return - that's one of the few "non-ASI" hazards, unless i'm very confused here.

bakkot commented 4 years ago

If there were do-expressions, ASI wouldn't apply

It would for return, because it has a no-lineterminator-here restriction.

syg commented 4 years ago

Ah indeed, true for return and yield throw. Does that example not generalize then? That'd be good.

syg commented 4 years ago

Looking at the grammar summary, it doesn't seem like the example generalizes. So I'd venture there're no concerns for implementability. Edit: I should say more narrowly, concerns for implementability in the parser.