commit 7335d5822c39a73f69e4e8bc48a8b1437f630149
parent 7d4915d7392b8e071c4ccbffd179d0b48804a280
Author: tomas <tomas@logand.com>
Date:   Tue,  6 Oct 2009 21:11:06 +0200
better parser, eval (cons too) and java ffi
Diffstat:
| M | wl.java |  |  | 667 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- | 
1 file changed, 392 insertions(+), 275 deletions(-)
diff --git a/wl.java b/wl.java
@@ -1,45 +1,31 @@
 // wl.java -- (c) 2009 Tomas Hlavaty
 
+import java.io.UnsupportedEncodingException;
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.io.PrintStream;
 import java.util.HashMap;
+import java.math.BigInteger;
 import java.io.InputStream;
-import java.io.IOException;
-import java.io.FileInputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.util.ArrayList;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.math.BigInteger;
 
 class wl implements Runnable {
 
     final static String Enc = "UTF-8";
 
-    int Level = 0;
-
-    void _level() {
-        for(int I = Level; 0 < I; I--)
-            System.out.print("  ");
-    }
     void dbg(String M) {
-        _level();
         System.out.println(M);
     }
     void dbg(String M, Any E) {
-        _level();
         System.out.print(M);
         System.out.print(' ');
         print(E);
         System.out.println();
     }
     void dbg(String M, Any E, Any F) {
-        _level();
         System.out.print(M);
         System.out.print(' ');
         print(E);
@@ -48,7 +34,6 @@ class wl implements Runnable {
         System.out.println();
     }
     void dbg(String M, Any E, Any F, Any G, Any H) {
-        _level();
         System.out.print(M);
         System.out.print(' ');
         print(E);
@@ -62,50 +47,115 @@ class wl implements Runnable {
     }
 
     void err(Object X, String M) {
-        if(X instanceof Any) throw new RuntimeException(M + ": " + str((Any) X));
+        if(null != X && X instanceof Any)
+            throw new RuntimeException(M + ": " + str((Any) X));
         throw new RuntimeException(M + ": " + X);
     }
-    void err(String M) {throw new RuntimeException(M);}
+    static void err(String M) {throw new RuntimeException(M);}
 
-    public static interface Fn {
+    static public interface Fn {
         public Any fn(Any E);
     }
 
-    static class Any {
+    static interface Any {
+        public String nm();
+        public Any car();
+        public Any cdr();
+        public Object cxr();
+        public Any set(Any a);
+        public Any con(Any d);
+        public Object obj(Object x);
+        public boolean isCons();
+        public boolean isSym();
+        public boolean isIsym();
+        public boolean isObj();
+        public boolean isOfn();
+        public boolean isOstr();
+        public boolean isOnum();
+        public boolean isOobj();
+    }
+    static class Cons implements Any {
+        public Any car, cdr;
+        public Cons(Any a, Any d) {car = a; cdr = d;}
+        public String nm() {err("No Cons.nm"); return null;}
+        public Any car() {return car;}
+        public Any cdr() {return cdr;}
+        public Object cxr() {err("No Cons.cxr"); return null;}
+        public Any set(Any a) {car = a; return car;}
+        public Any con(Any d) {cdr = d; return cdr;}
+        public Object obj(Object x) {err("No Cons.obj"); return null;}
+        public boolean isCons() {return true;};
+        public boolean isSym() {return false;};
+        public boolean isIsym() {return false;};
+        public boolean isObj() {return false;};
+        public boolean isOfn() {return false;};
+        public boolean isOstr() {return false;};
+        public boolean isOnum() {return false;};
+        public boolean isOobj() {return false;};
+    }
+    static interface Sym extends Any {}
+    static class Isym implements Sym {
         public String nm;
         public Any car, cdr;
+        public Isym(String n, Any a, Any d) {nm = n; car = a; cdr = d;}
+        public String nm() {return nm;}
+        public Any car() {return car;}
+        public Any cdr() {return cdr;}
+        public Object cxr() {err("No Isym.cxr"); return null;}
+        public Any set(Any a) {car = a; return car;}
+        public Any con(Any d) {cdr = d; return cdr;}
+        public Object obj(Object x) {err("No Isym.obj"); return null;}
+        public boolean isCons() {return false;};
+        public boolean isSym() {return true;};
+        public boolean isIsym() {return true;};
+        public boolean isObj() {return false;};
+        public boolean isOfn() {return false;};
+        public boolean isOstr() {return false;};
+        public boolean isOnum() {return false;};
+        public boolean isOobj() {return false;};
+    }
+    static class Obj implements Any {
         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 BigInteger;}
-        public boolean isFn() {return cxr instanceof Fn;}
-        public boolean isObj() {return null == car && null == cdr;}
-    }
-    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, new BigInteger(x));}
-    Any mkFix(String x) {err(NIL, "fixpoint not implemented"); return NIL;}
-    static Any mkStr(String x) {return new Any(null, null, null, x);}
-    static Any mkAny(Object x) {return new Any(null, null, null, x);}
+        public Obj(Object x) {cxr = x;}
+        public String nm() {err("No Obj.nm"); return null;}
+        public Any car() {err("No Obj.car"); return null;}
+        public Any cdr() {err("No Obj.cdr"); return null;}
+        public Object cxr() {return cxr;}
+        public Any set(Any a) {err("No Obj.set"); return null;}
+        public Any con(Any d) {err("No Obj.con"); return null;}
+        public Object obj(Object x) {cxr = x; return cxr;}
+        public boolean isCons() {return false;};
+        public boolean isSym() {return false;};
+        public boolean isIsym() {return false;};
+        public boolean isObj() {return true;};
+        public boolean isOfn() {return cxr instanceof Fn;};
+        public boolean isOstr() {return cxr instanceof String;};
+        public boolean isOnum() {return cxr instanceof BigInteger;};
+        public boolean isOobj() {return !isOfn() && !isOstr() && !isOnum();};
+    }
 
-    final static Any NIL = new Any("NIL", null, null, null);
-    final static Any T = new Any("T", NIL, null, null);
+    static Any mkCons(Any a, Any d) {return new Cons(a, d);}
+    static Any mkIsym(String n, Any a, Any d) {return new Isym(n, a, d);}
+    static Any mkObj(Object x) {return new Obj(x);}
+    static Any mkOint(String x) {return mkObj(new BigInteger(x));}
+    static Any mkOfix(String x) {err("mkOfix not implemented"); return null;}
+
+    final static Any NIL = mkIsym("NIL", null, null);
+    final static Any T = mkIsym("T", NIL, null);
 
     static {
-        NIL.car = NIL;
-        NIL.cdr = NIL;
-        T.cdr = T;
+        NIL.set(NIL);
+        NIL.con(NIL);
+        T.con(T);
     }
 
     // reader
-    final static Any Lp = new Any(null, null, null, null);
-    final static Any Rp = new Any(null, null, null, null);
+    final static Any Lp = mkObj(null);
+    final static Any Rp = mkObj(null);
 
-    //final Any Qte = new Any("quote", NIL, NIL, null);
-    final Any Dot = new Any(".", NIL, NIL, null);
+    final Any Qte = mkIsym("quote", NIL, NIL);
+    final Any Dot = mkIsym(".", NIL, NIL);
+    final Any At = mkIsym("@", NIL, NIL);
 
     class In {
         Character c;
@@ -113,11 +163,11 @@ class wl implements Runnable {
         public In(InputStream S) {c = null; s = S;}
     }
 
-    final Any In = new Any("*In", null, null, new In(System.in));
-    final Any Out = new Any("*Out", null, null, System.out);
+    final Any In = mkIsym("*In", NIL, mkObj(new In(System.in)));
+    final Any Out = mkIsym("*Out", NIL, mkObj(System.out));
 
     Character peek() {
-        In I = (In) In.cxr;
+        In I = (In) In.cdr().cxr();
         try {
             if(null == I.c) I.c = (char) I.s.read();
         } catch(Exception e) {} // TODO eof vs error?
@@ -125,7 +175,7 @@ class wl implements Runnable {
     }
     Character xchar() {
         peek();
-        In I = (In) In.cxr;
+        In I = (In) In.cdr().cxr();
         Character Z = I.c;
         I.c = null;
         return Z;
@@ -137,51 +187,64 @@ class wl implements Runnable {
             xchar();
     }
     Any symbol() {
-        //dbg("symbol");
         Character C = xchar();
-        if(charIn(C, "() \t\n")) err(C, "Symbol expected");
+        if(charIn(C, "()\" \t\n\r")) err(C, "Symbol expected");
         StringBuffer L = new StringBuffer();
         L.append(C);
-        while((null != (C = peek())) && !charIn(C, "() \t\n"))
+        while((null != (C = peek())) && !charIn(C, "()\" \t\n\r"))
             L.append(xchar());
         String M = L.toString();
-        //dbg("symbol: " + M);
         return intern(M);
     }
+    Any text() {
+        StringBuffer L = new StringBuffer();
+        while(null != peek() && '"' != 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()) err("Unbalanced double quote");
+        if(0 < L.length()) return mkObj(L.toString()); //.replace(/\r\n/g, "\n");
+        return NIL;
+    }
     Any read1(boolean Top) {
-        //dbg("read1: " + Top);
         skip();
         Any Z = null;
         Character X = peek();
         if(null != X) {
-            //dbg("read1: '" + X + "'");
             switch(X) {
             case '(': xchar(); Z = readL(); break;
             case ')': xchar(); if(Top) err("Reader overflow"); Z = Rp; break;
+            case '"': xchar(); Z = text(); break;
+            case '\'': xchar(); Z = mkCons(Qte, read1(false)); break;
+            case '`': xchar(); Z = eval(read1(false)); break;
             default: Z = symbol();
             }
         }
-        //dbg("read1", Z);
         return Z;
     }
     Any readL() {
-        Level++;
-        //dbg("readL");
-        Any A = cons(NIL, NIL);
+        Any A = mkCons(NIL, NIL);
         Any Z = A;
         Any X;
         boolean D = false;
         while(null != (X = read1(false)) && Rp != X) {
             if(Dot != X) {
-                Z.cdr = D ? X : cons(X, NIL);
-                if(Z.cdr.isCons()) Z = Z.cdr;
+                Z.con(D ? X : mkCons(X, NIL));
+                if(Z.cdr().isCons()) Z = Z.cdr();
             }
             D = Dot == X;
         }
-        if(D) Z.cdr = A.cdr;
-        //dbg("readL", Z);
-        Level--;
-        return A.cdr;
+        if(null == X) err("Reader underflow");
+        if(D) Z.con(A.cdr());
+        return A.cdr();
     }
     public void run() {
         Any Z = null;
@@ -198,75 +261,144 @@ class wl implements Runnable {
     HashMap<String, Any> Sd = new HashMap<String, Any>();
 
     Any intern(String Nm) {
-        if(!Sd.containsKey(Nm)) Sd.put(Nm, new Any(Nm, NIL, NIL, null));
+        if(!Sd.containsKey(Nm)) Sd.put(Nm, mkIsym(Nm, NIL, NIL));
         return Sd.get(Nm);
     }
 
-
-
-
-
     Any xrun(Any E) {
         Any Z = NIL;
         while(NIL != E) {
-            Z = eval(E.car);
-            E = E.cdr;
+            Z = eval(E.car());
+            E = E.cdr();
         }
         return Z;
     }
     Any eval(Any E) {
-        //dbg("eval", E);
         Any Z = NIL;
-        if(E.isInt()) Z = E;
-        else if(E.isSym()) Z = E.isFn() ? E : E.cdr;
-        else if(E.isCons()) Z = apply(E);
-        else if(E.isStr()) Z = E;
+        if(E.isCons()) Z = apply(E);
+        else if(E.isIsym()) Z = E.cdr();
+        else if(E.isObj()) Z = E;
         else err(E, "Don't know how to eval");
-        //dbg("eval", E, Z);
         return Z;
     }
     Any apply(Any E) {
         Any Z = NIL;
-        Any F = eval(E.car);
-        if(F.isInt()) Z = E;
-        else if(F.isSym()) {
-            if(F.isFn()) Z = ((Fn) F.cxr).fn(E);
-            else applyC(E, F);
-        } else if(F.isCons()) applyC(E, F);
-        else err(E, "Unexpected function type");
+        Any F = eval(E.car());
+        if(F.isCons()) Z = applyC(E, F);
+        else if(F.isSym()) Z = applyC(E, F);
+        else if(F.isOfn()) Z = ((Fn) F.cxr()).fn(E);
+        else if(F.isObj()) Z = japplyC(E, F);
+        else err(E, "Don't know how to apply");
         return Z;
     }
     Any applyC(Any E, Any F) {
-        dbg("applyC", E, F); // TODO !!!
         Any Z = NIL;
-        Any A = E.cdr;
-        Any Fa = F.car;
-        Any Fb = F.cdr;
-        dbg("A", A);
-        dbg("Fa", Fa);
-        dbg("Fb", Fb);
+        Any A = E.cdr();
+        Any Fa = F.car();
+        Any Fb = F.cdr();
+        Any O = saveV(Fa, A);
+        Z = xrun(Fb);
+        restoreV(Fa, O);
+        return Z;
+    }
+    Any saveV(Any Fa, Any A) {
+        Any O = NIL;
+        if(Fa.isIsym()) {
+            if(NIL != Fa) {
+                O = mkCons(Fa.cdr(), NIL);
+                Fa.con(A);
+            } // TODO @
+        } else if(Fa.isCons()) {
+            Any B = mkCons(NIL, NIL);
+            Any Z = B;
+            while(Fa.isCons()) {
+                Any X = Fa.car();
+                Fa = Fa.cdr();
+                if(!X.isIsym()) err(X, "Isym expected in saveV");
+                Z.con(mkCons(X.cdr(), NIL));
+                Z = Z.cdr();
+                X.con(eval(A.car()));
+                A = A.cdr();
+            }
+            if(NIL != Fa) {
+                if(!Fa.isIsym()) err(Fa, "Isym expected in saveV");
+                Z.con(mkCons(Fa.cdr(), NIL));
+                Fa.con(A);
+            } // TODO (X Y . @)
+            O = B.cdr();
+        } else err(Fa, "Don't know how to saveV");
+        return O;
+    }
+    void restoreV(Any Fa, Any O) {
+        if(Fa.isIsym()) {
+            if(NIL != Fa) Fa.con(O.car());
+            // TODO @
+        } else if(Fa.isCons()) {
+            while(Fa.isCons()) {
+                Any X = Fa.car();
+                Fa = Fa.cdr();
+                if(!X.isIsym()) err(X, "Isym expected in restoreV");
+                X.con(O.car());
+                O = O.cdr();
+            }
+            if(NIL != Fa) {
+                if(!Fa.isIsym()) err(Fa, "Isym expected in saveV");
+                Fa.con(O.car());
+            } // TODO (X Y . @)
+        } else err(Fa, "Don't know how to restoreV");
+    }
+    Any japplyC(Any E, Any O) { // 'obj 'meth [arg ...]
+        Any I = E.cdr();
+        Any F = eval(I.car());
+        Any A = I.cdr();
+        Any Z = NIL;
+        ArrayList<Object> a = new ArrayList();
+        ArrayList<Class> t = new ArrayList();
+        for(Any X = A; NIL != X; X = X.cdr()) {
+            // TODO handle non-native?
+            Any Y = eval(X.car());
+            a.add(Y.cxr());
+            t.add(Y.cxr().getClass());
+        }
+        Object[] aa = a.toArray();
+        Class[] ta = (Class[]) t.toArray(new Class[aa.length]);
+        try {
+            Object o = O.cxr();
+            Class c = o instanceof Class ? (Class) o : o.getClass();
+            Method m = c.getMethod(F.nm(), ta);
+            Object r = m.invoke(o, aa);
+            Z = mkObj(r);
+        } catch(NoSuchMethodException e) {
+            err(E, "NoSuchMethodException");
+        } catch(IllegalAccessException e) {
+            err(E, "IllegalAccessException");
+        } catch(InvocationTargetException e) {
+            err(E, "InvocationTargetException");
+        }
         return Z;
     }
 
     void fn(String Nm, Fn F) {
         Any Z = Sd.get(Nm);
-        if(null != Z) Z.cxr = F;
-        else Sd.put(Nm, new Any(Nm, null, null, F));
+        if(null != Z) Z.con(mkObj(F));
+        else Sd.put(Nm, mkIsym(Nm, NIL, mkObj(F)));
     }
 
     public wl() {
         Sd.put("NIL", NIL);
         Sd.put("T", T);
-        //Sd.put("quote", Qte);
+        Sd.put("quote", Qte);
         Sd.put(".", Dot);
+        Sd.put("@", At);
         Sd.put("*In", In);
         Sd.put("*Out", Out);
+        Sd.put("java.lang.Class", mkObj(java.lang.Class.class));
 
-        fn("run", new Fn() {public Any fn(Any E) {return xrun(E.cdr.car);}});
-        fn("eval", new Fn() {public Any fn(Any E) {return eval(eval(E.cdr.car));}});
-        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("run", new Fn() {public Any fn(Any E) {return xrun(E.cdr().car());}});
+        fn("eval", new Fn() {public Any fn(Any E) {return eval(eval(E.cdr().car()));}});
+        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);
@@ -320,79 +452,79 @@ class wl implements Runnable {
         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;
+                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 xrun(Y.cdr);
+                        Y = Y.cdr();
+                        if(NIL == eval(Y.car())) return xrun(Y.cdr());
                     } else if(Y.isCons() && T == Y) {
-                        Y = Y.cdr;
-                        if(NIL != eval(Y.car)) return xrun(Y.cdr);
+                        Y = Y.cdr();
+                        if(NIL != eval(Y.car())) return xrun(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;
+            Any X = E.cdr();
+            return eval(X.car()) == eval(X.cdr().car()) ? T : NIL;
         }});
 
         fn("peek", new Fn() {public Any fn(Any E) {
             Character X = peek();
-            return null == X ? NIL : mkStr(X.toString());
+            return null == X ? NIL : mkObj(X.toString());
         }});
         fn("char", new Fn() {public Any fn(Any E) {
             Character X = xchar();
-            return null == X ? NIL : mkStr(X.toString());
+            return null == X ? NIL : mkObj(X.toString());
         }});
         fn("print", new Fn() {public Any fn(Any E) {
-            PrintStream S = (PrintStream) Out.cxr;
+            PrintStream S = (PrintStream) Out.cdr().cxr();
             Any Z = NIL;
             int I = 0;
-            for(Any X = E.cdr; NIL != X; X = X.cdr) {
+            for(Any X = E.cdr(); NIL != X; X = X.cdr()) {
                 if(0 < I++) S.print(' ');
-                Z = eval(X.car);
+                Z = eval(X.car());
                 print(Z);
             }
             return Z;
         }});
 
-        fn("in", new Fn() {public Any fn(Any E) {
-            Any X = E.cdr;
-            String F = evStr(X.car);
-            In S = null;
-            Any Z = NIL;
-            try {
-                S = new In(new FileInputStream(F));
-                In I = (In) In.cxr;
-                In.cxr = S;
-                Z = xrun(X.cdr);
-                In.cxr = I;
-                S.s.close();
-            } catch(FileNotFoundException e) {
-                err(E, "File not found");
-            } catch(IOException e) {
-                err(E, "Error closing input");
-            }
-            return Z;
-        }});
-        fn("out", new Fn() {public Any fn(Any E) {
-            Any X = E.cdr;
-            String F = evStr(X.car);
-            Any Z = NIL;
-            try {
-                FileOutputStream B = new FileOutputStream(F);
-                PrintStream S = new PrintStream(B);
-                OutputStream O = (OutputStream) Out.cxr;
-                Out.cxr = S;
-                Z = xrun(X.cdr);
-                Out.cxr = O;
-                S.close();
-            } catch(FileNotFoundException e) {
-                err(E, "File not found");
-            }
-            return Z;
-        }});
+        // fn("in", new Fn() {public Any fn(Any E) {
+        //     Any X = E.cdr;
+        //     String F = evStr(X.car);
+        //     In S = null;
+        //     Any Z = NIL;
+        //     try {
+        //         S = new In(new FileInputStream(F));
+        //         In I = (In) In.cxr;
+        //         In.cxr = S;
+        //         Z = xrun(X.cdr);
+        //         In.cxr = I;
+        //         S.s.close();
+        //     } catch(FileNotFoundException e) {
+        //         err(E, "File not found");
+        //     } catch(IOException e) {
+        //         err(E, "Error closing input");
+        //     }
+        //     return Z;
+        // }});
+        // fn("out", new Fn() {public Any fn(Any E) {
+        //     Any X = E.cdr;
+        //     String F = evStr(X.car);
+        //     Any Z = NIL;
+        //     try {
+        //         FileOutputStream B = new FileOutputStream(F);
+        //         PrintStream S = new PrintStream(B);
+        //         OutputStream O = (OutputStream) Out.cxr;
+        //         Out.cxr = S;
+        //         Z = xrun(X.cdr);
+        //         Out.cxr = O;
+        //         S.close();
+        //     } catch(FileNotFoundException e) {
+        //         err(E, "File not found");
+        //     }
+        //     return Z;
+        // }});
         // fn("load", new Fn() {public Any fn(Any E) {
         //     Any Z = NIL;
         //     for(Any X = E.cdr; NIL != X; X = X.cdr) {
@@ -417,89 +549,90 @@ class wl implements Runnable {
         // }});
 
         fn("def", new Fn() {public Any fn(Any E) {
-            Any X = E.cdr;
-            Any N = eval(X.car);
+            Any X = E.cdr();
+            Any N = eval(X.car());
             if(!N.isSym()) err(E, "Symbol expected");
-            if(!Sd.containsKey(N.nm)) err(E, "Symbol not interned");
-            Any V = eval(X.cdr.car);
-            Sd.get(N.nm).cdr = V;
+            if(!Sd.containsKey(N.nm())) err(E, "Symbol not interned");
+            Any V = eval(X.cdr().car());
+            Sd.get(N.nm()).con(V);
             return N;
         }});
         fn("val", new Fn() {public Any fn(Any E) {
             Any Z = NIL;
-            Any X = eval(E.cdr.car);
-            if(X.isSym()) Z = X.cdr;
-            else if(X.isStr()) Z = X;
-            else if(X.isCons()) Z = X.car;
-            else err(E, "Expected sym|str|cell");
+            Any X = eval(E.cdr().car());
+            if(X.isCons()) Z = X.car();
+            else if(X.isSym()) Z = X.cdr();
+            else if(X.isObj()) Z = X;
+            else err(E, "Don't know how to val");
             return Z;
         }});
         fn("cons", new Fn() {public Any fn(Any E) {
-            Any X = E.cdr;
-            return cons(eval(X.car), eval(X.cdr.car));
+            Any X = E.cdr();
+            return mkCons(eval(X.car()), eval(X.cdr().car()));
         }});
 
-        fn("jclass", new Fn() {public Any fn(Any E) { // jclass 'sym
-            Any X = E.cdr;
-            String N = evStr(X.car);
-            Any Z = NIL;
-            try {
-                Class C = Class.forName(N);
-                Z = mkAny(C);
-            } catch(ClassNotFoundException e) {
-            }
-            return Z;
-        }});
-        fn("jcall", new Fn() {public Any fn(Any E) { // jcall 'fn 'obj [arg ...]
-            Any I = E.cdr;
-            Any F = eval(I.car);
-            I = I.cdr;
-            Any O = eval(I.car);
-            Any A = I.cdr;
-            Any Z = NIL;
-            ArrayList<Object> a = new ArrayList();
-            ArrayList<Class> t = new ArrayList();
-            for(Any X = A; NIL != X; X = X.cdr) {
-                // TODO handle non-native?
-                Any Y = eval(X.car);
-                a.add(Y.cxr);
-                t.add(Y.cxr.getClass());
-            }
-            Object[] aa = a.toArray();
-            Class[] ta = (Class[]) t.toArray(new Class[aa.length]);
-            try {
-                Class c = O.cxr instanceof Class ? (Class) O.cxr : O.cxr.getClass();
-                Method m = c.getMethod(F.nm, ta);
-                Object r = m.invoke(O.cxr, aa);
-                Z = mkAny(r);
-            } catch(NoSuchMethodException e) {
-                err(E, "NoSuchMethodException");
-            } catch(IllegalAccessException e) {
-                err(E, "IllegalAccessException");
-            } catch(InvocationTargetException e) {
-                err(E, "InvocationTargetException");
-            }
-            return Z;
-        }});
+        // fn("jclass", new Fn() {public Any fn(Any E) { // jclass 'sym
+        //     Any X = E.cdr();
+        //     String N = evStr(X.car());
+        //     Any Z = NIL;
+        //     try {
+        //         Class C = Class.forName(N);
+        //         Z = mkObj(C);
+        //     } catch(ClassNotFoundException e) {
+        //     }
+        //     return Z;
+        // }});
+        // fn("jcall", new Fn() {public Any fn(Any E) { // jcall 'fn 'obj [arg ...]
+        //     Any I = E.cdr();
+        //     Any F = eval(I.car());
+        //     I = I.cdr();
+        //     Any O = eval(I.car());
+        //     Any A = I.cdr();
+        //     Any Z = NIL;
+        //     ArrayList<Object> a = new ArrayList();
+        //     ArrayList<Class> t = new ArrayList();
+        //     for(Any X = A; NIL != X; X = X.cdr()) {
+        //         // TODO handle non-native?
+        //         Any Y = eval(X.car());
+        //         a.add(Y.cxr());
+        //         t.add(Y.cxr().getClass());
+        //     }
+        //     Object[] aa = a.toArray();
+        //     Class[] ta = (Class[]) t.toArray(new Class[aa.length]);
+        //     try {
+        //         Object o = O.cxr();
+        //         Class c = o instanceof Class ? (Class) o : o.getClass();
+        //         Method m = c.getMethod(F.nm(), ta);
+        //         Object r = m.invoke(o, aa);
+        //         Z = mkObj(r);
+        //     } catch(NoSuchMethodException e) {
+        //         err(E, "NoSuchMethodException");
+        //     } catch(IllegalAccessException e) {
+        //         err(E, "IllegalAccessException");
+        //     } catch(InvocationTargetException e) {
+        //         err(E, "InvocationTargetException");
+        //     }
+        //     return Z;
+        // }});
         fn("jnew", new Fn() {public Any fn(Any E) { // jnew 'cls [arg ...]
-            Any I = E.cdr;
-            Any C = eval(I.car);
-            Any A = I.cdr;
+            Any I = E.cdr();
+            Any C = eval(I.car());
+            Any A = I.cdr();
             Any Z = NIL;
             ArrayList<Object> a = new ArrayList();
             ArrayList<Class> t = new ArrayList();
-            for(Any X = A; NIL != X; X = X.cdr) {
+            for(Any X = A; NIL != X; X = X.cdr()) {
                 // TODO handle non-native?
-                Any Y = eval(X.car);
-                a.add(Y.cxr);
-                t.add(Y.cxr.getClass());
+                Any Y = eval(X.car());
+                a.add(Y.cxr());
+                t.add(Y.cxr().getClass());
             }
             Object[] aa = a.toArray();
             Class[] ta = (Class[]) t.toArray(new Class[aa.length]);
             try {
-                Constructor c = ((Class) C.cxr).getConstructor(ta);
+                Constructor c = ((Class) C.cxr()).getConstructor(ta);
                 Object r = c.newInstance(aa);
-                Z = mkAny(r);
+                Z = mkObj(r);
             } catch(NoSuchMethodException e) {
                 err(E, "NoSuchMethodException");
             } catch(InstantiationException e) {
@@ -511,67 +644,49 @@ class wl implements Runnable {
             }
             return Z;
         }});
-        fn("jfield", new Fn() {public Any fn(Any E) { // jfield 'fld 'obj
-            Any X = E.cdr;
-            Any F = eval(X.car);
-            X = X.cdr;
-            Any O = eval(X.car);
+        fn("jfield", new Fn() {public Any fn(Any E) { // jfield 'obj 'fld ['val]
+            // TODO set 'val
+            Any X = E.cdr();
+            Any O = eval(X.car());
+            X = X.cdr();
+            Any F = eval(X.car());
             Any Z = NIL;
             try {
-                Class c = O.cxr instanceof Class ? (Class) O.cxr : O.cxr.getClass();
-                Field f = c.getField(F.nm);
-                Object r = f.get(O.cxr);
-                Z = mkAny(r);
+                Object o = O.cxr();
+                Class c = o instanceof Class ? (Class) o : o.getClass();
+                Field f = c.getField(F.nm());
+                Object r = f.get(o);
+                Z = mkObj(r);
             } catch(NoSuchFieldException e) {
-                dbg("NoSuchFieldException", E);
+                err(E, "NoSuchFieldException");
             } catch(IllegalAccessException e) {
-                dbg("IllegalAccessException", E);
+                err(E, "IllegalAccessException");
             }
             return Z;
         }});
-        // fn("gc", new Fn() {public Any fn(Any E) {
-        //     Runtime r = Runtime.getRuntime();
-        //     r.gc();
-        //     return NIL;
-        // }});
-        // fn("heap", new Fn() {public Any fn(Any E) {
-        //     Runtime R = Runtime.getRuntime();
-        //     long A = R.freeMemory();
-        //     long B = R.totalMemory();
-        //     long C = R.maxMemory();
-        //     long Z = B - A;
-        //     if(NIL != E.cdr) {
-        //         if(T == eval(E.cdr.car)) Z = A;
-        //         else Z = C;
-        //     }
-        //     return mkInt("" + Z / (1024 * 1024));
-        // }});
     }
     
     String evStr(Any E) {
         Any X = eval(E);
         String S = null;
-        if(X.isStr()) S = (String) X.cxr;
-        else if(X.isSym()) S = X.nm;
-        else err(E, "Expected str|sym");
+        if(X.isSym()) S = X.nm();
+        else if(X.isOstr()) S = (String) X.cxr();
+        else err(E, "Don't know how to evStr");
         return S;
     }
 
     void print(Any E) {
-        PrintStream S = (PrintStream) Out.cxr;
-        if(E.isSym()) S.print(E.nm);
-        //else if(E.isInt()) S.print(E.cxr);
-        else if(E.isCons()) {
+        PrintStream S = (PrintStream) Out.cdr().cxr();
+        if(E.isCons()) {
             Any X = E;
-            // if(Qte == X.car) {
-            //     S.print('\'');
-            //     print(X.cdr);
-            // } else {
-            {
+            if(Qte == X.car()) {
+                S.print('\'');
+                print(X.cdr());
+            } else {
                 S.print('(');
                 while(X.isCons()) {
-                    print(X.car);
-                    X = X.cdr;
+                    print(X.car());
+                    X = X.cdr();
                     if(NIL != X) S.print(' ');
                     if(E == X) {
                         S.print('.');
@@ -584,30 +699,32 @@ class wl implements Runnable {
                 }
                 S.print(')');
             }
-        // } else if(E.isStr()) {
-        //     S.print('"');
-        //     String X = (String) E.cxr;
-        //     for(int I = 0; I < X.length(); I++) {
-        //         Character C = X.charAt(I);
-        //         if('\\' == C) S.print("\\\\");
-        //         else if('"' == C) S.print("\\\"");
-        //         else S.print(C);
-        //     }
-        //     S.print('"');
-        } else {
+        } else if(E.isIsym()) S.print(E.nm());
+        else if(E.isOnum()) S.print(E.cxr());
+        else if(E.isOstr()) {
+            S.print('"');
+            String X = (String) E.cxr();
+            for(int I = 0; I < X.length(); I++) {
+                Character C = X.charAt(I);
+                if('\\' == C) S.print("\\\\");
+                else if('"' == C) S.print("\\\"");
+                else S.print(C);
+            }
+            S.print('"');
+        } else if(E.isObj()) {
             S.print('[');
-            S.print(E.cxr);
+            S.print(E.cxr());
             S.print(']');
-        }
+        } else err(E, "Don't know how to print");
     }
 
     String str(Any E) {
         ByteArrayOutputStream B = new ByteArrayOutputStream();
         PrintStream S = new PrintStream(B);
-        PrintStream O = (PrintStream) Out.cxr;
-        Out.cxr = S;
+        Any O = Out.cdr();
+        Out.con(mkObj(S));
         print(E);
-        Out.cxr = O;
+        Out.con(O);
         String Z = null;
         try {
             Z = B.toString(Enc);