remove old tail call transformer
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
function transformExpression(node, scope, state) {
|
||||
if (!node) return;
|
||||
|
||||
return (function subTransform(node) {
|
||||
switch (node.type) {
|
||||
case "ConditionalExpression":
|
||||
// any value of ternary operator can be final one
|
||||
subTransform(node.consequent);
|
||||
subTransform(node.alternate);
|
||||
break;
|
||||
|
||||
case "LogicalExpression":
|
||||
// only right expression can be final and so optimized
|
||||
subTransform(node.right);
|
||||
break;
|
||||
|
||||
case "SequenceExpression":
|
||||
// only last element of sequence can be optimized
|
||||
var seq = node.expressions;
|
||||
subTransform(seq[seq.length - 1]);
|
||||
break;
|
||||
|
||||
case "CallExpression":
|
||||
var callee = node.callee, thisBinding;
|
||||
var args = [callee];
|
||||
|
||||
// bind `this` to object in member expressions
|
||||
if (t.isMemberExpression(callee)) {
|
||||
var object = state.wrapSideEffect(callee.object);
|
||||
callee.object = object.expr;
|
||||
thisBinding = object.ref;
|
||||
}
|
||||
|
||||
if (node.arguments.length > 0 || thisBinding) {
|
||||
args.push(t.arrayExpression(node.arguments));
|
||||
}
|
||||
|
||||
if (thisBinding) {
|
||||
args.push(thisBinding);
|
||||
}
|
||||
|
||||
node.callee = state.getHelperRef();
|
||||
node.arguments = args;
|
||||
break;
|
||||
}
|
||||
})(node);
|
||||
}
|
||||
|
||||
var functionChildrenVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isReturnStatement(node)) {
|
||||
// prevent entrance by current visitor
|
||||
this.skip();
|
||||
// transform return argument into statement if
|
||||
// it contains tail recursion
|
||||
transformExpression(node.argument, scope, state);
|
||||
} else if (t.isFunction(node)) {
|
||||
// inner function's bodies are irrelevant
|
||||
this.skip();
|
||||
} else if (t.isTryStatement(parent)) {
|
||||
if (node === parent.block) {
|
||||
// `try`-blocks can't be optimized
|
||||
this.skip();
|
||||
} else if (parent.finalizer && node !== parent.finalizer) {
|
||||
// `catch` clause followed by `finally` can't be optimized
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var functionVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
// traverse all child nodes of this function and find `arguments` and `this`
|
||||
scope.traverse(node, functionChildrenVisitor, state);
|
||||
|
||||
return this.skip();
|
||||
}
|
||||
};
|
||||
|
||||
exports.FunctionDeclaration =
|
||||
exports.FunctionExpression = function (node, parent, scope, file) {
|
||||
var tempId, helperRef;
|
||||
|
||||
var state = {
|
||||
ownerId: node.id,
|
||||
|
||||
getHelperRef: function () {
|
||||
return helperRef = helperRef || file.addHelper("tail-call");
|
||||
},
|
||||
|
||||
wrapSideEffect: function (node) {
|
||||
if (t.isIdentifier(node) || t.isLiteral(node)) {
|
||||
return {expr: node, ref: node};
|
||||
}
|
||||
tempId = tempId || scope.generateUidIdentifier("temp");
|
||||
return {
|
||||
expr: t.assignmentExpression("=", tempId, node),
|
||||
ref: tempId
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// traverse the function and look for tail recursion
|
||||
scope.traverse(node, functionVisitor, state);
|
||||
|
||||
if (tempId) {
|
||||
t.ensureBlock(node).body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(tempId)
|
||||
]));
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user