できるだけ短い継続インタプリタ
この間ものの継続渡しバージョン+α
今までのは、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>