0.0.3
JSONを使った関数型言語JSOPをバージョンアップしてみました。
無名関数が使えるようにしてみました。
alert(eval({body: [{args:["a","b"], body:["+","a","b"]}, 1, 2]}));
のように書くと計算結果の3がアラートボックス内に表示されます。
C式を使った場合は、下のように書けたらいいなぁ思ってるんだけど、
誰でも納得出来るものは作ることができないものなのか、それとも、
考えが、まだまだ、甘いのか、とにかく出来てないです。
alert(eval( (a,b){+(a,b)} (1,2) ));
とか
alert(eval( function ((a,b),+(a,b)) (1,2) ));
な感じで書けたらいいんだけどなぁ。適当になら、作れそうなのだけど。
ソースは以下の通り。
<html> <script language="javascript"> Array.prototype.toString = function() { return "[" + this.join(",") + "]"; } Object.prototype.toString = function() { var str = ""; var p = ""; for(var i in this) { str += p + i + ":" + this[i]; p = ","; } return "{" + str + "}"; } function eval(p, env) { if (!isNaN(p))return p; if (p instanceof Array) {// 関数適用 switch (p[0]) { case "+": return eval(p[1], env) + eval(p[2], env); case "-": return eval(p[1], env) - eval(p[2], env); case "*": return eval(p[1], env) * eval(p[2], env); case "/": return eval(p[1], env) / eval(p[2], env); case "=": return eval(p[1], env) == eval(p[2], env); case "if": return eval(p[1], env) ? eval(p[2], env) : eval(p[3], env); case "cond": for (var i = 1; i < p.length; i++) if (eval(p[i][0], env)) return eval(p[i][1], env); default: if (p[0] instanceof Object) { // 無名関数 var e = {body: p[0]["body"], parent: env}; for(var i = 0; i < p[0]["args"].length; i++) e[ p[0]["args"][i] ] = eval(p[i + 1], env); return eval(e, env); } else { var envs = getEnv(p[0], env); var e = {body: envs[0]["body"], parent: envs[1]}; for(var i = 0; i < envs[0]["args"].length; i++) e[ envs[0]["args"][i] ] = eval(p[i + 1], env); alert(envs[1]); return eval(e, envs[1]); } } } if (p instanceof Object) { p["parent"] = env; return eval(p["body"], p); } var envs = getEnv(p, env); return eval(envs[0], envs[1]); } function getEnv(p, env) { while (env != null) { if (env[p] != null) return [env[p], env]; env = env["parent"]; } } var program = { // add: {args:["a","b"], body:["+","a","b"]}, // body: ["add", 1, 2] body: [{args:["a","b"], body:["+","a","b"]}, 1, 2] }; alert(eval(program, null)); </script> </html>