commit f829c1790b61532efbbdc62fc74ebf91b642f3b1
parent d68eb42502f07b3002cdad0f4f40adb9ec797687
Author: tomas <tomas@logand.com>
Date: Tue, 6 Oct 2009 21:06:31 +0200
java port started
Diffstat:
A | wl.java | | | 568 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 568 insertions(+), 0 deletions(-)
diff --git a/wl.java b/wl.java
@@ -0,0 +1,568 @@
+// wl.java -- (c) 2009 Tomas Hlavaty
+
+import java.util.Stack;
+import java.util.HashMap;
+
+class wl {
+
+ 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;}
+ }
+ static Any cons(Any a, Any d) {return new Any(null, a, d);}
+
+ final static Any NIL = new Any("NIL", null, null);
+ final static Any T = new Any("T", NIL, null);
+
+ static {
+ NIL.car = NIL;
+ NIL.cdr = NIL;
+ 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();
+
+ String L;
+ int N, I, D;
+
+ void init(String L) {this.L = L; this.N = L.length(); this.I = 0; this.D = 0;}
+
+ boolean charIn(Character C, String L) {return 0 <= L.indexOf(C);}
+ Character peek() {return this.I < this.N ? this.L.charAt(this.I) : null;}
+ Character xchar() {return this.I < this.N ? this.L.charAt(this.I++) : null;}
+ void skip() {
+ while(this.I < this.N && charIn(this.L.charAt(this.I), " \t\n\r"))
+ this.I++;
+ }
+ void comment() {
+ while('#' == peek()) {
+ Character X;
+ while(((X = peek()) != null) && ('\n' != X))
+ xchar();
+ skip();
+ }
+ }
+ String text() {
+ StringBuffer L = new StringBuffer();
+ while('"' != peek()) {
+ Character C = xchar();
+ if('\\' == C) C = xchar();
+ else if('^' == C) {
+ C = xchar();
+ if('I' == C) C = '\t';
+ else if('J' == C) C = '\n';
+ else if('M' == C) C = '\r';
+ else C = (char) ('?' == C ? 127 : C & 0x1f);
+ }
+ L.append(C);
+ }
+ if('"' != xchar()) throw new RuntimeException("Unbalanced double quote");
+ if(0 < L.length()) return L.toString(); //.replace(/\r\n/g, "\n");
+ return "";
+ }
+ Object symbol() {
+ Character C = xchar();
+ if(charIn(C, "()# \t\n"))
+ throw new RuntimeException("Symbol expected, got " + C);
+ boolean N = charIn(C, "+-0123456789.");
+ boolean F = ('.' == C);
+ StringBuffer L = new StringBuffer();
+ L.append(C);
+ Character X;
+ while(((X = peek()) != null) && !charIn(X, "()# \t\n")) {
+ C = xchar();
+ L.append(C);
+ if(N && !charIn(C, "0123456789")) {
+ if(!F && ('.' == C)) F = true;
+ else N = false;
+ }
+ }
+ 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);
+ }
+ Object token() {
+ skip();
+ Character X = peek();
+ if(null == X) return null;
+ else
+ switch(X) {
+ case '#': comment(); return null;
+ case '"': xchar(); return text();
+ case '\'': xchar(); return Qte;
+ case '(': xchar(); this.D++; return Lp;
+ case ')': xchar(); this.D--; return Rp;
+ default: return symbol();
+ }
+ }
+
+ // parser
+ Object parseBuild(Stack Os) {
+ Object Z = null;
+ Object Dot = null;
+ while(0 < Os.size()) {
+ Object 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;
+ Dot = X;
+ } else throw new RuntimeException("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);
+ }
+ throw new RuntimeException("Missing mark");
+ }
+ Object parse(String L) {
+ init(L);
+ Stack Os = new Stack();
+ 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();
+ 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);
+ return Z;
+ }
+
+ // printer
+ String str(Object L) {
+ StringBuilder A = new StringBuilder();
+ if(L instanceof Sym) A.append(L.nm);
+ else if(L instanceof Cons) {
+ if(this.Sd.get("quote") == L.car) {
+ A.append('\'');
+ A.append(str(L.cdr));
+ } else {
+ A.append('(');
+ while(L instanceof Cons) {
+ A.append(str(L.car));
+ L = L.cdr;
+ if(NIL !== L) A.append(' ');
+ }
+ 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, "\\\\");
+ A.append('"');
+ A.append(S);
+ A.append('"');
+ } else A.append(L);
+ return A.toString();
+ }
+
+
+ // evaluator
+ HashMap Sd = new HashMap();
+
+ Sym intern(String Nm) {
+ if(!this.Sd.containsKey(Nm)) this.Sd.put(Nm, new Sym(Nm, NIL, NIL));
+ return (Sym) 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));
+ }
+
+
+
+ public static void main(String args[]) {
+ wl X = new wl();
+ //wl.init("(+ 1 2 3)");
+ }
+}
+
+// // 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;
+// var F = ev(E.car);
+// if(NIL === F.car) run(F.cdr);
+// else if(isSym(F.car)) {
+// if("@" == F.car.nm) {
+// // TODO
+// } else {
+// // TODO
+// }
+// } else if(isCons(F.car)) {
+// // TODO
+// } 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;
+// var X = ev(E.cdr.car);
+// if(typeof X == "number") throw "Variable expected";
+// else if(isSym(X)) Z = X.cdr;
+// else if(isCons(X)) Z = X.car;
+// else Z = X; // string
+// return Z;
+// });
+// def(".cons", function(E) {return cons(ev(E.cdr.car), ev(E.cdr.cdr.car));});
+
+// // 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);
+// // }