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

Hack-pipe proposal with % topic token #13416

Conversation

js-choi
Copy link
Contributor

@js-choi js-choi commented Jun 3, 2021

Q                       A
Fixed Issues? None
Patch: Bug Fix? No
Major: Breaking Change? No
Minor: New Feature? Yes
Tests Added + Pass? Yes
Documentation PR Link babel/website#2541
Any Dependency Changes? No
License MIT

This is a continuation of #13191, which added support for { proposal: "hack", topicToken: "#" } to the proposal-pipeline-operator plugin. This pull request adds support for configuring proposal-pipeline-operator with topicToken: "%" instead of "#". See also js-choi/proposal-hack-pipes, tc39/proposal-pipeline-operator#91, and tc39/proposal-hack-pipes#2.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jun 3, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 974d8fa:

Sandbox Source
babel-repl-custom-plugin Configuration
babel-plugin-multi-config Configuration

@js-choi js-choi marked this pull request as ready for review June 3, 2021 02:29
@@ -155,7 +155,7 @@ export const types: { [name: string]: TokenType } = {
bitShift: createBinop("<</>>/>>>", 8),
plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }),
// startsExpr: required by v8intrinsic plugin
modulo: new TokenType("%", { beforeExpr, binop: 10, startsExpr }),
Copy link
Contributor

@JLHwung JLHwung Jun 3, 2021

Choose a reason for hiding this comment

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

The beforeExpr is required by v8intrinsic plugin.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a v8intrinsic test case that is broken by this change? The babel-parser/test/fixtures/v8intrinsic suite is still succeeding.

It does seem that currently, when babel-parser is configured with both pipelineOperator: { proposal: "hack", topicToken: "%" } and v8intrinsic on, x |> % breaks due toparseExprAtom always calling parseV8Intrinsic first, which then calls unexpected. This seems to be a separate problem, though.

Copy link
Member

Choose a reason for hiding this comment

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

I think beforeExpr is not needed for the v8intrinsic plugin, but for the normal % operator.

Could you check if this code is still parsed correctly?

5 % /3/g

We might need to manually manage exprAllowed for % instead of relying on beforeExpr.

Also, we should check if these two things are parsed correctly:

a |> %
function f() {}
a %
function f() {}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nicolo-ribaudo: I added tests for those cases in 5d24958. They seem to be still parsing correctly.

Copy link
Member

Choose a reason for hiding this comment

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

Oh awesome. I'll still try to find an example that breaks it because I'm not 100% convinced yet that beforeExpr is completely unnecessary, but if I cannot find it then it's good 😅

@nicolo-ribaudo nicolo-ribaudo added this to the v7.15.0 milestone Jun 3, 2021
@nicolo-ribaudo nicolo-ribaudo added PR: New Feature 🚀 A type of pull request used for our changelog categories Spec: Pipeline Operator labels Jun 3, 2021
@js-choi
Copy link
Contributor Author

js-choi commented Jun 4, 2021

I just pushed efdac2d, which makes v8intrinsics and topicToken: "%" compatible. I don’t like the current implementation, and I think it can be refactored to remove code duplication. Edit: The duplication has been improved in b1dd014.

The problem was that activating babel-parser’s v8intrinsic plugin causes parseExprAtom to preferentially call parseV8Intrinsic. If the current token is %, then parseV8Intrinsic will consume the % and then attempt to match an identifier after the %. If it does not find such an identifier after the consumed %, then it will throw a fatal unexpected error.

This makes the default parseExprAtom method, when v8intrinsic is on, unable to handle any other % atom (that is not followed by an identifier). Because parseV8Intrinsic consumes the % token, it short-circuits the default parseExprAtom method.

Ideally, parseV8Intrinsic would use a lookahead method like match that would look ahead at the next two tokens. If parseV8Intrinsic looked ahead two tokens (for a % token followed by an identifier), instead of consuming the %, then it could defer matching any other % token to the default parseExprAtom method.

But, barring that, efdac2d adds a new branch to parseV8Intrinsic that checks whether topicToken: "%" is active, and prevents it from calling unexpected. I’m sure its duplicate code can be reduced further.

CC: @ljharb

@js-choi js-choi force-pushed the proposal-hack-pipes-percent branch from 4e53882 to efdac2d Compare June 4, 2021 16:35
@js-choi
Copy link
Contributor Author

js-choi commented Jun 5, 2021

We also need to also add tests for Hack pipes with syntactic placeholders.

We might have to face some interesting questions. For example, should x |> %%%%EXPRESSION%% be valid and equivalent to x |> %%EXPRESSION%% % %? (Is x%%%EXPRESSION%% even a valid modulo operation?)

Or perhaps we should simply forbid topicToken: "%" with placeholders, like how v8intrinsics with placeholders are already forbidden.

Edit: It looks like, when with placeholders are turned on:

  1. x%%%VALUE%% already throws Unexpected token, rather than parsing successfully as (x) % (%%VALUE%%), in the status quo without Hack pipes.
  2. With Hack pipes and percent topic tokens, x |> %% %%VALUE%%, x |> %%%%VALUE%%, x |> %%VALUE%% %%, and x |> %%VALUE%%%% also throw Unexpected token, rather than parsing successfully as (x |> (%) % (%%VALUE%%)) or (x |> (%%VALUE%%) % (%)), since the tokenizer eagerly consumes any %% as a placeholder sigil.
  3. Everything else, like x |> % % %%VALUE%% and x |> %%VALUE%% % %, already does successfully and correctly parse.

