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

Transform for F# Pipeline #9984

Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -0,0 +1,50 @@
import { types as t } from "@babel/core";

// tries to optimize sequence expressions in the format
// (a = b, ((c) => d + e)(a))
// to
// (a = b, a + e)
const buildOptimizedSequenceExpression = ({ assign, call, path }) => {

This comment has been minimized.

const { left: placeholderNode, right: pipelineLeft } = assign;
const { callee: calledExpression } = call;

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

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

call.callee = evalSequence;

return t.sequenceExpression([assign, call]);
}

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

if (param) {
path.get("right").scope.rename(param.name, placeholderNode.name);

return t.sequenceExpression([assign, calledExpression.body]);
}

return t.sequenceExpression([assign, call]);
};

export default buildOptimizedSequenceExpression;
@@ -0,0 +1,26 @@
import { types as t } from "@babel/core";
import buildOptimizedSequenceExpression from "./buildOptimizedSequenceExpression";

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

const placeholder = scope.generateUidIdentifierBasedOnNode(left);
scope.push({ id: placeholder });

const call =
right.type === "AwaitExpression"
? t.awaitExpression(t.cloneNode(placeholder))
: t.callExpression(right, [t.cloneNode(placeholder)]);
const sequence = buildOptimizedSequenceExpression({
assign: t.assignmentExpression("=", t.cloneNode(placeholder), left),
call,
path,
});
path.replaceWith(sequence);
},
};

export default fsharpVisitor;
@@ -2,10 +2,12 @@ import { declare } from "@babel/helper-plugin-utils";
import syntaxPipelineOperator from "@babel/plugin-syntax-pipeline-operator";
import minimalVisitor from "./minimalVisitor";
import smartVisitor from "./smartVisitor";
import fsharpVisitor from "./fsharpVisitor";

const visitorsPerProposal = {
minimal: minimalVisitor,
smart: smartVisitor,
fsharp: fsharpVisitor,
};

export default declare((api, options) => {
@@ -1,51 +1,22 @@
import { types as t } from "@babel/core";
import buildOptimizedSequenceExpression from "./buildOptimizedSequenceExpression";

const minimalVisitor = {
BinaryExpression(path) {
const { scope } = path;
const { node } = path;
const { operator, left } = node;
let { right } = node;
const { scope, node } = path;
const { operator, left, 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);
const placeholder = scope.generateUidIdentifierBasedOnNode(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)]);
const call = t.callExpression(right, [t.cloneNode(placeholder)]);
path.replaceWith(
t.sequenceExpression([
t.assignmentExpression("=", t.cloneNode(placeholder), left),
buildOptimizedSequenceExpression({
assign: t.assignmentExpression("=", t.cloneNode(placeholder), left),
call,
]),
path,
}),
);
},
};
@@ -0,0 +1,27 @@
const y = 2;

const f = (x) => (x |> (y) => y + 1)
|> (z) => z * y

const _f = (x) => x
|> (y) => y + 1
|> (z) => z * y

const g = (x) => x
|> (y) => (y + 1 |> (z) => z * y)

const _g = (x) => x
|> (y => (y + 1 |> (z) => z * y))

const __g = (x) => x
|> (
y => {
return (y + 1 |> (z) => z * y);
}
)

expect( f(1)).toBe(4);
expect( _f(1)).toBe(4);
expect( g(1)).toBe(2);
expect( _g(1)).toBe(2);
expect(__g(1)).toBe(2);
@@ -0,0 +1,14 @@
var result = [5,10]
|> (_ => _.map(x => x * 2))
|> (_ => _.reduce( (a,b) => a + b ))
|> (sum => sum + 1)

expect(result).toBe(31);


var inc = (x) => x + 1;
var double = (x) => x * 2;

var result2 = [4, 9].map( x => x |> inc |> double )

expect(result2).toEqual([10, 20]);
@@ -0,0 +1,14 @@
var result = [5,10]
|> (_ => _.map(x => x * 2))
|> (_ => _.reduce( (a,b) => a + b ))
|> (sum => sum + 1)

expect(result).toBe(31);


