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();