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

Fix right precedence of Hack pipes #13668

Merged
merged 5 commits into from Sep 8, 2021

Conversation

nicolo-ribaudo
Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Aug 11, 2021

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

Spec: http://jschoi.org/21/es-hack-pipes/#sec-pipe-operator

@babel-bot
Copy link
Collaborator

babel-bot commented Aug 11, 2021

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/48595/

@nicolo-ribaudo nicolo-ribaudo added PR: Bug Fix 🐛 A type of pull request used for our changelog categories Spec: Pipeline Operator pkg: parser labels Aug 11, 2021
@codesandbox-ci
Copy link

codesandbox-ci bot commented Aug 11, 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 b984f7e:

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

@jridgewell
Copy link
Member

Was this intentional, or just an oversight? I think every other operator is left associative (with the exception of **), which would make this a weird divergence.

@js-choi
Copy link
Contributor

js-choi commented Aug 11, 2021

@jridgewell: Yeah, Hack pipes should be right-associative, not left-associative.

Currently, Hack pipes are functionally bidirectionally associative, so (x |> (f(%) |> g(%)) always evaluates to the same thing as ((x |> f(%)) |> g(%). However, Hack pipes are more similar to => than to other operators: both |> and => create a binding over their right-hand body, and => (and by analogy |>) are therefore right-associative to support nested binding contexts.

In fact, after taking with @nicolo-ribaudo, I plan to loosen the precedence of Hack pipes in the specification to AssignmentExpression, to match => further.

Of course, for % bindings this does not matter, since a % binding is shadowed by each inner nested % binding. So currently Hack pipes are functionally bidirectionally associative. However, future extensions to Hack pipes might support binding the topic to a named identifier, à la Haskell’s do syntax, which would make right-associativity essential.

@nicolo-ribaudo
Copy link
Member Author

nicolo-ribaudo commented Aug 13, 2021

Let's keep this PR only for the associativity, to give some time for the discussion at tc39/proposal-hack-pipes#11.

@js-choi
Copy link
Contributor

js-choi commented Aug 17, 2021

This pull request could probably now be updated to the new changes as per tc39/proposal-hack-pipes#11 and tc39/proposal-hack-pipes#12:

  • The left-hand side is now ShortCircuitExpression.
  • The right-hand side is still AssignmentExpression, but the right-hand side must not cover an unparenthesized operation with the same precedence (ArrowFunction, AsyncArrowFunction, YieldExpression, ConditionalExpression, or an assignment operation). This check probably should be added to checkHackPipeBodyEarlyErrors.
  • The PipeBodyIsTighter error should be removed if it would not break backwards compatibility.

@nicolo-ribaudo
Copy link
Member Author

Updated to reflect the precedence currently defined in the proposal.

@js-choi
Copy link
Contributor

js-choi commented Sep 4, 2021

Thanks for continuing to work on this, @nicolo-ribaudo. Once we merge these in, I can work on support for ^ as the topic token.

@nicolo-ribaudo nicolo-ribaudo added PR: Bug Fix 🐛 A type of pull request used for our changelog categories PR: Spec Compliance 👓 A type of pull request used for our changelog categories and removed PR: Bug Fix 🐛 A type of pull request used for our changelog categories labels Sep 8, 2021
@nicolo-ribaudo nicolo-ribaudo changed the title Hack pipes are right-associative Fix right precedence of Hack pipes Sep 8, 2021

const body = this.parseMaybeAssign();

const invalidBodies = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider hoist this object to top level so it doesn't have to be re-created in parseHackPipeBody().

ArrowFunctionExpression: "arrow function",
AssignmentExpression: "assignment",
ConditionalExpression: "conditional",
YieldExpression: "yield",
Copy link
Contributor

Choose a reason for hiding this comment

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

Could leave a todo item here that invalidBodies currently does not handle TS extensions such as TSAsExpression, they will be supported after TypeScript supports hack pipes.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added a todo, but I don't think that it will be a problem because:

  • a = b as c is an AssignmentExpression
  • a => b as c is an ArrowFunctionExpression
  • a ? b : c as d is a ConditionalExpression
  • yield as a is a syntax error

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I was meant to the plain as expression a as c. The precedence of as and |> are unclear before TS supports pipes.

YieldExpression: "yield",
};

if (hasOwn(invalidBodies, body.type) && !body.extra?.parenthesized) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can transform invalidBodies to a map so it comes with .has(), and it's also faster than objects.

@nicolo-ribaudo nicolo-ribaudo merged commit 3c3f520 into babel:main Sep 8, 2021
@nicolo-ribaudo nicolo-ribaudo deleted the hack-pipe-precedence branch September 8, 2021 15:38
@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 Dec 9, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 9, 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 pkg: parser PR: Bug Fix 🐛 A type of pull request used for our changelog categories PR: Spec Compliance 👓 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

5 participants