継続インタプリタ
やっぱり、継続をまちがえてたので修正した。
まだ間違えているかもしれない。
<html> <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 jeval(s, env, k) { if (k == null) k = function(u){return u;} if (env == null) env = {}; 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 jeval(s[n], env, function(u){ if (n >= s.length-1) return k(u) return begin(n+1,env) }) } function apply(lambda, newenv, s, i) { if (i == lambda[1].length) return jeval(lambda[2],newenv,k) else return jeval(s[i+1], env, function(v){ newenv[lambda[1][i]]=v; return apply(lambda,newenv,s,i+1)}) } if (s instanceof Array) { switch (s[0]) { case "add": return jeval(s[1],env,function(u){return jeval(s[2],env,function(v){return k(u+v)})}) case "mul": return jeval(s[1],env,function(u){return jeval(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,function(v){return k(cont[4])},null]; return jeval([s[1], ["list",cont]], env, k) case "#cont": return jeval(s[1],s[2],s[3]) case "define": return jeval(s[2],env,function(u){return k(env[s[1]] = u)}) case "set!": return jeval(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 jeval(s[1], env, function(v){alert(v); return k(v)}) case "display": return jeval(s[1], env, function(v){log(v); return k(v)}) } return jeval(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") { data[4]=s[1];return jeval(data,env,k)} return k(data) }) } if (typeof(s) == "string") return k(getEnv(env, s)) return k(s) } var env = {}; function log(s){ document.getElementById("output").value = (s+"\n")+document.getElementById("output").value; return s } function run() { try{ log(jeval(eval(document.getElementById("input").value),env)) }catch(e){log(e)} } </script> <body> <h3>継続つきJSON Lisp</h3> <form> <textarea id="input" cols=80 rows=5> ["begin", ["define","s",0], ["add",100,["callCC",["lambda",["cc"],["begin",["set!","s","cc"],3]]]] ] </textarea><input type="button" value="実行" onclick="run()"><br> <textarea id="output" cols=80 rows=25></textarea> </form> </body> </html>