Perhaps the second examples should remain invalid, in order to match the first example’s precedent, and to avoid modifying babel-parser/src/plugins/placeholders.js. I added tests assuming as such in 0a65467.

@nicolo-ribaudo
Copy link
Member

We can start by disallowing the v8intrinsics and placeholders plugins, and think about it again if TC39 will end up deciding to use %.

js-choi added a commit to js-choi/babel that referenced this pull request Jun 7, 2021
We may reenable combining these again if TC39 ends up deciding to use % as a topic token.
See babel#13416 (comment).
@js-choi
Copy link
Contributor Author

js-choi commented Jun 7, 2021

fa257f5 disables combining v8intrinsic/placeholders and Hack pipes in babel-parser. It also reverts changes to babel-parser/src/plugins/v8intrinsic.js.

js-choi added a commit to js-choi/babel that referenced this pull request Jun 8, 2021
We may reenable combining these again if TC39 ends up deciding to use % as a topic token.
See babel#13416 (comment).
@js-choi js-choi force-pushed the proposal-hack-pipes-percent branch from 236ca74 to fa257f5 Compare June 8, 2021 17:20
@JLHwung
Copy link
Contributor

JLHwung commented Jun 8, 2021

I don't think it conflicts with v8intrinsic: we can check if an identifier start follows % immediately when parsing PrimayExpression in parseExprAtom. If it is, it goes with v8intrinsic, otherwise it is a pipe topic.

@js-choi
Copy link
Contributor Author

js-choi commented Jun 8, 2021

@JLHwung: Yes, it is true that v8intrinsic and topicToken: "%" do not actually syntactically conflict. I had already made a now-reverted change that enabled their coexistence, in efdac2d. However, in order to do this, I had to change babel-parser/src/plugins/v8intrinsic.js.

When @nicolo-ribaudo suggested disallowing v8intrinsic unless TC39 commits to Hack pipes with %, I assumed that it was to prevent changing v8intrinsic.js unnecessarily, in case TC39 ends up not choosing Hack pipes with %. So I reverted the changes to v8intrinsic.js in fa257f5.

JLHwung pushed a commit to JLHwung/babel that referenced this pull request Jun 8, 2021
We may reenable combining these again if TC39 ends up deciding to use % as a topic token.
See babel#13416 (comment).
@JLHwung
Copy link
Contributor

JLHwung commented Jun 8, 2021

I have rebased on upstream/feat-7.15.0/hack-pipes and pushed here: https://github.com/JLHwung/babel/commits/proposal-hack-pipes-percent-rebased

I think it can be a good start for reviewing the real diff. The are some parser testing errors from outdated test fixtures, likely due to #13426. I haven't updated the test fixtures.

@js-choi
Copy link
Contributor Author

js-choi commented Jun 8, 2021

@JLHwung: I have made a merge from upstream/feat-7.15.0/hack-pipes to this branch, in 91d28f9.

I can rebase this branch on upstream/feat-7.15.0/hack-pipes instead, but there a particular reason that we need to rebase instead of merge?

@JLHwung
Copy link
Contributor

JLHwung commented Jun 8, 2021

@js-choi We squash merge PRs so if your PR depends on the unsquashed branch, GitHub will show all the different commits (87) instead of real different commits (20). The rebased history is more focused because it does not include a merge commit.

@js-choi js-choi force-pushed the proposal-hack-pipes-percent branch from 91d28f9 to c9eb8dd Compare June 9, 2021 00:07
@js-choi
Copy link
Contributor Author

js-choi commented Jun 9, 2021

I have squashed, rebased onto #13413, and force pushed.

packages/babel-parser/src/parser/expression.js Outdated Show resolved Hide resolved
Co-authored-by: Federico Ciardi <fed.ciardi@gmail.com>
@nicolo-ribaudo
Copy link
Member

I'm merging this with my and @fedeci's reviews: even if @fedeci's check is not green, he has quite a bit of experience in @babel/parser now.

If there needs to be other changes, this PR is not yet on main but in feat-7.15.0/hack-pipes. I'm merging this because I need to rebase that branch and it's easier to rebase both the commits at the same time.

@nicolo-ribaudo nicolo-ribaudo changed the title Hack-pipe proposal with percent topic token Hack-pipe proposal with % topic token Jul 6, 2021
@nicolo-ribaudo nicolo-ribaudo merged commit e4e8975 into babel:feat-7.15.0/hack-pipes Jul 6, 2021
@js-choi js-choi deleted the proposal-hack-pipes-percent branch July 6, 2021 17:32
nicolo-ribaudo pushed a commit that referenced this pull request Jul 6, 2021
Co-authored-by: Federico Ciardi <fed.ciardi@gmail.com>
nicolo-ribaudo pushed a commit that referenced this pull request Jul 6, 2021
Co-authored-by: Federico Ciardi <fed.ciardi@gmail.com>
nicolo-ribaudo pushed a commit that referenced this pull request Aug 3, 2021
Co-authored-by: Federico Ciardi <fed.ciardi@gmail.com>
nicolo-ribaudo pushed a commit that referenced this pull request Aug 3, 2021
Co-authored-by: Federico Ciardi <fed.ciardi@gmail.com>
@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Oct 6, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue PR: New Feature 🚀 A type of pull request used for our changelog categories Spec: Pipeline Operator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants