Fix right precedence of Hack pipes (#13668)

This commit is contained in:
Nicolò Ribaudo
2021-09-08 17:38:07 +02:00
committed by GitHub
parent 8c061f0848
commit 3c3f5205c9
78 changed files with 973 additions and 224 deletions

View File

@@ -134,6 +134,7 @@ export const ErrorMessages = makeErrorTemplates(
ParamDupe: "Argument name clash.",
PatternHasAccessor: "Object pattern can't contain getter or setter.",
PatternHasMethod: "Object pattern can't contain methods.",
// This error is only used by the smart-mix proposal
PipeBodyIsTighter:
"Unexpected %0 after pipeline body; any %0 expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence.",
PipeTopicRequiresHackPipes:
@@ -144,6 +145,8 @@ export const ErrorMessages = makeErrorTemplates(
'Invalid topic token %0. In order to use %0 as a topic reference, the pipelineOperator plugin must be configured with { "proposal": "hack", "topicToken": "%0" }.',
PipeTopicUnused:
"Hack-style pipe body does not contain a topic reference; Hack-style pipes must use topic at least once.",
PipeUnparenthesizedBody:
"Hack-style pipe body cannot be an unparenthesized %0 expression; please wrap it in parentheses.",
// Messages whose codes start with “Pipeline” or “PrimaryTopic”
// are retained for backwards compatibility

View File

@@ -61,6 +61,13 @@ import { cloneIdentifier } from "./node";
import type { SourceType } from "../options";
*/
const invalidHackPipeBodies = new Map([
["ArrowFunctionExpression", "arrow function"],
["AssignmentExpression", "assignment"],
["ConditionalExpression", "conditional"],
["YieldExpression", "yield"],
]);
export default class ExpressionParser extends LValParser {
// Forward-declaration: defined in statement.js
/*::
@@ -285,28 +292,6 @@ export default class ExpressionParser extends LValParser {
const operator = this.state.value;
node.operator = operator;
const leftIsHackPipeExpression =
left.type === "BinaryExpression" &&
left.operator === "|>" &&
this.getPluginOption("pipelineOperator", "proposal") === "hack";
if (leftIsHackPipeExpression) {
// If the pipelinePlugin is configured to use Hack pipes,
// and if an assignment expressions LHS invalidly contains `|>`,
// then the user likely meant to parenthesize the assignment expression.
// Throw a human-friendly error
// instead of something like 'Invalid left-hand side'.
// For example, `x = x |> y = #` (assuming `#` is the topic reference)
// groups into `x = (x |> y) = #`,
// and `(x |> y)` is an invalid assignment LHS.
// This is because Hack-style `|>` has tighter precedence than `=>`.
// (Unparenthesized `yield` expressions are handled
// in `parseHackPipeBody`,
// and unparenthesized `=>` expressions are handled
// in `checkHackPipeBodyEarlyErrors`.)
throw this.raise(this.state.start, Errors.PipeBodyIsTighter, operator);
}
if (this.match(tt.eq)) {
node.left = this.toAssignable(left, /* isLHS */ true);
refExpressionErrors.doubleProto = -1; // reset because double __proto__ is valid in assignment expression
@@ -497,16 +482,20 @@ export default class ExpressionParser extends LValParser {
switch (this.getPluginOption("pipelineOperator", "proposal")) {
case "hack":
return this.withTopicBindingContext(() => {
const bodyExpr = this.parseHackPipeBody(op, prec);
this.checkHackPipeBodyEarlyErrors(startPos);
return bodyExpr;
return this.parseHackPipeBody();
});
case "smart":
return this.withTopicBindingContext(() => {
const childExpr = this.parseHackPipeBody(op, prec);
if (this.prodParam.hasYield && this.isContextual("yield")) {
throw this.raise(
this.state.start,
Errors.PipeBodyIsTighter,
this.state.value,
);
}
return this.parseSmartPipelineBodyInStyle(
childExpr,
this.parseExprOpBaseRightExpr(op, prec),
startPos,
startLoc,
);
@@ -539,37 +528,25 @@ export default class ExpressionParser extends LValParser {
);
}
// Helper function for `parseExprOpRightExpr` for the Hack-pipe operator
// (and the Hack-style smart-mix pipe operator).
parseHackPipeBody(): N.Expression {
const { start } = this.state;
parseHackPipeBody(op: TokenType, prec: number): N.Expression {
// If the following expression is invalidly a `yield` expression,
// then throw a human-friendly error.
// A `yield` expression in a generator context (i.e., a [Yield] production)
// starts a YieldExpression.
// Outside of a generator context, any `yield` as a pipe body
// is considered simply an identifier.
// This error is checked here, before actually parsing the body expression,
// because `yield`s “not allowed as identifier in generator” error
// would otherwise have immediately
// occur before the pipe body is fully parsed.
// (Unparenthesized assignment expressions are handled
// in `parseMaybeAssign`,
// and unparenthesized `=>` expressions are handled
// in `checkHackPipeBodyEarlyErrors`.)
const bodyIsInGeneratorContext = this.prodParam.hasYield;
const bodyIsYieldExpression =
bodyIsInGeneratorContext && this.isContextual("yield");
const body = this.parseMaybeAssign();
if (bodyIsYieldExpression) {
throw this.raise(
this.state.start,
Errors.PipeBodyIsTighter,
this.state.value,
// TODO: Check how to handle type casts in Flow and TS once they are supported
if (invalidHackPipeBodies.has(body.type) && !body.extra?.parenthesized) {
this.raise(
start,
Errors.PipeUnparenthesizedBody,
invalidHackPipeBodies.get(body.type),
);
} else {
return this.parseExprOpBaseRightExpr(op, prec);
}
if (!this.topicReferenceWasUsedInCurrentContext()) {
// A Hack pipe body must use the topic reference at least once.
this.raise(start, Errors.PipeTopicUnused);
}
return body;
}
checkExponentialAfterUnary(node: N.AwaitExpression | N.UnaryExpression) {
@@ -2738,24 +2715,7 @@ export default class ExpressionParser extends LValParser {
// The `startPos` is the starting position of the pipe body.
checkHackPipeBodyEarlyErrors(startPos: number): void {
// If the following token is invalidly `=>`,
// then throw a human-friendly error
// instead of something like 'Unexpected token, expected ";"'.
// For example, `x => x |> y => #` (assuming `#` is the topic reference)
// groups into `x => (x |> y) => #`,
// and `(x |> y) => #` is an invalid arrow function.
// This is because Hack-style `|>` has tighter precedence than `=>`.
// (Unparenthesized `yield` expressions are handled
// in `parseHackPipeBody`,
// and unparenthesized assignment expressions are handled
// in `parseMaybeAssign`.)
if (this.match(tt.arrow)) {
throw this.raise(
this.state.start,
Errors.PipeBodyIsTighter,
tt.arrow.label,
);
} else if (!this.topicReferenceWasUsedInCurrentContext()) {
if (!this.topicReferenceWasUsedInCurrentContext()) {
// A Hack pipe body must use the topic reference at least once.
this.raise(startPos, Errors.PipeTopicUnused);
}

View File

@@ -7,6 +7,5 @@
"topicToken": "#"
}
]
],
"throws": "Unexpected => after pipeline body; any => expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:8)"
]
}

View File

@@ -0,0 +1,62 @@
{
"type": "File",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized arrow function expression; please wrap it in parentheses. (1:6)"
],
"program": {
"type": "Program",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"left": {
"type": "NumericLiteral",
"start":0,"end":2,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":2}},
"extra": {
"rawValue": 10,
"raw": "10"
},
"value": 10
},
"operator": "|>",
"right": {
"type": "ArrowFunctionExpression",
"start":6,"end":16,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":16}},
"id": null,
"generator": false,
"async": false,
"params": [
{
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"x"},
"name": "x"
}
],
"body": {
"type": "BinaryExpression",
"start":11,"end":16,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":16}},
"left": {
"type": "Identifier",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12},"identifierName":"x"},
"name": "x"
},
"operator": "+",
"right": {
"type": "TopicReference",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}
}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "#"
}
]
],
"throws": "Unexpected &&= after pipeline body; any &&= expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:11)"
}
]
}

View File

@@ -0,0 +1,44 @@
{
"type": "File",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized assignment expression; please wrap it in parentheses. (1:9)"
],
"program": {
"type": "Program",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"left": {
"type": "Identifier",
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5},"identifierName":"value"},
"name": "value"
},
"operator": "|>",
"right": {
"type": "AssignmentExpression",
"start":9,"end":16,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":16}},
"operator": "&&=",
"left": {
"type": "Identifier",
"start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"x"},
"name": "x"
},
"right": {
"type": "TopicReference",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "#"
}
]
],
"throws": "Unexpected = after pipeline body; any = expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:16)"
}
]
}

