Clean up transformations after #714.

Since now we have runtime helper, we don't need
expression -> statement conversions anymore.
This commit is contained in:
Ingvar Stepanyan 2015-02-08 10:15:25 +02:00
parent cde988f99f
commit 91362f80b1
7 changed files with 23 additions and 82 deletions

View File

@ -12,51 +12,21 @@ function transformExpression(node, scope, state) {
return (function subTransform(node) { return (function subTransform(node) {
switch (node.type) { switch (node.type) {
case "ConditionalExpression": case "ConditionalExpression":
var callConsequent = subTransform(node.consequent); // any value of ternary operator can be final one
var callAlternate = subTransform(node.alternate); subTransform(node.consequent);
if (!callConsequent && !callAlternate) { subTransform(node.alternate);
return; break;
}
// if ternary operator had tail recursion in value, convert to optimized if-statement
node.type = "IfStatement";
node.consequent = callConsequent ? t.toBlock(callConsequent) : returnBlock(node.consequent);
if (callAlternate) {
node.alternate = t.isIfStatement(callAlternate) ? callAlternate : t.toBlock(callAlternate);
} else {
node.alternate = returnBlock(node.alternate);
}
return [node];
case "LogicalExpression": case "LogicalExpression":
// only call in right-value of can be optimized // only right expression can be final and so optimized
var callRight = subTransform(node.right); subTransform(node.right);
if (!callRight) { break;
return;
}
var test = state.wrapSideEffect(node.left);
if (node.operator === "&&") {
test.expr = t.unaryExpression("!", test.expr);
}
return [t.ifStatement(test.expr, returnBlock(test.ref))].concat(callRight);
case "SequenceExpression": case "SequenceExpression":
// only last element of sequence can be optimized
var seq = node.expressions; var seq = node.expressions;
subTransform(seq[seq.length - 1]);
// only last element can be optimized break;
var lastCall = subTransform(seq[seq.length - 1]);
if (!lastCall) {
return;
}
// remove converted expression from sequence
// and convert to regular expression if needed
if (--seq.length === 1) {
node = seq[0];
}
return [t.expressionStatement(node)].concat(lastCall);
case "CallExpression": case "CallExpression":
var callee = node.callee, thisBinding; var callee = node.callee, thisBinding;
@ -77,10 +47,9 @@ function transformExpression(node, scope, state) {
args.push(thisBinding); args.push(thisBinding);
} }
return [t.returnStatement(t.callExpression( node.callee = state.getHelperRef();
state.getHelperRef(), node.arguments = args;
args break;
))];
} }
})(node); })(node);
} }
@ -92,7 +61,8 @@ var functionChildrenVisitor = {
this.skip(); this.skip();
// transform return argument into statement if // transform return argument into statement if
// it contains tail recursion // it contains tail recursion
return transformExpression(node.argument, scope, state); transformExpression(node.argument, scope, state);
return;
} else if (t.isFunction(node)) { } else if (t.isFunction(node)) {
return this.skip(); return this.skip();
} else if (t.isTryStatement(parent)) { } else if (t.isTryStatement(parent)) {

View File

@ -5,9 +5,5 @@
console.log(this, arguments); console.log(this, arguments);
return "foo"; return "foo";
} }
if (Math.random() > 0.5) { return Math.random() > 0.5 ? to5Runtime.tailCall(f.call, [this, n - 1], f) : to5Runtime.tailCall(f.apply, [this, [n - 1]], f);
return to5Runtime.tailCall(f.call, [this, n - 1], f);
} else {
return to5Runtime.tailCall(f.apply, [this, [n - 1]], f);
}
})(1000000) === "foo"; })(1000000) === "foo";

View File

@ -1,7 +1,7 @@
function f(n) { function f(n) {
return n <= 0 ? "foo" : g(n - 1); return n <= 0 ? "foo" : g(n - 1);
} }
function g(n) { function g(n) {
return n <= 0 ? "goo" : f(n - 1); return n <= 0 ? "goo" : f(n - 1);
} }

View File

@ -1,17 +1,9 @@
"use strict"; "use strict";
function f(n) { function f(n) {
if (n <= 0) { return n <= 0 ? "foo" : to5Runtime.tailCall(g, [n - 1]);
return "foo";
} else {
return to5Runtime.tailCall(g, [n - 1]);
}
} }
function g(n) { function g(n) {
if (n <= 0) { return n <= 0 ? "goo" : to5Runtime.tailCall(f, [n - 1]);
return "goo";
} else {
return to5Runtime.tailCall(f, [n - 1]);
}
} }

View File

@ -1,18 +1,5 @@
"use strict"; "use strict";
(function f(n) { (function f(n) {
var _temp; return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || to5Runtime.tailCall(f, [n - 1])));
if (n <= 0) {
return "foo";
} else {
doSmth();
if (!(_temp = getTrueValue())) {
return _temp;
}
if (_temp = getFalseValue()) {
return _temp;
}
return to5Runtime.tailCall(f, [n - 1]);
}
})(1000000, true) === "foo"; })(1000000, true) === "foo";

View File

@ -1,5 +1,5 @@
function f() { function f() {
return getObj().method(); return getObj().method();
} }
function g() { function g() {

View File

@ -6,9 +6,5 @@ function f() {
} }
function g() { function g() {
var _temp; return getFalseValue() || to5Runtime.tailCall(getValue);
if (_temp = getFalseValue()) {
return _temp;
}
return to5Runtime.tailCall(getValue);
} }