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>