View File

@@ -0,0 +1,55 @@
{
"type": "File",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized assignment expression; please wrap it in parentheses. (1:9)"
],
"program": {
"type": "Program",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"left": {
"type": "Identifier",
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5},"identifierName":"value"},
"name": "value"
},
"operator": "|>",
"right": {
"type": "AssignmentExpression",
"start":9,"end":19,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":19}},
"operator": "=",
"left": {
"type": "ArrayPattern",
"start":9,"end":15,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":15}},
"elements": [
{
"type": "Identifier",
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
"name": "x"
},
{
"type": "Identifier",
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"y"},
"name": "y"
}
]
},
"right": {
"type": "TopicReference",
"start":18,"end":19,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":19}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "#"
}
]
],
"throws": "Unexpected += after pipeline body; any += expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:11)"
}
]
}

View File

@@ -0,0 +1,44 @@
{
"type": "File",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized assignment expression; please wrap it in parentheses. (1:9)"
],
"program": {
"type": "Program",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"left": {
"type": "Identifier",
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5},"identifierName":"value"},
"name": "value"
},
"operator": "|>",
"right": {
"type": "AssignmentExpression",
"start":9,"end":15,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":15}},
"operator": "+=",
"left": {
"type": "Identifier",
"start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"x"},
"name": "x"
},
"right": {
"type": "TopicReference",
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -0,0 +1,66 @@
{
"type": "File",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
"program": {
"type": "Program",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"left": {
"type": "NumericLiteral",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1}},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":5,"end":17,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":17}},
"left": {
"type": "CallExpression",
"start":5,"end":9,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":9}},
"callee": {
"type": "Identifier",
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"f"},
"name": "f"
},
"arguments": [
{
"type": "TopicReference",
"start":7,"end":8,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":8}}
}
]
},
"operator": "|>",
"right": {
"type": "CallExpression",
"start":13,"end":17,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":17}},
"callee": {
"type": "Identifier",
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"g"},
"name": "g"
},
"arguments": [
{
"type": "TopicReference",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}
}
]
}
}
}
}
],
"directives": []
}
}

