2007年 11月 29日

JavaScript tailcall...

function Process () {
	this.init.apply(this);
}
Process.prototype = {
	init: function () {
		var self = this;
		this.stack = [];
		this.rvalue = undefined;
		setTimeout(function () { self.call() }, 0);
	},

	p: function (f) {
		this.stack.unshift(f);
		return this;
	},

	call: function () {
		var self = this;
		var f = this.stack.pop();
		var thisObj = {};
		thisObj.call = function (f, args) {
			args = Array.prototype.slice.call(arguments);
			f    = args.shift();
			self.stack.push(function () {
				return f.apply(thisObj, args);
			});
			return "this";
		};
		this._rvalue = f.call(thisObj, this._rvalue);
		if (this.stack.length) {
			setTimeout(function () { self.call() }, 0);
		}
	}
};

window.onload = function () {
	var ps = new Process();

	ps.p(function () {
		$("#content").append("<div>start!</div>");
	}).p(function () {
		function pow (x, n) {
			function _pow (n, r) {
				$("#content").append("<div>"+[n, r]+"</div>");
				if (n == 0) return r;
				return this.call(_pow, n - 1, x * r);
			};
			return this.call(_pow, n, 1);
		}
		return this.call(pow, 2, 1000);
	}).p(function (r) {
		$("#content").append("<div>end!"+r+"</div>");
	});
};

nemui