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);
+// // }