-
Notifications
You must be signed in to change notification settings - Fork 202
Draft: Extractors proposal implementation #924
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
base: master
Are you sure you want to change the base?
Conversation
Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA).
To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application. When signing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated. If you are an Oracle employee, please make sure that you are a member of the main Oracle GitHub organization, and your membership in this organization is public. |
// todo-lw: conditionalExpression feels way too broad here, but binding also uses it so idk | ||
final Expression binding = conditionalExpression(true, yield, await, CoverExpressionError.DENY); | ||
|
||
final boolean isExtracting = binding instanceof CallNode; |
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.
isExtracting
seems unnecessary, and extractors may be nested inside
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.
do you have a proposed change here? not sure why it seems unnecessary, and don't know why extractors being nested is relevant
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.
Maybe I'm missing something but it seems you could just use isDestructuring
and handle extractors in the same code paths, couldn't you?
why extractors being nested is relevant
Unless isExtracting is really supposed to be shallow, it won't be true for extractors nested inside a destructuring pattern. I just don't understand why you'd want such a check?
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.
can you give an example that you feel won't work? "extractors nested inside a destructuring pattern" sounds like
const subject = new C(new D("data"));
const { a: { b: C(D(z)) } } = { a: { b: subject } }
to me, and that works with the current implementation
return false; | ||
} | ||
|
||
// todo-lw: this is duplicate code |
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.
seems like it could be moved to VerifyDestructuringPatternNodeVisitor
then.
throw error(AbstractParser.message(MSG_INVALID_LVALUE), callNode.getToken()); | ||
} | ||
for (final var arg : callNode.getArgs()) { | ||
if (arg instanceof IdentNode) { |
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.
could probably just use arg.accept(this)
return false; | ||
} | ||
|
||
private boolean isExtractorLhs(Expression lhs) { |
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.
Maybe this should be merged into isDestructuringLhs
, or are there any cases where you don't want to accept both?
In any case, we need to add a feature flag that enables extractors (disabled by default, enabled via an option).
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.
- i merged it but it ended up being used in a bunch of places and i'm a bit worried that there might now be some unintended behavior, so i'd feel safer keeping them separate
- introduced a feature flag, disabled by default. i also split the js test cases into a different suite, since i didn't want to enable the flag for the entire js suite.
|
||
const subject = new C(1, 2, 3); | ||
|
||
const C(x, ...y) = subject; |
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.
We should have Assignment and Binding patterns for all relevant cases (the file name seems a bit misleading here btw).
Make sure you also test extractors in function/method and arrow function parameters.
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.
renamed to assignment-binding.js
to hopefully make it clearer, and both should now be checked for each case
receiver = transform(accessNode.getBase()); | ||
} | ||
|
||
final var invokeCustomMatcherOrThrowNode = InvokeCustomMatcherOrThrowNode.create(context, function, assignedValue, receiver); |
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.
Please wrap this in a NodeFactory
method.
final var invokeCustomMatcherOrThrowNode = InvokeCustomMatcherOrThrowNode.create(context, function, assignedValue, receiver); | ||
|
||
final var args = fakeCallNode.getArgs(); | ||
VarRef valueTempVar = environment.createTempVar(); |
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.
valueTempVar
seems to be not assigned here? I presume this (Extractor() = x)
should still return x
, right? we should also add a test for this.
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.
my understanding is that this is not the case, no. it's just a leftover from when i factored out the destructuring code, will remove it.
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.
nevermind, i initially misunderstood you, yeah i think that this should still behave like a normal assignment in that regard; will also add tests
// todo-lw: this is duplicate code | ||
@Override | ||
public boolean enterCallNode(CallNode callNode) { | ||
if (callNode.isParenthesized()) { |
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.
This check needs to be stricter; not every non-parenthesized CallNode
is valid in this context.
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.
can you give an example of how to produce a non-parenthesized CallNode
that wouldn't be valid here? i might simply be missing something obvious here, but i don't see how the parser could do better than this
final Expression binding = bindingIdentifierOrPattern(yield, await, CONTEXT_VARIABLE_NAME); | ||
final boolean isDestructuring = !(binding instanceof IdentNode); | ||
// Get left hand side. | ||
// todo-lw: conditionalExpression feels way too broad here, but binding also uses it so idk |
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.
conditionalExpression
is indeed too broad here. not sure what you mean with "binding also uses it"?
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.
what i was trying (and failing...) to write is that the assignmentExpression
also uses conditionalExpression
as the lhs expression (which seems weird), but that's why i used it there
does that chnge your opinion that it's too broad?
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.
i narrowed it down to leftHandSideExpression
now and added a check for the remaining case
i don't love it, but i tried to implement it 'properly' and i ran into a bunch of issues. i'd like to discuss that with you before trying again, if you want me to continue refining this.
btw, ExtractorAssignmentPattern and ExtractorBindingPattern are defined as: so IIUC no newline is allowed before the opening parenthesis of an extractor, e.g.: let Extractor(x) = y; is valid but let Extractor
(x) = y; is not. |
- add feature flag - restructure tests accordingly - add factory method for InvokeCustomMatcherOrThrowNode - resolve some todos (better error msgs, ...) - ...
btw: I signed the contributor agreement, but it's pending confirmation |
https://github.com/tc39/proposal-extractors