View File

@@ -1,4 +0,0 @@
{
"plugins": [["pipelineOperator", { "proposal": "hack", "topicToken": "#" }]],
"throws": "Unexpected yield after pipeline body; any yield expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (2:14)"
}

View File

@@ -22,10 +22,6 @@
"right": {
"type": "ArrowFunctionExpression",
"start":6,"end":32,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":32}},
"extra": {
"parenthesized": true,
"parenStart": 5
},
"id": null,
"generator": false,
"async": false,
@@ -40,14 +36,14 @@
"type": "BinaryExpression",
"start":11,"end":32,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12}}
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":11,"end":23,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":23}},
"start":16,"end":32,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12}}
},
"operator": "|>",
"right": {
"type": "CallExpression",
"start":16,"end":23,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":23}},
"callee": {
@@ -66,27 +62,31 @@
"name": "$"
}
]
}
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":27,"end":32,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28}}
},
"operator": ">",
"operator": "|>",
"right": {
"type": "NumericLiteral",
"start":31,"end":32,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":32}},
"extra": {
"rawValue": 1,
"raw": "1"
"type": "BinaryExpression",
"start":27,"end":32,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28}}
},
"value": 1
"operator": ">",
"right": {
"type": "NumericLiteral",
"start":31,"end":32,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":32}},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
}
},
"extra": {
"parenthesized": true,
"parenStart": 5
}
}
}

