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

この間ものの継続渡しバージョン+α
今までのは、fiberみたいなものだったので、call-ccを作ろうと思ってるけど、出来てない。
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": return k(eval([s[1],["list",["#cont",s[1],env,k]]],env,null))
		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,{parent: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]]))
//	log(eval(["begin",["define","d",1],["add",2,["callCC",["lambda",["c"],["begin",["set","d","c"],20]]]],["alert",["d"]],["alert","d"]]))
}catch(e){log(e)}
</script>