wl

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

commit f829c1790b61532efbbdc62fc74ebf91b642f3b1
parent d68eb42502f07b3002cdad0f4f40adb9ec797687
Author: tomas <tomas@logand.com>
Date:   Tue,  6 Oct 2009 21:06:31 +0200

java port started

Diffstat:
Awl.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); +// // }