View File

@@ -25,10 +25,6 @@
"right": {
"type": "ArrowFunctionExpression",
"start":6,"end":17,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":17}},
"extra": {
"parenthesized": true,
"parenStart": 5
},
"id": null,
"generator": false,
"async": false,
@@ -52,6 +48,10 @@
"type": "TopicReference",
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}}
}
},
"extra": {
"parenthesized": true,
"parenStart": 5
}
}
}

View File

@@ -26,10 +26,6 @@
"right": {
"type": "BinaryExpression",
"start":6,"end":12,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":12}},
"extra": {
"parenthesized": true,
"parenStart": 5
},
"left": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"$"},
@@ -40,6 +36,10 @@
"type": "Identifier",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12},"identifierName":"f"},
"name": "f"
},
"extra": {
"parenthesized": true,
"parenStart": 5
}
}
}

View File

@@ -0,0 +1,3 @@
{
"plugins": [["pipelineOperator", { "proposal": "hack", "topicToken": "#" }]]
}

View File

@@ -0,0 +1,11 @@
{
"plugins": [
[
"pipelineOperator",
{
"proposal": "hack",
"topicToken": "#"
}
]
]
}

View File

@@ -0,0 +1,64 @@
{
"type": "File",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized yield expression; please wrap it in parentheses. (2:14)"
],
"program": {
"type": "Program",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"id": {
"type": "Identifier",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12},"identifierName":"f"},
"name": "f"
},
"generator": true,
"async": false,
"params": [
{
"type": "Identifier",
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"x"},
"name": "x"
}
],
"body": {
"type": "BlockStatement",
"start":17,"end":43,"loc":{"start":{"line":1,"column":17},"end":{"line":3,"column":1}},
"body": [
{
"type": "ReturnStatement",
"start":21,"end":41,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":22}},
"argument": {
"type": "BinaryExpression",
"start":28,"end":40,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":21}},
"left": {
"type": "Identifier",
"start":28,"end":29,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"x"},
"name": "x"
},
"operator": "|>",
"right": {
"type": "YieldExpression",
"start":33,"end":40,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":21}},
"delegate": false,
"argument": {
"type": "TopicReference",
"start":39,"end":40,"loc":{"start":{"line":2,"column":20},"end":{"line":2,"column":21}}
}
}
}
}
],
"directives": []
}
}
],
"directives": []
}
}

View File

@@ -0,0 +1,11 @@
{
"plugins": [
[
"pipelineOperator",
{
"proposal": "hack",
"topicToken": "#"
}
]
]
}

View File

@@ -0,0 +1,41 @@
{
"type": "File",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"program": {
"type": "Program",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"left": {
"type": "Identifier",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1},"identifierName":"x"},
"name": "x"
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":5,"end":14,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":14}},
"left": {
"type": "Identifier",
"start":5,"end":10,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":10},"identifierName":"yield"},
"name": "yield"
},
"operator": "+",
"right": {
"type": "TopicReference",
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "%"
}
]
],
"throws": "Unexpected => after pipeline body; any => expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:8)"
]
}

View File

