commit 2004f07abad444dbed83584edd10d32e4d3a227b
parent 4daa94954d15e88d1dc9db0a639cca1b47676cd0
Author: tomas <tomas@logand.com>
Date:   Wed, 21 Oct 2009 00:08:44 +0200
In static+close(),'jnew' constr dyn dispatch,'read',needLength in out load
Diffstat:
| M | java.wl |  |  | 22 | ++++++++++++---------- | 
| M | wl.java |  |  | 111 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ | 
2 files changed, 90 insertions(+), 43 deletions(-)
diff --git a/java.wl b/java.wl
@@ -321,8 +321,10 @@
 # | cdr      | map  | maplist | mapcon |
 # | car prop | maps |    -    |   -    |
 
+(de needLength (L) (foldl '((X Y) (cons NIL X)) NIL L))
+
 (de map (F . @)
-   (let (L (rest) M NIL A (need (length L)) B NIL E)
+   (let (L (rest) M NIL A (needLength L) B NIL E)
       (loop
          (setq M L B A E T)
          (while M
@@ -335,7 +337,7 @@
          (apply F A) ) ) )
 
 (de mapc (F . @)
-   (let (L (rest) M NIL A (need (length L)) B NIL E)
+   (let (L (rest) M NIL A (needLength L) B NIL E)
       (loop
          (setq M L B A E T)
          (while M
@@ -347,7 +349,7 @@
          (apply F A) ) ) )
 
 (de mapcan (F . @)
-   (let (L (rest) M NIL A (need (length L)) B NIL E)
+   (let (L (rest) M NIL A (needLength L) B NIL E)
       (make
          (loop
             (setq M L B A E T)
@@ -360,7 +362,7 @@
             (chain (apply F A)) ) ) ) )
 
 (de mapcar (F . @)
-   (let (L (rest) M NIL A (need (length L)) B NIL E)
+   (let (L (rest) M NIL A (needLength L) B NIL E)
       (make
          (loop
             (setq M L B A E T)
@@ -373,7 +375,7 @@
             (link (apply F A)) ) ) ) )
 
 (de mapcon (F . @)
-   (let (L (rest) M NIL A (need (length L)) B NIL E)
+   (let (L (rest) M NIL A (needLength L) B NIL E)
       (make
          (loop
             (setq M L B A E T)
@@ -387,7 +389,7 @@
             (chain (apply F A)) ) ) ) )
 
 (de maplist (F . @)
-   (let (L (rest) M NIL A (need (length L)) B NIL E)
+   (let (L (rest) M NIL A (needLength L) B NIL E)
       (make
          (loop
             (setq M L B A E T)
@@ -406,17 +408,17 @@
 (de in (F . P)
    (let *In (jnew `(jclass 'wl$In) (jnew `(jclass 'java.io.FileInputStream) F))
       (finally (*In 'close)
-         (run P 1) ) ) )
+         (run P 1 '(*In)) ) ) ) # TODO
 
 (de out (F . P)
    (let *Out (jnew `(jclass 'java.io.PrintStream)
                 (jnew `(jclass 'java.io.FileOutputStream) F) )
       (finally (*Out 'close)
-         (run P 1) ) ) )
+         (run P 1 '(*Out)) ) ) ) # TODO
 
 (de load @
-   (for F (rest)
-      (in F
+   (while (args)
+      (in (next)
          (finally ()
             (while (read)
                (eval @ 1) ) ) ) ) )
diff --git a/wl.java b/wl.java
@@ -21,6 +21,7 @@ import java.lang.reflect.Proxy;
 import java.lang.reflect.InvocationHandler;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.io.IOException;
 
 class wl implements Runnable {
 
@@ -195,11 +196,18 @@ class wl implements Runnable {
     final Any At = mkIsym("@", NIL);
     final Any Args = mkIsym("*Args", NIL);
 
-    public class In {
+    public static class In {
         InputStream s;
         int b; // -2 ~ unbound, -1 ~ eof, otherwise 0--255
         Character c; // null ~ NIL
         public In(InputStream S) {s = S; clear();}
+        public void close() {
+            try {
+                s.close();
+            } catch(IOException e) {
+                err("Error closing wl$In");
+            }
+        }
         void clear() {b = -2; c = null;}
         public boolean eof() {return b == -1;}
         public void eof(Any X) {if(NIL != X) b = -1;}
@@ -411,7 +419,7 @@ class wl implements Runnable {
     }
 
     // runtime dispatch
-    class MethodComparator implements Comparator<Method> {
+    class LtM implements Comparator<Method> {
         public int compare(Method l, Method r) {
             // most specific first
             Class[] lc = l.getParameterTypes();
@@ -422,7 +430,19 @@ class wl implements Runnable {
             return lc.length < rc.length ? 1 : -1;
         }
     }
-    final MethodComparator methodComparator = new MethodComparator();
+    class LtC implements Comparator<Constructor> { // code reuse in Java;-{
+        public int compare(Constructor l, Constructor r) {
+            // most specific first
+            Class[] lc = l.getParameterTypes();
+            Class[] rc = r.getParameterTypes();
+            for(int i = 0, j = 0; i < lc.length && j < rc.length; i++, j++)
+                if(!lc[i].equals(rc[i]) && lc[i].isAssignableFrom(rc[i]))
+                    return 1;
+            return lc.length < rc.length ? 1 : -1;
+        }
+    }
+    final LtM ltM = new LtM();
+    final LtC ltC = new LtC();
     boolean isApplicable(Method m, Object[] args) {
         Class[] c = m.getParameterTypes();
         if(c.length != args.length) return false; // nargs must be same
@@ -432,41 +452,67 @@ class wl implements Runnable {
                     return false;
         return true;
     }
+    boolean isApplicable(Constructor m, Object[] args) {
+        Class[] c = m.getParameterTypes();
+        if(c.length != args.length) return false; // nargs must be same
+        for(int i = 0; i < c.length; i++)
+            if(!c[i].isInstance(args[i])) // must be instanceof
+                if(args[i] != null || !Object.class.equals(c[i]))
+                    return false;
+        return true;
+    }
+    Method applicableMethod(Class c, String nm, Object[] aa) {
+        //Method m = c.getMethod(nm, ta);
+
+        // sort methods
+        final List<Method> methods = new LinkedList<Method>();
+        for(Method m: c.getMethods())
+            if(m.getName().equals(nm))
+                methods.add(m);
+        Collections.sort(methods, ltM);
+        // apply first (most specific) applicable method
+        Method m = null;
+        for(Method method: methods)
+            if(isApplicable(method, aa)) {
+                m = method;
+                break;
+            }
+        return m;
+    }
+    Constructor applicableConstructor(Class c, Object[] aa) {
+        //Constructor c = ((Class) C.obj()).getConstructor(ta);
+
+        // sort methods
+        final List<Constructor> methods = new LinkedList<Constructor>();
+        for(Constructor m: c.getConstructors())
+             methods.add(m);
+        Collections.sort(methods, ltC);
+        // apply first (most specific) applicable method
+        Constructor m = null;
+        for(Constructor method: methods)
+            if(isApplicable(method, aa)) {
+                m = method;
+                break;
+            }
+        return m;
+    }
     Any applyO(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()) {
             Any Y = eval(X.car());
             Object y = Y.isIsym() ? Y.nm() : Y.obj();
             a.add(y);
-            t.add(y.getClass());
         }
+        Object o = O.obj();
+        Class c = o instanceof Class ? (Class) o : o.getClass();
+        String nm = F.isOstr() ? (String) F.obj() : F.nm();
         Object[] aa = a.toArray();
-        Class[] ta = (Class[]) t.toArray(new Class[aa.length]);
         try {
-            Object o = O.obj();
-            Class c = o instanceof Class ? (Class) o : o.getClass();
-            String nm = F.isOstr() ? (String) F.obj() : F.nm();
-            //Method m = c.getMethod(nm, ta);
-            //Object r = m.invoke(o, aa);
-
-            // sort methods
-            final List<Method> methods = new LinkedList<Method>();
-            for(Method m: c.getMethods())
-                if(m.getName().equals(nm))
-                    methods.add(m);
-            Collections.sort(methods, methodComparator);
-            // apply first (most specific) applicable method
-            Method m = null;
-            for(Method method: methods)
-                if(isApplicable(method, aa)) {
-                    m = method;
-                    break;
-                }
+            Method m = applicableMethod(c, nm, aa);
             if(null == m) err(E, "No applicable method");
             Object r = m.invoke(o, aa);
             Z = mkObj(r);
@@ -899,22 +945,18 @@ class wl implements Runnable {
             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()) {
                 Any Y = eval(X.car());
                 Object y = Y.isIsym() ? Y.nm() : Y.obj();
                 a.add(y);
-                t.add(y.getClass());
             }
+            Class c = (Class) C.obj();
             Object[] aa = a.toArray();
-            Class[] ta = (Class[]) t.toArray(new Class[aa.length]);
             try {
-                // TODO might need dynamic dispatch here too
-                Constructor c = ((Class) C.obj()).getConstructor(ta);
-                Object r = c.newInstance(aa);
+                Constructor m = applicableConstructor(c, aa);
+                if(null == m) err(E, "No applicable constructor");
+                Object r = m.newInstance(aa);
                 Z = mkObj(r);
-            } catch(NoSuchMethodException e) {
-                err(E, "NoSuchMethodException");
             } catch(InstantiationException e) {
                 err(E, "InstantiationException");
             } catch(IllegalAccessException e) {
@@ -1030,6 +1072,9 @@ class wl implements Runnable {
             }
             return Z;
         }});
+        fn("read", new Fn() {public Any fn(Any E) { // TODO
+            return read1(true);
+        }});
     }
 
     void print(Any E) {