commit eeb39b653146973b7f7acf27d859c31ca9233ad1
parent 95531fb330388effe89f9bfff315d59e60b59a2f
Author: tomas <tomas@logand.com>
Date:   Fri, 23 Oct 2009 23:33:56 +0200
exceptions, quit throw catch finally, fix run eval let let? applyC redo
Diffstat:
| M | java.wl |  |  | 2 | ++ | 
| M | wl.java |  |  | 116 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- | 
2 files changed, 78 insertions(+), 40 deletions(-)
diff --git a/java.wl b/java.wl
@@ -458,3 +458,5 @@
 (de <> @ (not (pass =)))
 
 (de abs (N) (if (lt0 N) (- N) N))
+
+(de test (X . P) (println X (run P 1)))
diff --git a/wl.java b/wl.java
@@ -348,24 +348,26 @@ class wl implements Runnable {
     Any xrun(Any P, int n, Any L) {
         Any Z = NIL;
         Any E = 0 < n ? undo(n, L) : NIL;
-        if(P.isCons())
-            while(NIL != P) {
-                Z = eval(P.car());
-                P = P.cdr();
-            }
-        else eval(P);
-        if(NIL != E) redo(E);
+        try {
+            if(P.isCons())
+                while(NIL != P) {
+                    Z = eval(P.car());
+                    P = P.cdr();
+                }
+            else Z = eval(P);
+        } finally {redo(E);}
         return Z;
     }
     Any xrun(Any P) {return xrun(P, 0, NIL);}
     Any eval(Any X, int n, Any L) {
         Any Z = NIL;
         Any E = 0 < n ? undo(n, L) : NIL;
-        if(X.isCons()) Z = apply(X);
-        else if(X.isIsym()) Z = X.val();
-        else if(X.isObj()) Z = X;
-        else err(X, "Don't know how to eval");
-        if(NIL != E) redo(E);
+        try {
+            if(X.isCons()) Z = apply(X);
+            else if(X.isIsym()) Z = X.val();
+            else if(X.isObj()) Z = X;
+            else err(X, "Don't know how to eval");
+        } finally {redo(E);}
         return Z;
     }
     Any eval(Any X) {return eval(X, 0, NIL);}
@@ -403,8 +405,8 @@ class wl implements Runnable {
                 else bind(Fa, A);
             }
         } else err(Fa, "Don't know how to bind");
-        Z = xrun(Fb);
-        unframe();
+        try {Z = xrun(Fb);}
+        finally {unframe();}
         return Z;
     }
     Any mapcarEval(Any E) {
@@ -568,23 +570,25 @@ class wl implements Runnable {
         return Z;
     }
     void redo(Any E) {
-        Any X = Env.val();
-        while(NIL != E) {
-            Any C = E.car();
-            if(C.isCons()) {
-                // swap
-                Any K = C.car();
-                Any V = K.val();
-                K.val(C.cdr());
-                C.cdr(V);
+        if(NIL != E) {
+            Any X = Env.val();
+            while(NIL != E) {
+                Any C = E.car();
+                if(C.isCons()) {
+                    // swap
+                    Any K = C.car();
+                    Any V = K.val();
+                    K.val(C.cdr());
+                    C.cdr(V);
+                }
+                // flip
+                Any F = E;
+                E = E.cdr();
+                F.cdr(X);
+                X = F;
             }
-            // flip
-            Any F = E;
-            E = E.cdr();
-            F.cdr(X);
-            X = F;
+            Env.val(X);
         }
-        Env.val(X);
     }
     boolean eq(Any X, Any Y) {
         boolean z = true;
@@ -883,14 +887,14 @@ class wl implements Runnable {
                     bind(K, V);
                     n++;
                 }
-                Z = xrun(I.cdr());
-                unbind(n);
+                try {Z = xrun(I.cdr());}
+                finally {unbind(n);}
             } else if(L.isIsym()) { // (let L 'V . P)
                 I = I.cdr();
                 Any V = eval(I.car());
                 bind(L, V);
-                Z = xrun(I.cdr());
-                unbind();
+                try {Z = xrun(I.cdr());}
+                finally {unbind();}
             } else err(E, "Don't know how to let");
             return Z;
         }});
@@ -902,8 +906,8 @@ class wl implements Runnable {
             Any V = eval(I.car());
             if(NIL != V) {
                 bind(L, V);
-                Z = xrun(I.cdr());
-                unbind();
+                try {Z = xrun(I.cdr());}
+                finally {unbind();}
             }
             return Z;
         }});
@@ -918,12 +922,12 @@ class wl implements Runnable {
                     n++;
                     L = L.cdr();
                 }
-                Z = xrun(I.cdr());
-                unbind(n);
+                try {Z = xrun(I.cdr());}
+                finally {unbind(n);}
             } else if(L.isIsym()) { // (use L . P)
                 bind(L);
-                Z = xrun(I.cdr());
-                unbind();
+                try {Z = xrun(I.cdr());}
+                finally {unbind();}
             } else err(E, "Don't know how to let");
             return Z;
         }});
@@ -1092,7 +1096,7 @@ class wl implements Runnable {
             }
             return Z;
         }});
-        fn("finally", new Fn() {public Any fn(Any E) { // TODO
+        fn("finally", new Fn() {public Any fn(Any E) {
             Any I = E.cdr();
             Any F = I.car();
             Any P = I.cdr();
@@ -1101,11 +1105,43 @@ class wl implements Runnable {
             finally {eval(F);}
             return Z;
         }});
+        fn("quit", new Fn() {public Any fn(Any E) {
+            Any I = E.cdr();
+            Any C = eval(I.car());
+            Any M = eval(I.cdr().car());
+            throw new Exc(C, M);
+        }});
+        fn("throw", new Fn() {public Any fn(Any E) {
+            Any I = E.cdr();
+            Any C = eval(I.car());
+            Any M = eval(I.cdr().car());
+            throw new Exc(C, M);
+        }});
+        fn("catch", new Fn() {public Any fn(Any E) {
+            Any I = E.cdr();
+            Any C = eval(I.car());
+            Any P = I.cdr();
+            Any Z = NIL;
+            try {Z = xrun(P);}
+            catch(Exc e) {
+                if(T == C || C == e.cnd()) Z = e.msg();
+                else throw e;
+            }
+            return Z;
+        }});
         fn("read", new Fn() {public Any fn(Any E) { // TODO
             return read1(true);
         }});
     }
 
+    class Exc extends RuntimeException {
+        Any C, M;
+        public Exc(Any c, Any m) {C = c; M = m;}
+        public String toString() {return str(C) + " -- " + str(M);}
+        public Any cnd() {return C;}
+        public Any msg() {return M;}
+    }
+
     void print(Any E) {
         PrintStream S = (PrintStream) Out.val().obj();
         if(E.isCons()) {