@@ -0,0 +1,62 @@
{
"type": "File",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized arrow function expression; please wrap it in parentheses. (1:6)"
],
"program": {
"type": "Program",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"left": {
"type": "NumericLiteral",
"start":0,"end":2,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":2}},
"extra": {
"rawValue": 10,
"raw": "10"
},
"value": 10
},
"operator": "|>",
"right": {
"type": "ArrowFunctionExpression",
"start":6,"end":16,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":16}},
"id": null,
"generator": false,
"async": false,
"params": [
{
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"x"},
"name": "x"
}
],
"body": {
"type": "BinaryExpression",
"start":11,"end":16,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":16}},
"left": {
"type": "Identifier",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12},"identifierName":"x"},
"name": "x"
},
"operator": "+",
"right": {
"type": "TopicReference",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}
}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "%"
}
]
],
"throws": "Unexpected &&= after pipeline body; any &&= expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:11)"
}
]
}

View File

@@ -0,0 +1,44 @@
{
"type": "File",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized assignment expression; please wrap it in parentheses. (1:9)"
],
"program": {
"type": "Program",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}},
"left": {
"type": "Identifier",
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5},"identifierName":"value"},
"name": "value"
},
"operator": "|>",
"right": {
"type": "AssignmentExpression",
"start":9,"end":16,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":16}},
"operator": "&&=",
"left": {
"type": "Identifier",
"start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"x"},
"name": "x"
},
"right": {
"type": "TopicReference",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "%"
}
]
],
"throws": "Unexpected = after pipeline body; any = expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:16)"
}
]
}

View File

@@ -0,0 +1,55 @@
{
"type": "File",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized assignment expression; please wrap it in parentheses. (1:9)"
],
"program": {
"type": "Program",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"left": {
"type": "Identifier",
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5},"identifierName":"value"},
"name": "value"
},
"operator": "|>",
"right": {
"type": "AssignmentExpression",
"start":9,"end":19,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":19}},
"operator": "=",
"left": {
"type": "ArrayPattern",
"start":9,"end":15,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":15}},
"elements": [
{
"type": "Identifier",
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
"name": "x"
},
{
"type": "Identifier",
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"y"},
"name": "y"
}
]
},
"right": {
"type": "TopicReference",
"start":18,"end":19,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":19}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -7,6 +7,5 @@
"topicToken": "%"
}
]
],
"throws": "Unexpected += after pipeline body; any += expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (1:11)"
}
]
}

View File

@@ -0,0 +1,44 @@
{
"type": "File",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized assignment expression; please wrap it in parentheses. (1:9)"
],
"program": {
"type": "Program",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"left": {
"type": "Identifier",
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5},"identifierName":"value"},
"name": "value"
},
"operator": "|>",
"right": {
"type": "AssignmentExpression",
"start":9,"end":15,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":15}},
"operator": "+=",
"left": {
"type": "Identifier",
"start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"x"},
"name": "x"
},
"right": {
"type": "TopicReference",
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15}}
}
}
}
}
],
"directives": []
}
}

View File

@@ -0,0 +1,66 @@
{
"type": "File",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
"program": {
"type": "Program",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"left": {
"type": "NumericLiteral",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1}},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":5,"end":17,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":17}},
"left": {
"type": "CallExpression",
"start":5,"end":9,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":9}},
"callee": {
"type": "Identifier",
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"f"},
"name": "f"
},
"arguments": [
{
"type": "TopicReference",
"start":7,"end":8,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":8}}
}
]
},
"operator": "|>",
"right": {
"type": "CallExpression",
"start":13,"end":17,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":17}},
"callee": {
"type": "Identifier",
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"g"},
"name": "g"
},
"arguments": [
{
"type": "TopicReference",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}
}
]
}
}
}
}
],
"directives": []
}
}

View File

@@ -1,4 +0,0 @@
{
"plugins": [["pipelineOperator", { "proposal": "hack", "topicToken": "%" }]],
"throws": "Unexpected yield after pipeline body; any yield expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence. (2:14)"
}

View File

