Skip to content

Instantly share code, notes, and snippets.

@aholmes
Created May 9, 2015 06:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aholmes/8f6bee6334ddb849b751 to your computer and use it in GitHub Desktop.
Save aholmes/8f6bee6334ddb849b751 to your computer and use it in GitHub Desktop.
Trampoline (indirect jump) implementation in TypeScript
var Trampoline = (function ()
{
function Trampoline(func, baseConditionReachedFunc)
{
var _this = this;
this.func = func;
this.baseConditionReachedFunc = baseConditionReachedFunc;
if (typeof func !== 'function') throw new Error('Wrong type');
this.wrappedFunc = function ()
{
var args = [];
for (var _i = 0; _i < arguments.length; _i++)
{
args[_i - 0] = arguments[_i];
}
return (args instanceof Array)
? func.apply(_this.func, args)
: func.call(_this.func, args);
};
}
Trampoline.prototype.Execute = function ()
{
var args = [];
for (var _i = 0; _i < arguments.length; _i++)
{
args[_i - 0] = arguments[_i];
}
var func = this.wrappedFunc;
// Because the base condition test function signifies that the
// iterative state has reached what will trigger the base condition,
// the recursive method needs to be called so that it can do what
// it needs to do when that base condition has been met.
// That is why the base condition test is checked first, and then
// the recursive method is called.
var baseConditionReachedOnNextCall = false;
do
{
baseConditionReachedOnNextCall = args instanceof Array
? this.baseConditionReachedFunc.apply(this.baseConditionReachedFunc, args)
: this.baseConditionReachedFunc.call(this.baseConditionReachedFunc, args);
args = args instanceof Array
? func.apply(this.func, args)
: func.call(this.func, args);
} while (!baseConditionReachedOnNextCall);
return args;
};
return Trampoline;
})();
// fibonacci
var t = new Trampoline(
function (n, a, b) { return n > 0 ? [n - 1, b || 1, (a || 0) + (b || 1)] : a; },
function (n, a, b) { return n === 0; }
);
t.Execute(50);
t.Execute(100);
t.Execute(1000);
t.Execute(500000);
class Trampoline
{
private wrappedFunc: (...args: any[]) => any;
constructor(private func: (...args: any[]) => any, private baseConditionReachedFunc: (...args: any[]) => boolean)
{
if (typeof func !== 'function') throw new Error('Wrong type');
this.wrappedFunc = (...args: any[]) =>
{
return (args instanceof Array)
? func.apply(this.func, args)
: func.call(this.func, args);
};
}
public Execute(...args: any[])
{
let func = this.wrappedFunc;
// Because the base condition test function signifies that the
// iterative state has reached what will trigger the base condition,
// the recursive method needs to be called so that it can do what
// it needs to do when that base condition has been met.
// That is why the base condition test is checked first, and then
// the recursive method is called.
let baseConditionReachedOnNextCall = false;
do
{
baseConditionReachedOnNextCall = args instanceof Array
? this.baseConditionReachedFunc.apply(this.baseConditionReachedFunc, args)
: this.baseConditionReachedFunc.call(this.baseConditionReachedFunc, args);
args = args instanceof Array
? func.apply(this.func, args)
: func.call(this.func, args);
} while (!baseConditionReachedOnNextCall)
return args;
}
}
// fibonacci
var t = new Trampoline(
(n, a, b) => n > 0 ? [n - 1, b || 1, (a || 0) + (b || 1)] : a,
(n, a, b) => n === 0
);
t.Execute(50);
t.Execute(100);
t.Execute(1000);
t.Execute(500000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment