できるだけ短い継続インタプリタ

call-ccの実装がとりあえず出来たっぽいバージョン
よくわかってないので、怪しい。

<script>
Array.prototype.toString = function(){ return "["+this.join(",")+"]"}
Object.prototype.toString = function(){ var a = []; for(var i in this) a.push(i+":"+this[i]); return "{"+a.join(",")+"}"}
function log(s){ document.write(s+"<br>"); return s }
function eval(s, env, k) {
	function getEnv(env, a) {
		if (env[a] != null) return env[a];
		if (env.parent == null) throw "error not get value " + a;
		return getEnv(env.parent, a);
	}
	function setEnv(env, a, v) {
		if (env[a] != null) return env[a] = v;
		if (env.parent == null) throw "error not set value " + a;
		return setEnv(env.parent, a, v);
	}
	function begin(n,env){
		return eval(s[n], env, function(u){
			if (n >= s.length-1) return k(u)
			return k(begin(n+1,env))
		})
	}
	if (k == null) k = function(u){return u;}
	function apply(lambda, newenv, s, i) {
		if (i == lambda[1].length) return eval(lambda[2],newenv,function(v){return k(v)})
		else                       return eval(s[i+1], env, function(v){ newenv[lambda[1][i]]=v; return apply(lambda,newenv,s,i+1)})
	}
	if (env == null) env = {};
	if (s instanceof Array) {
		switch (s[0]) {
		case "add":    return eval(s[1],env,function(u){return eval(s[2],env,function(v){return k(u+v)})})
		case "mul":    return eval(s[1],env,function(u){return eval(s[2],env,function(v){return k(u*v)})})
		case "cont":   return ["#cont",s[1], env,k]
		case "list":   return k(s[1])
		case "callCC": var cont = ["#cont",null,env,null];
			           return k(eval([s[1], ["list",cont]], env, function(v){cont[3]=function(u){return k(v)}; return v}))
		case "#cont":  return eval(s[1],s[2],s[3])
		case "define": return eval(s[2],env,function(u){return k(env[s[1]] = u)})
		case "set":    return eval(s[2],env,function(u){return k(setEnv(env, s[1], u))})
		case "begin":  return begin(1,env)
		case "lambda": return k(["#closure", s, {parent:env}])
		case "alert":  return eval(s[1], env, function(v){alert(v); return k(v)})
		}
		return eval(s[0], env, function(data){
			if (data instanceof Array && data[0] == "#closure") return apply(data[1], data[2], s, 0)
			if (data instanceof Array && data[0] == "#cont") return eval(data,env,k)
			return k(data)
		})
	}
	if (typeof(s) == "string") return k(getEnv(env, s))
	return k(s)
}
var env = {};
try{
	log(eval(["add",1,2],env));
	log(eval(["define","a",555],env));
	log(env["a"]);
	log(eval(["begin",["define","a",["add",1,2]],["define","b",2],["mul","a","b"]]));
	c = eval(["begin",["define","a",["add",1,2]],["cont"],["define","b",2],["cont"],["mul","a","b"]]);
	log(c);
	log(c2=eval(c));
	log(eval(c2));
	log(c2=eval(c));
	log(eval(c2));
	log(c2=eval(c));
	log(eval(c2));
	log("<hr>");
	log(eval(["define","a",["add",["mul",2,3],2]],env));
	log(eval("a",env));
	log(eval(["begin",["define","a",["add",1,2]],["define","b",["add",1,2]],["add","a","b"]]));
	log(eval(["begin",["define","data",1],["define","c",["lambda",["a","b"],["add",["add","a","b"],"data"]]],["begin",["define","data",2],["c",2,"data"]]]));
	log(eval([["lambda",["a","b"],["add","a","b"]],1,2]));
	log(eval(["begin",["define","data",1],["define","c",["lambda",["a","b"],["add",["add","a","b"],"data"]]],"c"]));
	c = eval(["begin",["define","data",1],["alert","data"],["cont"],["set","data",["add","data",1]],["alert","data"]]);
	log(c);
	log(eval(c));
	log(eval(["begin",["define","d",1],["add", ["callCC",["lambda",["c"],["begin",["set","d","c"],2]]] ,5]],env))

	log(eval(["begin",
		["define","c",0],
		["define","d",0],
		["callCC",["lambda",["a"],["set","c","a"]]],
		["set","d",["add","d",1]]
	],env))
	log(eval(["c"],env))
	log(eval(["c"],env))
	log(eval(["c"],env))
	log(eval(["c"],env))
	log(eval(["c"],env))
	log(eval(["c"],env))
}catch(e){(e)}
</script>