JScriptでGrass処理系書け・・・てなかった (2)

詳細にトレースしたりして必死にデバッグしてたら,Absの部分適用でLの引数に配列じゃない物を記述していることに気づいてしまった.こ,これは恥ずかしすぎる……

wwWWwWWWwvwWWwwWwwwWwwwwwWwwwwwwww
T = λfx.f(fx)
λx.(T T T) Out w
==> wwwwwwwwwwwwwwww

以前のはそれでバグってて上のコードがまともに動かなかったんだけど,

VM.E = VM.E.s([((abs.n > 1) ? L([new Abs(abs.n-1, abs.c)]) : abs.c), VM.E]);

としてやることで,意図したとおりに動くようになった.
しかし,公式のはいはいわろすわろすスクリプトがまともに動かないのは,どうしたものか……

function grass(code, inputHandler, outputHandler){
	// List
	function N(v, n) { this.n = n; this.v = v; }
	N.prototype.i = function(s) { var p = this; for(i = 1; i < s; ++i) p = p.n; return p; }
	N.prototype.s = function(v) { return new N(v, this); }
	var Eps = new N(null, null);
	function L(A) { var n = Eps; for(var i = A.length - 1; i >= 0; --i) n = new N(A[i], n); return n; }
	// Grass op-codes
	function App(m,n){ this.m = m; this.n = n; }
	function Abs(n,C){ this.n = n; this.c = C; }
	// Boolean functions
	var Id = new Abs(1, Eps);
	var True = new Abs(2, L([Id, new App(1, 3)]));
	var False = new Abs(2, L([Eps]));
	// Primitive functions
	function gW(c) { function w(s){ return s == w.w ? True : False; }; w.w = c; return w; }
	function Out(s) { if(!('w' in s)) throw new Error("文字じゃないくさいな(キリッ"); outputHandler(s.w); return s; }
	function In(s) { var c = inputHandler(); return c < 0 || c > 255 ? s : gW(c); }
	function Succ(s) { if(!('w' in s)) throw new Error("文字じゃないくさいな(キリッ"); s.w = (s.w+1)&255; return s; }

	// compile
	var tokens = code.replace(/[^WwvWwv]/g,'').match(/[ww]+|[WW]+[ww]+|[vv]/g) || [];
	var stateAbs = 0,stateApp = 1,state = stateAbs, C = [];
	while (tokens.length) {
		var tok = tokens.shift();
		if (tok.match(/^[ww]+/)) {
			if (state != stateAbs) throw new Error("文法エラーくさいな(キリッ");
			var nd = RegExp.lastMatch.length, Cd = [];
			for (;;) {
				if (!tokens.length || !tokens[0].match(/([WW]+)([ww]+)/)) break;
				tokens.shift();
				var m = RegExp.$1.length;
				var n = RegExp.$2.length;
				Cd.push(new App(m,n));
			}
			if (tokens.length && !tokens.shift().match(/^[vv]/)) throw new Error("文法エラーくさいな(キリッ");
			C.push(new Abs(nd,L(Cd)));
		} if (tok.match(/^([WW]+)([ww]+)/)) {
			if (state == stateAbs) state = stateApp;
			var m = RegExp.$1.length;
			var n = RegExp.$2.length;
			C.push(new App(m,n));
		}
	}
	var VM = { C: L(C), E: L([Out, Succ, gW(119), In]), D: L([[L([new App(1,1)]), Eps],[Eps, Eps]])};
	// step
	return function GrassStep() {
		if(VM.C != Eps || VM.D != Eps) {
				var f = VM.E.v;
				var d = VM.D.v;
				VM.C = d[0];
				VM.E = d[1].s(f);
				VM.D = VM.D.n;
			} else if (VM.C.v instanceof App) {
				var app = VM.C.v;
				var em = VM.E.i(app.m).v;
				var en = VM.E.i(app.n).v;
				if (!(em instanceof Array)) {
					// primitive function
					VM.E = VM.E.s(em(en));
					VM.C = VM.C.n;
				} else {
					// Grass function
					VM.D = VM.D.s([VM.C.n, VM.E]);
					VM.C = em[0];
					VM.E = em[1].s(en);
					en = VM.E.i(2).v;
				}
			} else if (VM.C.v instanceof Abs) {
				var abs = VM.C.v;
				VM.E = VM.E.s([((abs.n > 1) ? L([new Abs(abs.n-1, abs.c)]) : abs.c), VM.E]);
				VM.C = VM.C.n;
			}
			
			return GrassStep;
		} else {
			return null;
		}
	};

}

var input = "";
while (!WScript.StdIn.AtEndOfStream)
{
   input += WScript.StdIn.ReadAll();
}

var step = grass(input, function() { return -1; }, function(c) { WScript.StdOut.Write(String.fromCharCode(c)); });
while(step = step()) this.CollectGarbage();