var inc = (x) => x + 1;
var double = (x) => x * 2;

var result2 = [4, 9].map( x => x |> inc |> double )

expect(result2).toEqual([10, 20]);
@@ -0,0 +1,15 @@
var _ref, _ref2, _ref3;

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

var inc = x => x + 1;

var double = x => x * 2;

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

return _ref4 = (_x = x, inc(_x)), double(_ref4);
});
expect(result2).toEqual([10, 20]);
@@ -0,0 +1,13 @@
const triple = (x) => x * 3;

async function myFunction(n) {
return n
|> Math.abs
|> Promise.resolve
|> await
|> triple;
}

return myFunction(-7).then(result => {
expect(result).toBe(21);
});
@@ -0,0 +1,6 @@
async function myFunction(n) {
return n
|> Math.abs
|> Promise.resolve
|> await;
}
@@ -0,0 +1,9 @@
{
"plugins": [
["proposal-pipeline-operator", { "proposal": "fsharp" }]
],
"parserOpts": {
"allowReturnOutsideFunction": true
},
"minNodeVersion": "8.0.0"
}
@@ -0,0 +1,5 @@
async function myFunction(n) {
var _ref, _ref2, _n;

return _ref = (_ref2 = (_n = n, Math.abs(_n)), Promise.resolve(_ref2)), await _ref;
}
@@ -0,0 +1,3 @@
var inc = (x) => x + 1

expect(10 |> inc).toBe(11);
@@ -0,0 +1,3 @@
var inc = (x) => x + 1

expect(10 |> inc).toBe(11);
@@ -0,0 +1,5 @@
var _;

var inc = x => x + 1;

expect((_ = 10, inc(_))).toBe(11);
@@ -0,0 +1,7 @@
(function() {
'use strict';
var result = '(function() { return this; })()'
|> eval;

expect(result).not.toBeUndefined();
})();
@@ -0,0 +1,7 @@
(function() {
'use strict';
var result = '(function() { return this; })()'
|> eval;

expect(result).not.toBeUndefined();
})();
@@ -0,0 +1,8 @@
(function () {
'use strict';

var _functionReturn;

var result = (_functionReturn = '(function() { return this; })()', (0, eval)(_functionReturn));
expect(result).not.toBeUndefined();
})();
@@ -0,0 +1,5 @@
var array = [10,20,30];

var last = array |> (a => a[a.length-1]);

expect(last).toBe(30);
@@ -0,0 +1,5 @@
var _array;

var array = [10, 20, 30];
var last = (_array = array, _array[_array.length - 1]);
expect(last).toBe(30);
@@ -0,0 +1,8 @@
var a = 1,
b = 2,
c = 3;
var result = a
|> (() => b)
|> (() => c);

expect(result).toBe(c);
@@ -0,0 +1,8 @@
var a = 1,
b = 2,
c = 3;
var result = a
|> (() => b)
|> (() => c);

expect(result).toBe(c);
@@ -0,0 +1,7 @@
var _ref, _a;

var a = 1,
b = 2,
c = 3;
var result = ((a, b), c);
expect(result).toBe(c);
@@ -0,0 +1,8 @@
{
"plugins": [
["proposal-pipeline-operator", { "proposal": "fsharp" }]
],
"parserOpts": {
"allowReturnOutsideFunction": true
}
}
@@ -0,0 +1,20 @@
const y = 2;
const f = (x) => x
|> (y => y + 1)
|> (z => z * y)

const g = (x) => x
|> (y =>
y + 1
|> (z => z * y)
)

const h = (x) => x
|> (y => (
y + 1
|> (z => z * y)
))

expect(f(1)).toBe(4);
expect(g(1)).toBe(2);
expect(h(1)).toBe(2);
@@ -0,0 +1,20 @@
const y = 2;
const f = (x) => x
|> (y => y + 1)
|> (z => z * y)

const g = (x) => x
|> (y =>
y + 1
|> (z => z * y)
)

const h = (x) => x
|> (y => (
y + 1
|> (z => z * y)
))

expect(f(1)).toBe(4);
expect(g(1)).toBe(2);
expect(h(1)).toBe(2);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.