@@ -22,10 +22,6 @@
"right": {
"type": "ArrowFunctionExpression",
"start":6,"end":32,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":32}},
"extra": {
"parenthesized": true,
"parenStart": 5
},
"id": null,
"generator": false,
"async": false,
@@ -40,14 +36,14 @@
"type": "BinaryExpression",
"start":11,"end":32,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12}}
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":11,"end":23,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":23}},
"start":16,"end":32,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12}}
},
"operator": "|>",
"right": {
"type": "CallExpression",
"start":16,"end":23,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":23}},
"callee": {
@@ -66,27 +62,31 @@
"name": "$"
}
]
}
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":27,"end":32,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28}}
},
"operator": ">",
"operator": "|>",
"right": {
"type": "NumericLiteral",
"start":31,"end":32,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":32}},
"extra": {
"rawValue": 1,
"raw": "1"
"type": "BinaryExpression",
"start":27,"end":32,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":32}},
"left": {
"type": "TopicReference",
"start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28}}
},
"value": 1
"operator": ">",
"right": {
"type": "NumericLiteral",
"start":31,"end":32,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":32}},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
}
},
"extra": {
"parenthesized": true,
"parenStart": 5
}
}
}

View File

@@ -25,10 +25,6 @@
"right": {
"type": "ArrowFunctionExpression",
"start":6,"end":17,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":17}},
"extra": {
"parenthesized": true,
"parenStart": 5
},
"id": null,
"generator": false,
"async": false,
@@ -52,6 +48,10 @@
"type": "TopicReference",
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}}
}
},
"extra": {
"parenthesized": true,
"parenStart": 5
}
}
}

View File

@@ -26,10 +26,6 @@
"right": {
"type": "BinaryExpression",
"start":6,"end":12,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":12}},
"extra": {
"parenthesized": true,
"parenStart": 5
},
"left": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"$"},
@@ -40,6 +36,10 @@
"type": "Identifier",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12},"identifierName":"f"},
"name": "f"
},
"extra": {
"parenthesized": true,
"parenStart": 5
}
}
}

View File

@@ -0,0 +1,3 @@
{
"plugins": [["pipelineOperator", { "proposal": "hack", "topicToken": "%" }]]
}

View File

@@ -0,0 +1,11 @@
{
"plugins": [
[
"pipelineOperator",
{
"proposal": "hack",
"topicToken": "%"
}
]
]
}

View File

@@ -0,0 +1,64 @@
{
"type": "File",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: Hack-style pipe body cannot be an unparenthesized yield expression; please wrap it in parentheses. (2:14)"
],
"program": {
"type": "Program",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"id": {
"type": "Identifier",
"start":11,"end":12,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12},"identifierName":"f"},
"name": "f"
},
"generator": true,
"async": false,
"params": [
{
"type": "Identifier",
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"x"},
"name": "x"
}
],
"body": {
"type": "BlockStatement",
"start":17,"end":43,"loc":{"start":{"line":1,"column":17},"end":{"line":3,"column":1}},
"body": [
{
"type": "ReturnStatement",
"start":21,"end":41,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":22}},
"argument": {
"type": "BinaryExpression",
"start":28,"end":40,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":21}},
"left": {
"type": "Identifier",
"start":28,"end":29,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"x"},
"name": "x"
},
"operator": "|>",
"right": {
"type": "YieldExpression",
"start":33,"end":40,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":21}},
"delegate": false,
"argument": {
"type": "TopicReference",
"start":39,"end":40,"loc":{"start":{"line":2,"column":20},"end":{"line":2,"column":21}}
}
}
}
}
],
"directives": []
}
}
],
"directives": []
}
}

View File

@@ -0,0 +1,11 @@
{
"plugins": [
[
"pipelineOperator",
{
"proposal": "hack",
"topicToken": "%"
}
]
]
}

View File

@@ -0,0 +1,41 @@
{
"type": "File",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"program": {
"type": "Program",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"left": {
"type": "Identifier",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1},"identifierName":"x"},
"name": "x"
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":5,"end":14,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":14}},
"left": {
"type": "Identifier",
"start":5,"end":10,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":10},"identifierName":"yield"},
"name": "yield"
},
"operator": "+",
"right": {
"type": "TopicReference",
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14}}
}
}
}
}
],
"directives": []
}
}