書きかけ


書いてたらだんだん眠くなってやめた。
環境とか、lambdaとクロージャとそのへん、こんがらがり中。
適当になってるのがよくないかんじ。
MiniDってののソースが気になる今日この頃ですけど、時間ね。
単なるゴミなかんじ。

<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}];
		}
		var data = null;
		if(s[0] instanceof Array && s[0][0] == "lambda") data = eval(s[0],env);
		else if(s[0] instanceof Array && s[0][0] == "#closure") data = s[0];
		else data = getEnv(env, s[0]);
		if (data == null) throw "error";
		if (data instanceof Array) {
			if (data[0] == "#closure") {
				var lambda = data[1];
				var argv = lambda[1];
				var newenv = {parent:data[2]};
				for (var i = 0; i < argv.length; i++) newenv[argv[i]] = eval(s[i+1], env);
				return eval(lambda[2],newenv);
			}
			throw "error";
		}
	}
	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>