wl

Unnamed repository; edit this file 'description' to name the repository.
git clone https://logand.com/git/wl.git/
Log | Files | Refs | LICENSE

commit 69640b8ad79b8112d5ace2409934d3e8eba71c43
parent f829c1790b61532efbbdc62fc74ebf91b642f3b1
Author: tomas <tomas@logand.com>
Date:   Tue,  6 Oct 2009 21:07:33 +0200

generic Any used

Diffstat:
Mwl.java | 575++++++++++++++++++++++++++-----------------------------------------------------
1 file changed, 189 insertions(+), 386 deletions(-)

diff --git a/wl.java b/wl.java @@ -5,17 +5,36 @@ import java.util.HashMap; class wl { + void err(Object X, String M) { + if(X instanceof Any) throw new RuntimeException(M + ": " + str((Any) X)); + throw new RuntimeException(M + ": " + X); + } + void err(String M) {throw new RuntimeException(M);} + + static interface Fn { + public Any fn(Any E); + } + static class Any { public String nm; - public Object car, cdr; - public Any(String n, Object a, Object d) {nm = n; car = a; cdr = d;} - public isSym() {return null != nm;} - public isCons() {return null == nm;} + public Any car, cdr; + public Object cxr; + public Any(String n, Any a, Any d, Object x) { + nm = n; car = a; cdr = d; cxr = x; + } + public boolean isSym() {return null != nm;} + public boolean isCons() {return null == nm && null != car && null != cdr;} + public boolean isStr() {return null == nm && cxr instanceof String;} + public boolean isInt() {return null == nm && cxr instanceof Integer;} + public boolean isFn() {return cxr instanceof Fn;} } - static Any cons(Any a, Any d) {return new Any(null, a, d);} + static Any cons(Any a, Any d) {return new Any(null, a, d, null);} + static Any mkInt(String x) {return new Any(null, null, null, Integer.parseInt(x));} + static Any mkFix(String x) {return new Any(null, null, null, Float.parseFloat(x));} + static Any mkStr(String x) {return new Any(null, null, null, x);} - final static Any NIL = new Any("NIL", null, null); - final static Any T = new Any("T", NIL, null); + final static Any NIL = new Any("NIL", null, null, null); + final static Any T = new Any("T", NIL, null, null); static { NIL.car = NIL; @@ -23,31 +42,10 @@ class wl { T.cdr = T; } - // static class Cons { - // public Object car, cdr; - // public Cons(Object a, Object d) {car = a; cdr = d;} - // } - // static Cons cons(Object a, Object d) {return new Cons(a, d);} - - // static class Sym { - // public String nm; - // public Object car, cdr; - // public Sym(String n, Object a, Object d) {nm = n; car = a; cdr = d;} - // } - - // final static Sym NIL = new Sym("NIL", null, null); - // final static Sym T = new Sym("T", NIL, null); - - // static { - // NIL.car = NIL; - // NIL.cdr = NIL; - // T.cdr = T; - // } - // reader - final static Object Qte = new Object(); - final static Object Lp = new Object(); - final static Object Rp = new Object(); + final static Any Qte = new Any(null, null, null, null); + final static Any Lp = new Any(null, null, null, null); + final static Any Rp = new Any(null, null, null, null); String L; int N, I, D; @@ -69,7 +67,7 @@ class wl { skip(); } } - String text() { + Any text() { StringBuffer L = new StringBuffer(); while('"' != peek()) { Character C = xchar(); @@ -83,14 +81,13 @@ class wl { } L.append(C); } - if('"' != xchar()) throw new RuntimeException("Unbalanced double quote"); - if(0 < L.length()) return L.toString(); //.replace(/\r\n/g, "\n"); - return ""; + if('"' != xchar()) err("Unbalanced double quote"); + if(0 < L.length()) return mkStr(L.toString()); //.replace(/\r\n/g, "\n"); + return mkStr(""); } - Object symbol() { + Any symbol() { Character C = xchar(); - if(charIn(C, "()# \t\n")) - throw new RuntimeException("Symbol expected, got " + C); + if(charIn(C, "()# \t\n")) err(C, "Symbol expected"); boolean N = charIn(C, "+-0123456789."); boolean F = ('.' == C); StringBuffer L = new StringBuffer(); @@ -106,9 +103,9 @@ class wl { } String M = L.toString(); if((1 == M.length()) && charIn(M.charAt(0), "+-.")) N = false; - return N ? (F ? Float.parseFloat(M) : Integer.parseInt(M, 10)) : intern(M); + return N ? (F ? mkFix(M) : mkInt(M)) : intern(M); } - Object token() { + Any token() { skip(); Character X = peek(); if(null == X) return null; @@ -124,127 +121,212 @@ class wl { } // parser - Object parseBuild(Stack Os) { - Object Z = null; - Object Dot = null; + Any parseBuild(Stack<Any> Os) { + Any Z = NIL; + Any Dot = null; while(0 < Os.size()) { - Object X = Os.pop(); + Any X = Os.pop(); if(Lp == X) return Dot != null ? cons(Dot, cons(Z, NIL)) : Z; Dot = null; - if((X instanceof Sym) && (".".equals(((Sym) X).nm))) { - if((Z instanceof Cons) && (null == ((Cons) Z).cdr)) { - Z = ((Cons) Z).car; + if(X.isSym() && (".".equals(X.nm))) { + if(Z.isCons() && NIL == Z.cdr) { + Z = Z.car; Dot = X; - } else throw new RuntimeException("Bad dotted pair"); + } else err("Bad dotted pair"); } else if(X == Qte) - Z = cons(cons(this.Sd.get("quote"), ((Cons) Z).car), ((Cons) Z).cdr); - else Z = cons(X, Z == null ? NIL : Z); + Z = cons(cons(this.Sd.get("quote"), Z.car), Z.cdr); + else Z = cons(X, Z); } - throw new RuntimeException("Missing mark"); + err("Missing mark"); + return NIL; // make compiler happy:-{ } - Object parse(String L) { + public Any parse(String L) { init(L); - Stack Os = new Stack(); + Stack<Any> Os = new Stack<Any>(); Os.push(Lp); // TODO circular list . // TODO interpret while reading ~ for each top-level sexp // TODO no wasteful consing while(null != peek()) { - Object X = token(); + Any X = token(); if(null != X) { if(Rp == X) Os.push(parseBuild(Os)); else Os.push(X); } } - Object Z = parseBuild(Os); - if(0 < Os.size()) - throw new RuntimeException("Incomplete input, left with " + Os); + Any Z = parseBuild(Os); + if(0 < Os.size()) err(Os, "Incomplete input"); return Z; } // printer - String str(Object L) { + public String str(Any L) { StringBuilder A = new StringBuilder(); - if(L instanceof Sym) A.append(L.nm); - else if(L instanceof Cons) { + if(L.isSym()) A.append(L.nm); + else if(L.isInt()) A.append(L.cxr.toString()); + else if(L.isCons()) { if(this.Sd.get("quote") == L.car) { A.append('\''); A.append(str(L.cdr)); } else { A.append('('); - while(L instanceof Cons) { + while(L.isCons()) { A.append(str(L.car)); L = L.cdr; - if(NIL !== L) A.append(' '); + if(NIL != L) A.append(' '); } - if(NIL !== L) { + if(NIL != L) { A.append(". "); A.append(str(L)); } A.append(')'); } - } else if(L instanceof String) { - var Y = L.split(""); - for(var I = 0; I < Y.length; I++) { - if(Y[I] == "\\") Y[I] = "\\\\"; - else if(Y[I] == '"') Y[I] = '\\"'; - } - var S = Y.join(""); - //var S = L.replace(/\"/g, "\\\"").replace(/\\/g, "\\\\"); + } else if(L.isStr()) { A.append('"'); - A.append(S); + String S = (String) L.cxr; + for(int I = 0; I < S.length(); I++) { + Character C = S.charAt(I); + if('\\' == C) A.append("\\\\"); + else if('"' == C) A.append("\\\""); + else A.append(C); + } A.append('"'); - } else A.append(L); + } else err(L, "Don't know how to print"); return A.toString(); } // evaluator - HashMap Sd = new HashMap(); + HashMap<String, Any> Sd = new HashMap<String, Any>(); - Sym intern(String Nm) { - if(!this.Sd.containsKey(Nm)) this.Sd.put(Nm, new Sym(Nm, NIL, NIL)); - return (Sym) this.Sd.get(Nm); + Any intern(String Nm) { + if(!this.Sd.containsKey(Nm)) this.Sd.put(Nm, new Any(Nm, NIL, NIL, null)); + return this.Sd.get(Nm); } - void def(String Nm, Object Val) { - if(this.Sd.containsKey(Nm)) ((Sym) this.Sd.get(Nm)).cdr = Val; - else this.Sd.put(Nm, new Sym(Nm, Val, NIL)); + // void def(String Nm, Fn F) { + // if(this.Sd.containsKey(Nm)) this.Sd.get(Nm).cxr = F; + // else this.Sd.put(Nm, new Sym(Nm, null, null, F)); + // } + + Any run(Any E) { + System.out.println("run: " + str(E)); + Any Z = NIL; + while(NIL != E) { + Z = eval(E.car); + E = E.cdr; + } + return Z; + } + Any eval(Any E) { + System.out.println("eval: " + str(E)); + Any Z = NIL; + if(E.isInt()) Z = E; + else if(E.isSym()) Z = E.cdr; + else if(E.isCons()) { + Any X = E.car; + if(X.isInt()) Z = E; + else if(X.isSym()) { + if(X.isFn()) Z = ((Fn) X.cxr).fn(E); + else err(E, "TODO ap"); //Z = ap(E); + } else err(E, "Unexpected function type"); + } else Z = E; // string + //alert("ev: " + str(E) + " => " + Z); + return Z; + } + + void fn(String Nm, Fn F) {this.Sd.put(Nm, new Any(Nm, null, null, F));} + + public wl() { + Sd.put("NIL", NIL); + Sd.put("T", T); + + fn("run", new Fn() {public Any fn(Any E) {return run(E);}}); + fn("eval", new Fn() {public Any fn(Any E) {return eval(E);}}); + fn("quote", new Fn() {public Any fn(Any E) {return E.cdr;}}); + fn("car", new Fn() {public Any fn(Any E) {return eval(E.cdr.car).car;}}); + fn("cdr", new Fn() {public Any fn(Any E) {return eval(E.cdr.car).cdr;}}); + fn("-", new Fn() {public Any fn(Any E) { + Any X = E.cdr; + Any Z = eval(X.car); + if(NIL == Z) return NIL; + if(NIL == X.cdr) Z.cxr = -((Integer) Z.cxr); + else + while(NIL != X.cdr) { + X = X.cdr; + Any Y = eval(X.car); + if(NIL == Y) return NIL; + Z.cxr = (Integer) Z.cxr - (Integer) Y.cxr; + } + return Z; + }}); + fn("*", new Fn() {public Any fn(Any E) { + Any X = E.cdr; + Any Z = eval(X.car); + if(NIL == Z) return NIL; + while(NIL != X.cdr) { + X = X.cdr; + Any Y = eval(X.car); + if(NIL == Y) return NIL; + Z.cxr = (Integer) Z.cxr * (Integer) Y.cxr; + } + return Z; + }}); + fn("/", new Fn() {public Any fn(Any E) { + Any X = E.cdr; + Any Z = eval(X.car); + if(NIL == Z) return NIL; + while(NIL != X.cdr) { + X = X.cdr; + Any Y = eval(X.car); + if(NIL == Y) return NIL; + Z.cxr = (Integer) Z.cxr / (Integer) Y.cxr; + } + return Z; + }}); + fn("loop", new Fn() {public Any fn(Any E) { + // TODO @ + while(true) { + for(Any X = E.cdr; NIL != X.cdr; X = X.cdr) { + Any Y = X.car; + if(Y.isCons() && NIL == Y) { + Y = Y.cdr; + if(NIL == eval(Y.car)) return run(Y.cdr); + } else if(Y.isCons() && T == Y) { + Y = Y.cdr; + if(NIL != eval(Y.car)) return run(Y.cdr); + } else eval(Y); + } + } + }}); + fn("==", new Fn() {public Any fn(Any E) { + Any X = E.cdr; + return eval(X.car) == eval(X.cdr.car) ? T : NIL; + }}); + + fn("in", new Fn() {public Any fn(Any E) { + Any X = E.cdr; + Any N = eval(E.car); + String F; + if(N.isStr()) F = (String) N.cxr; + else if(N.isSym()) F = N.nm; + else err(E, "File name expected"); + //FileInputStream S = new FileInputStream(N); + //InputStreamReader R = new InputStreamReader(S, "UTF-8"); + return NIL; + }}); + //FileOutputStream fos = new FileOutputStream("test.txt"); + //OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8"); } public static void main(String args[]) { wl X = new wl(); - //wl.init("(+ 1 2 3)"); + System.out.println(X.str(X.parse("(- 1 2 3)"))); + System.out.println(X.str(X.run(X.parse("(- 1 2 3)(- 3 5)(/ ")))); } } -// // TODO fix E ~ whole sexp fn - -// function run(E) { -// var Z; -// while(NIL !== E) { -// Z = ev(E.car); -// E = E.cdr; -// } -// return Z; -// } -// function ev(E) { // eval -// var Z; -// if(typeof E == "number") Z = E; -// else if(isSym(E)) Z = E.cdr; -// else if(isCons(E)) { -// var X = E.car; -// if(typeof X == "number") Z = E; -// else if(isSym(X)) { -// if(typeof X.cdr == "function") Z = X.cdr(E); -// else throw "TODO ap"; //Z = ap(E); -// } else throw "Unexpected function type"; -// } else Z = E; // string -// //alert("ev: " + str(E) + " => " + Z); -// return Z; -// } - // // TODO ap // function ap(E) { // apply // var Z; @@ -261,10 +343,7 @@ class wl { // } else throw "Function expected"; // } -// //def("run", run); -// //def("eval", ev); // //def("apply", ap); -// def("quote", function(E) {return E.cdr;}); // def("val", function(E) { // var Z; @@ -280,289 +359,13 @@ class wl { // // TODO def !!!!!!!!!!!!! // // OK -// def("car", function(E) {return ev(E.cdr.car).car;}); -// def("cdr", function(E) {return ev(E.cdr.car).cdr;}); -// def("-", function(E) { -// var X = E.cdr; -// var Z = ev(X.car); -// if(NIL === Z) return NIL; -// if(NIL === X.cdr) Z = -Z; -// else -// while(NIL !== X.cdr) { -// X = X.cdr; -// var Y = ev(X.car); -// if(NIL === Y) return NIL; -// Z -= Y; -// } -// return Z; -// }); -// def("*", function(E) { -// var X = E.cdr; -// var Z = ev(X.car); -// if(NIL === Z) return NIL; -// while(NIL !== X.cdr) { -// X = X.cdr; -// var Y = ev(X.car); -// if(NIL === Y) return NIL; -// Z *= Y; -// } -// return Z; -// }); -// def("/", function(E) { -// var X = E.cdr; -// var Z = ev(X.car); -// if(NIL === Z) return NIL; -// while(NIL !== X.cdr) { -// X = X.cdr; -// var Y = ev(X.car); -// if(NIL === Y) return NIL; -// Z /= Y; -// } -// return Z; -// }); // // Sd["%"] = function(E) {var X = Os.pop(); Os.push(Os.pop() % X);}; // // Sd["eq"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X == Y);}; // // Sd["lt"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X < Y);}; -// wl.prototype.parse = parse; -// wl.prototype.str = str; -// wl.prototype.run = run; -// return this; -// } - - - - - - - - -// // Sd["if"] = function() { -// // var N = Os.pop(); -// // var P = Os.pop(); -// // var C = Os.pop(); -// // Es.push([false, C === true ? P : N]); -// // }; - -// // // Sd[".call"] = function() { -// // // var N = Os.pop(); -// // // var K = Os.pop(); -// // // var D = Os.pop(); -// // // var X = []; -// // // for(var I = 0; I < N; I++) X.unshift(Os.pop()); -// // // Os.push(D[K].apply(D, X)); -// // // }; -// // Sd[".date"] = function(E) {return new Date();}; // TODO split new and Date -// // // Sd[".callback"] = function() { // TODO event arg? -// // // var X = Os.pop(); -// // // Os.push(function() { -// // // Ps.run(X, true); -// // // while(0 < Es.length) -// // // Ps.step(); -// // // }); -// // // }; - - -// // Sd["list2array"] = function list2array(E) { -// // var Z = []; -// // while(!isNil(E)) { -// // Z.push(E.car); -// // E = E.cdr; -// // } -// // return Z; -// // }; -// // // Sd["array2list"] = function array2list(A) { -// // // var Z = NIL; -// // // for(var I = A.length - 1; 0 <= I; I--) -// // // Z = cons(A[I], Z); -// // // return Z; -// // // }; -// // // Sd["object2list"] = function object2list(O) { -// // // var Z = NIL; -// // // for(var I in O) -// // // Z = cons(cons(I, O[I]), Z); -// // // return Z; -// // // }; - -// // function parse() { -// // var Z; -// // var A = arguments; -// // if(A.length) -// // for(var I = 0; I < A.length; I++) -// // Z = Rd.parse(A[I]); -// // else Z = Rd.parse(A); -// // return Z; -// // } -// // wl.prototype.parse = parse; -// // return this; -// // } - -// // /// lisp - -// // // function format(N, S) { -// // // var X = "" + N; -// // // var L = X.length; -// // // return X.slice(0, L - S) + "." + X.slice(L - S, L); -// // // } - -// // // function real(N, S) { -// // // return N / Math.pow(10, S); -// // // } - -// // var Syms = {}; - -// // function mkSym(Nm, Val, Prop) { -// // var X = new Sym(Nm, Val, Prop); -// // Syms[Nm] = X; -// // return X; -// // } - -// // function xget(Sym) { -// // return isSym(Sym) ? Sym._val : Sym; -// // } - -// // function xset(Sym, Val) { -// // if(!isSym(Sym)) throw "Sym expected"; -// // Sym._val = Val; -// // return Sym._val; -// // } - -// // //var NIL = mkSym("NIL"); -// // var T = mkSym("T"); - -// // //xset(NIL, NIL); -// // xset(T, T); -// // // TODO set props for NIL and T - -// // function intern(Sym) { -// // //if(!(Sym in Syms)) Syms[Sym] = mkSym(Sym, NIL, NIL); -// // return Syms[Sym] || (Syms[Sym] = mkSym(Sym, NIL, NIL)); -// // } - - -// // function isT(X) { -// // return X === T; -// // } - - - - - - - - // // function eq(X, Y) { // // if(X === Y) return T; // // //if(X == Y) return T; // // return NIL; // // } - -// // function xdelete(A, L) { -// // var X = NIL; -// // while(!isNil(L)) { -// // if(isNil(eq(A, L.car))) X = cons(L.car, X); -// // L = L.cdr; -// // } -// // return reverse(X); -// // } - -// // function lsApply(Fn, Args) { -// // } - -// // function jsFn(Fn) { -// // var F = function() { -// // return lsApply(Fn, list2array(arguments)); -// // }; -// // return F; -// // } - -// // function jsApply() { -// // var Fn = arguments.shift(); -// // var Args = arguments.shift(); -// // var Rest = arguments; -// // return Fn.apply(list2array(Args).unshift.apply(list2array(Rest))); -// // } - -// // var Xeval = {}; - -// // function xdef(Nm, Fn) { -// // if(!(Nm in Syms)) intern(Nm); -// // Xeval[Nm] = Fn; -// // } - -// // xdef("quote", function(E) { -// // return cdr(E); // or cdr? -// // }); -// // xdef("if", function(E) { -// // if(!isNil(xeval(cadr(E)))) return xeval(caddr(E)); -// // else return xeval(cadddr(E)); -// // }); -// // xdef("prog", function(E) { -// // var L = cdr(E); -// // var X = NIL; -// // while(!isNil(L)) { -// // X = xeval(L.car); -// // L = L.cdr; -// // } -// // return X; -// // }); - -// // function xeval(E) { -// // if(isSym(E)) return xget(E); -// // else if(!isCons(E)) return E; -// // else if(car(E)._nm in Xeval) return Xeval[car(E)._nm](E); -// // else return xapply(xeval(car(E)), map(xeval, cdr(E))); -// // } - -// // function initLisp() { -// // //xalert(xeval(NIL), xeval(T), xeval(12), xeval(12.3), xeval({x: "hi"}), xeval([1, 2])); -// // //xalert(xeval(cons(intern("quote"), cons("whoa", NIL)))); -// // //xalert(xeval(cons(intern("quote"), cons("whoa", cons("b", NIL))))); -// // //xalert(intern("if")); -// // //xalert(object2list(Syms)); -// // //xalert(object2list(Xeval)); -// // //xalert(xeval(cons(intern("if"), cons(T, cons("yes", cons("no", NIL)))))); -// // //xalert(xeval(cons(intern("if"), cons(NIL, cons("yes", cons("no", NIL)))))); -// // //xalert(xeval(cons(intern("quote"), intern("whoa")))); -// // } - -// // // parser - -// // function isArray(A) { -// // return A && A.constructor == Array; -// // } - -// // function flatten(A) { -// // var X = []; -// // function rec(B) { -// // var N = B.length; -// // var I; -// // for(I = 0; I < N; I++) { -// // if(isArray(B[I])) rec(B[I]); -// // else X.push(B[I]); -// // } -// // } -// // rec(A); -// // return X; -// // } - -// // function lisp2string(Any) { -// // return flatten(unparse(Any)).join(""); -// // } - -// // function xalert() { -// // var X = []; -// // var N = arguments.length; -// // var I; -// // for(I = 0; I < N; I++) { -// // X.push(flatten(unparse(arguments[I])).join("")); -// // } -// // alert(X.join(" ")); -// // } - -// // function xmsg(A) { -// // var B = parse(A); -// // var X = flatten(unparse(B)).join(""); -// // mk(w("test"), "pre", {}, {}, "'" + A + "' => " + X); -// // }