Skip to content

Commit

Permalink
Transform for the smart pipeline operator proposal (#9179)
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagoarrais authored and nicolo-ribaudo committed Jan 21, 2019
1 parent ba41419 commit e9331aa
Show file tree
Hide file tree
Showing 65 changed files with 240 additions and 62 deletions.
63 changes: 9 additions & 54 deletions packages/babel-plugin-proposal-pipeline-operator/src/index.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,19 @@
import { declare } from "@babel/helper-plugin-utils";
import syntaxPipelineOperator from "@babel/plugin-syntax-pipeline-operator";
import { types as t } from "@babel/core";
import minimalVisitor from "./minimalVisitor";
import smartVisitor from "./smartVisitor";

export default declare(api => {
const visitorsPerProposal = {
minimal: minimalVisitor,
smart: smartVisitor,
};

export default declare((api, options) => {
api.assertVersion(7);

return {
name: "proposal-pipeline-operator",
inherits: syntaxPipelineOperator,

visitor: {
BinaryExpression(path) {
const { scope } = path;
const { node } = path;
const { operator, left } = node;
let { right } = node;
if (operator !== "|>") return;

let optimizeArrow =
t.isArrowFunctionExpression(right) &&
t.isExpression(right.body) &&
!right.async &&
!right.generator;
let param;

if (optimizeArrow) {
const { params } = right;
if (params.length === 1 && t.isIdentifier(params[0])) {
param = params[0];
} else if (params.length > 0) {
optimizeArrow = false;
}
} else if (t.isIdentifier(right, { name: "eval" })) {
right = t.sequenceExpression([t.numericLiteral(0), right]);
}

if (optimizeArrow && !param) {
// Arrow function with 0 arguments
path.replaceWith(t.sequenceExpression([left, right.body]));
return;
}

const placeholder = scope.generateUidIdentifierBasedOnNode(
param || left,
);
scope.push({ id: placeholder });
if (param) {
path.get("right").scope.rename(param.name, placeholder.name);
}

const call = optimizeArrow
? right.body
: t.callExpression(right, [t.cloneNode(placeholder)]);
path.replaceWith(
t.sequenceExpression([
t.assignmentExpression("=", t.cloneNode(placeholder), left),
call,
]),
);
},
},
visitor: visitorsPerProposal[options.proposal],
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { types as t } from "@babel/core";

const minimalVisitor = {
BinaryExpression: {
exit(path) {
const { scope } = path;
const { node } = path;
const { operator, left } = node;
let { right } = node;
if (operator !== "|>") return;

let optimizeArrow =
t.isArrowFunctionExpression(right) &&
t.isExpression(right.body) &&
!right.async &&
!right.generator;
let param;

if (optimizeArrow) {
const { params } = right;
if (params.length === 1 && t.isIdentifier(params[0])) {
param = params[0];
} else if (params.length > 0) {
optimizeArrow = false;
}
} else if (t.isIdentifier(right, { name: "eval" })) {
right = t.sequenceExpression([t.numericLiteral(0), right]);
}

if (optimizeArrow && !param) {
// Arrow function with 0 arguments
path.replaceWith(t.sequenceExpression([left, right.body]));
return;
}

const placeholder = scope.generateUidIdentifierBasedOnNode(param || left);
scope.push({ id: placeholder });
if (param) {
path.get("right").scope.rename(param.name, placeholder.name);
}

const call = optimizeArrow
? right.body
: t.callExpression(right, [t.cloneNode(placeholder)]);
path.replaceWith(
t.sequenceExpression([
t.assignmentExpression("=", t.cloneNode(placeholder), left),
call,
]),
);
},
},
};

export default minimalVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { types as t } from "@babel/core";
import minimalVisitor from "./minimalVisitor";

const updateTopicReferenceVisitor = {
PipelinePrimaryTopicReference(path) {
path.replaceWith(this.topicId);
},
AwaitExpression(path) {
throw path.buildCodeFrameError(
"await is not supported inside pipeline expressions yet",
);
},
YieldExpression(path) {
throw path.buildCodeFrameError(
"yield is not supported inside pipeline expressions yet",
);
},
PipelineTopicExpression(path) {
path.skip();
},
};

const smartVisitor = {
...minimalVisitor,
PipelineTopicExpression(path) {
const topicId = path.scope.generateUidIdentifier("topic");

path.traverse(updateTopicReferenceVisitor, { topicId });

const arrowFunctionExpression = t.arrowFunctionExpression(
[topicId],
path.node.expression,
);

path.replaceWith(arrowFunctionExpression);
},
PipelineBareFunction(path) {
path.replaceWith(path.node.callee);
},
};

export default smartVisitor;
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
var _sum, _ref, _ref2;
var _ref, _ref2, _sum;

var result = (_sum = (_ref = (_ref2 = [5, 10], _ref2.map(x => x * 2)), _ref.reduce((a, b) => a + b)), _sum + 1);
var result = (_sum = (_ref2 = (_ref = [5, 10], _ref.map(x => x * 2)), _ref2.reduce((a, b) => a + b)), _sum + 1);
expect(result).toBe(31);

var inc = x => x + 1;

var double = x => x * 2;

var result2 = [4, 9].map(x => {
var _ref3, _x;
var _x, _ref3;

return _ref3 = (_x = x, inc(_x)), double(_ref3);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var _ref, _;
var _, _ref;

function then(fn) {
return async value => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var _ref, _;
var _, _ref;

var inc = x => x + 1;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var _ref, _a;
var _a, _ref;

var a = 1,
b = 2,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var _ref, _ref2, _;
var _ref, _, _ref2;

var inc = x => x + 1;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
async function myFunction() {
const value = -5.9
|> abs
|> await Math.floor(#);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"throws": "await is not supported inside pipeline expressions yet",
"plugins": [
["proposal-pipeline-operator", { "proposal": "smart" }]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const abs = Math.abs;

const value = -5.9
|> abs
|> Math.floor;

expect(value).toBe(5);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const abs = Math.abs;

const value = -5.9
|> abs
|> Math.floor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var _ref, _ref2;

const abs = Math.abs;
const value = (_ref2 = (_ref = -5.9, abs(_ref)), Math.floor(_ref2));
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var result = 5
|> # + 1
|> # + #
|> Math.pow(((x) => (x * 7))(#), 2)

expect(result).toBe(7056);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var result = 5
|> # + 1
|> # + #
|> Math.pow(((x) => (x * 7))(#), 2)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var _topic2, _topic4, _topic6;

var result = (_topic6 = (_topic4 = (_topic2 = 5, _topic2 + 1), _topic4 + _topic4), Math.pow((x => x * 7)(_topic6), 2));
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var result = 5
|> Math.pow(#, 2)
|> [ 10, 20, 30, 40, 50 ].filter(n => #
|> n > #
|> !#);

expect(result).toEqual([10, 20]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var result = 5
|> Math.pow(#, 2)
|> [ 10, 20, 30, 40, 50 ].filter(n => #
|> n > #
|> !#);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var _topic2, _topic8;

var result = (_topic8 = (_topic2 = 5, Math.pow(_topic2, 2)), [10, 20, 30, 40, 50].filter(n => {
var _topic5, _topic7;

return _topic7 = (_topic5 = _topic8, n > _topic5), !_topic7;
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function area(rect) {
return rect.width * rect.height;
}

const result = -5
|> Math.abs
|> ({ width: #, height: # + 3 })
|> area;

expect(result).toBe(40);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function area(rect) {
return rect.width * rect.height;
}

const result = -5
|> Math.abs
|> ({ width: #, height: # + 3 })
|> area;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
var _ref, _topic2, _ref2;

function area(rect) {
return rect.width * rect.height;
}

const result = (_ref2 = (_topic2 = (_ref = -5, Math.abs(_ref)), {
width: _topic2,
height: _topic2 + 3
}), area(_ref2));
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
["proposal-pipeline-operator", { "proposal": "smart" }]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v |> #.method |> f;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var _topic2, _ref;

_ref = (_topic2 = v, _topic2.method), f(_ref);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const result = -2.2 // -2.2
|> Math.floor // -3
|> (() => Math.pow(#, 5)) // () => -243
|> #() // -243
|> Math.sign; // -1

expect(result).toBe(-1);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const result = -2.2 // -2.2
|> Math.floor // -3
|> (() => Math.pow(#, 5)) // () => -243
|> #() // -243
|> Math.sign; // -1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var _ref, _topic2, _topic4, _ref2;

const result = (_ref2 = (_topic4 = (_topic2 = (_ref = -2.2 // -2.2
, Math.floor(_ref) // -3
), () => Math.pow(_topic2, 5) // () => -243
), _topic4() // -243
), Math.sign(_ref2)); // -1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function *myGenerator() {
return v
|> (yield #)
|> g;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"throws": "yield is not supported inside pipeline expressions yet",
"plugins": [
["proposal-pipeline-operator", { "proposal": "smart" }]
]
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { declare } from "@babel/helper-plugin-utils";

export const proposals = ["minimal"];
export const proposals = ["minimal", "smart"];

export default declare((api, { proposal }) => {
api.assertVersion(7);
Expand Down

0 comments on commit e9331aa

Please sign in to comment.