■
とりあえず、只のインタプリタ。
こんなんでいいか。
<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 eval(s,env){ function getEnv(env, a) { if (env[a] != null) return env[a]; if (env.parent == null) throw "error not found val "+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"; return setEnv(env.parent, a, v); } if (env == null) env = {}; if (s instanceof Array) { switch(s[0]){ case "add": return eval(s[1],env) + eval(s[2],env); case "mul": return eval(s[1],env) * eval(s[2],env); case "define": return env[s[1]] = eval(s[2],env); case "set": return setEnv(env, s[1], eval(s[2],env)); case "begin": env = {parent:env}; case "#begin2": var a = s.reverse();a.pop(); var rc = eval(a.pop(),env); if (a.length == 0) return rc; a.push("#begin2"); return eval(a.reverse(),env); case "lambda": return ["#closure",s,{parent:env}]; case "#closure": return s; } var data = eval(s[0], env); if (data instanceof Array && data[0] == "#closure") { var newenv = {parent:data[2]}; for (var i = 0; i < data[1][1].length; i++) newenv[data[1][1][i]] = eval(s[i+1], env); return eval(data[1][2], newenv); } return data; } if (typeof(s) == "string") return getEnv(env, s); return s; } var env = {}; try{ //alert(eval(["define","a",["add",["mul",2,3],2]],env)); //alert(eval("a",env)); //alert(eval(["begin",["define","a",["add",1,2]],["define","b",["add",1,2]],["add","a","b"]])); alert(eval(["begin",["define","data",1],["define","c",["lambda",["a","b"],["add",["add","a","b"],"data"]]],["begin",["define","data",2],["c",2,"data"]]])); alert(eval([["lambda",["a","b"],["add","a","b"]],1,2])); }catch(e){alert(e)} </script>