Merge pull request #701 from RReverser/master

Add tail recursion optimization.
This commit is contained in:
Sebastian McKenzie
2015-02-07 23:37:43 +11:00
12 changed files with 427 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
(function f(n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
return Math.random() > 0.5 ? f.call(this, n - 1) : f.apply(this, [n - 1]);
})(1e6) === "foo";

View File

@@ -0,0 +1,27 @@
"use strict";
(function f(n) {
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
if (Math.random() > 0.5) {
_arguments = [n - 1];
_this = this;
return _shouldContinue = true;
} else {
_arguments = [n - 1];
_this = this;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000) === "foo";

View File

@@ -0,0 +1,3 @@
(function f(n) {
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || f(n - 1)));
})(1e6, true) === "foo";

View File

@@ -0,0 +1,30 @@
"use strict";
(function f(n) {
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
var _left;
if (n <= 0) {
return "foo";
} else {
doSmth();
if (!(_left = getTrueValue())) {
return _left;
}
if (_left = getFalseValue()) {
return _left;
}
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000, true) === "foo";

View File

@@ -0,0 +1,8 @@
(function f(n = getDefaultValue(), /* should be undefined after first pass */ m) {
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
return f(n - 1);
})(1e6, true) === "foo";

View File

@@ -0,0 +1,9 @@
var timeLimit = Date.now() + 5000;
assert.equal((function f(n) {
assert.operator(Date.now(), '<', timeLimit, "Timeout");
if (n <= 0) {
return "foo";
}
return f(n - 1);
})(1e6), "foo");

View File

@@ -0,0 +1,23 @@
"use strict";
(function f(_x, /* should be undefined after first pass */m) {
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (_x, m) {
var n = arguments[0] === undefined ? getDefaultValue() : arguments[0];
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000, true) === "foo";

View File

@@ -0,0 +1,39 @@
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
return f(n - 1);
} catch (e) {}
})(1e6) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return f(n - 1);
}
})(1e6) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return f(n - 1);
} finally {}
})(1e6) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {} finally {
return f(n - 1);
}
})(1e6) === "foo";

View File

@@ -0,0 +1,65 @@
"use strict";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
return f(n - 1);
} catch (e) {}
})(1000000) === "foo";
(function f(n) {
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return f(n - 1);
} finally {}
})(1000000) === "foo";
(function f(n) {
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
if (n <= 0) {
return "foo";
}
try {} finally {
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000) === "foo";