Skip to content
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

Detect when from in a for loop declaration is an identifier #4393

Conversation

GeoffreyBooth
Copy link
Collaborator

@GeoffreyBooth GeoffreyBooth commented Dec 6, 2016

Per #4390, this should be valid:

lines = [
  {from: 0, to: 10}
  {from: 3, to: 17}
]

for {from, to} in lines
  console.log from

But it throws an error on thinking that from is a keyword. Since from has never been a reserved word (outside the context of an import or export statement), we should try to detect when a from on a for declaration line is really a keyword or rather a variable identifier.

I’ve tried to make the detection by looking at the previous token. If the previous token is an identifier itself, like for a from b I think that that would mean that the present from is always a keyword. If the previous token is { or [ or ,, then we’re inside destructuring and from is always an identifier. If the previous token value is from, we have for from from a or for a from from and the first from is an identifier and the second is a keyword.

Are there any other cases I haven’t thought of?

@lydell
Copy link
Collaborator

lydell commented Dec 6, 2016

Are there any other cases I haven’t thought of?

I can't think of more for…from cases, but yield from from came to mind. Not sure if it belongs in this PR, though.

Other than that this looks good to me.

@GeoffreyBooth
Copy link
Collaborator Author

This bug is only because the lexer (previously) was declaring a from token to be FROM (instead of IDENTIFIER) if there was a for anywhere previously on the same line. Now the lexer is more discerning about when from should be considered FROM.

yield from from works already because the lexer there only declares the first from a FROM if the previous tag is yield.

@GeoffreyBooth
Copy link
Collaborator Author

@IvanVergiliev or @vendethiel, can you think of any other cases where from might be a variable name and not a keyword in a for loop declaration, other than the ones in the tests in this PR?

# `export` statements (handled above) and in the declaration line of a `for`
# loop. Try to detect when `from` is a variable identifier and when it is this
# “sometimes” keyword.
fromIsKeywordInForDeclaration = (prev) ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: would isForFrom be an acceptable, more concise name?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes 👍

else if prev[0] is 'FOR'
no
# `for {from}…`, `for [from]…`
else if prev[1] in ['{', '[']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if prev[1] in '{[' would save an array allocation (not really sure if that's meaningful).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if prev[1] in '{[' looks confusing to me. The way I wrote it seems to be the style of the codebase.

@IvanVergiliev
Copy link

Thanks for the quick fix!

How about destructuring with aliasing (not sure if that's the right term):

for {b: from} in a
  print from

? This is broken right now as well, and I think there might have to be a separate check for it in the lexer. (Also, all this special casing is making me a bit sad, but I guess there's no other way to detect this so it's much better than before.)

@vendethiel
Copy link
Collaborator

vendethiel commented Dec 6, 2016

@IvanVergiliev or @vendethiel, can you think of any other cases where from might be a variable name and not a keyword in a for loop declaration, other than the ones in the tests in this PR?

./bin/coffee -bce 'for {a: from} from 1 then 1'
[stdin]:1:9: error: unexpected from
for {a: from} from 1 then 1
        ^^^^
./bin/coffee -bce 'for [a: from] from 1 then 1'
[stdin]:1:9: error: unexpected from
for [a: from] from 1 then 1
        ^^^^

Somewhat reminds me of satyr/coco#195 (though we don't have this exact issue when you can have a typeless for).

@GeoffreyBooth
Copy link
Collaborator Author

Thanks, anything else?

@IvanVergiliev
Copy link

I can't think of any other cases.

@GeoffreyBooth GeoffreyBooth merged commit 88f2bf9 into jashkenas:master Dec 6, 2016
@GeoffreyBooth
Copy link
Collaborator Author

@lydell we should probably release 1.12.1. I can prep it tonight.

@GeoffreyBooth GeoffreyBooth deleted the for-from-when-from-isnt-a-keyword branch December 6, 2016 20:29
GeoffreyBooth added a commit to GeoffreyBooth/coffeescript that referenced this pull request Dec 7, 2016
@GeoffreyBooth GeoffreyBooth mentioned this pull request Dec 7, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants