better control flow for tco continuation - fixes #850 and fixes #822

This commit is contained in:
Sebastian McKenzie
2015-02-21 12:27:24 +11:00
parent 8d92a75190
commit 6220fd9fc3
9 changed files with 55 additions and 43 deletions

View File

@@ -1,3 +1,4 @@
{
FUNCTION_ID:while (true) BLOCK
var AGAIN_ID = true;
FUNCTION_ID: while (AGAIN_ID) BLOCK
}

View File

@@ -1,23 +0,0 @@
(function () {
function Tail(func, args, context) {
this.func = func;
this.args = args;
this.context = context;
}
Tail.prototype._isTailDescriptor = true;
var isRunning = false;
return function (func, args, context) {
var result = new Tail(func, args, context);
if (!isRunning) {
isRunning = true;
do {
result = result.func.apply(result.context, result.args);
} while (result instanceof Tail || (result && result._isTailDescriptor));
isRunning = false;
}
return result;
};
})()

View File

@@ -40,6 +40,10 @@ TailCallTransformer.prototype.getFunctionId = function () {
return this.functionId = this.functionId || this.scope.generateUidIdentifier("function");
};
TailCallTransformer.prototype.getAgainId = function () {
return this.againId = this.againId || this.scope.generateUidIdentifier("again");
};
TailCallTransformer.prototype.getParams = function () {
var params = this.params;
@@ -112,9 +116,12 @@ TailCallTransformer.prototype.run = function () {
body.unshift(t.variableDeclaration("var", paramDecls));
}
body.push(t.returnStatement());
body.unshift(t.expressionStatement(
t.assignmentExpression("=", this.getAgainId(), t.literal(false)))
);
node.body = util.template("tail-call-body", {
AGAIN_ID: this.getAgainId(),
THIS_ID: this.thisId,
ARGUMENTS_ID: this.argumentsId,
FUNCTION_ID: this.getFunctionId(),
@@ -288,6 +295,9 @@ TailCallTransformer.prototype.subTransformCallExpression = function (node) {
}
}
body.push(t.expressionStatement(
t.assignmentExpression("=", this.getAgainId(), t.literal(true))
));
body.push(t.continueStatement(this.getFunctionId()));
return body;