wl

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

commit 01b71465d522197dcb2f1bb16535786b4e058a71
parent 3d41ab29bd5f483d8f46aa7254327ef6e77cf85b
Author: tomas <tomas@logand.com>
Date:   Sat, 17 Oct 2009 00:34:37 +0200

runtime dispatch, jproxy, Que + wait, push and other

Diffstat:
Mjava.wl | 26+++++++++++++++-----------
Mwl.java | 149++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 155 insertions(+), 20 deletions(-)

diff --git a/java.wl b/java.wl @@ -222,16 +222,6 @@ (pass prin) (prin "^J") ) -(de jclass (N) (java.lang.Class 'forName N)) - -(de gc () (`((jclass 'java.lang.Runtime) 'getRuntime) 'gc)) - -(de import L - (let (P (pop 'L) C) - (while L - (setq C (pop 'L)) - (def C (jclass (pack P "." C))) ) ) ) - (de - L (let? Z (eval (pop 'L) 1) (ifn L @@ -269,7 +259,17 @@ (de + @ (- (pass - 0))) (de =0 (N) (when (= 0 N) N)) -(de n0 (N) (not(=0 N))) +(de n0 (N) (not (=0 N))) + +(de jclass (N) (java.lang.Class 'forName N)) + +(de gc () (`((jclass 'java.lang.Runtime) 'getRuntime) 'gc)) + +(de import L + (let (P (pop 'L) C) + (while L + (setq C (pop 'L)) + (def C (jclass (pack P "." C))) ) ) ) (de jnum (X) (jnew `(jclass 'java.math.BigInteger) (X 'toString)) ) @@ -282,3 +282,7 @@ (jnum (R 'maxMemory)) ) (- (jnum (R 'totalMemory)) (jnum (R 'freeMemory))) ) `(* 1024 1024) ) ) ) + +(def 'true (jfield (jclass 'java.lang.Boolean) 'TRUE)) +(def 'false (jfield (jclass 'java.lang.Boolean) 'FALSE)) +(def 'null (gc)) diff --git a/wl.java b/wl.java @@ -13,6 +13,14 @@ import java.util.ArrayList; import java.lang.reflect.Field; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.util.Comparator; +import java.util.List; +import java.util.LinkedList; +import java.util.Collections; +import java.lang.reflect.Proxy; +import java.lang.reflect.InvocationHandler; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; class wl implements Runnable { @@ -156,7 +164,7 @@ class wl implements Runnable { static Any mkIsym(String n, Any v) {return new Isym(n, v, NIL);} 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;} + static Any mkOfix(String x) {err("TODO mkOfix"); return null;} final static Any NIL = mkIsym("NIL", null); final static Any T = mkIsym("T", null); @@ -205,6 +213,7 @@ class wl implements Runnable { final Any Out = mkIsym("*Out", mkObj(System.out)); final Any Env = mkIsym("*Env", NIL); final Any Stk = mkIsym("*Stk", NIL); + final Any Scl = mkIsym("*Scl", mkObj(BigInteger.ZERO)); Character peek() {return ((In) In.val().obj()).peek();} Character xchar() {return ((In) In.val().obj()).xchar();} @@ -386,6 +395,29 @@ class wl implements Runnable { } return A.cdr(); } + + // runtime dispatch + class MethodComparator implements Comparator<Method> { + public int compare(Method l, Method 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 MethodComparator methodComparator = new MethodComparator(); + boolean isApplicable(Method 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; + } Any applyO(Any E, Any O) { // 'obj 'meth [arg ...] Any I = E.cdr(); Any F = eval(I.car()); @@ -405,11 +437,25 @@ class wl implements Runnable { 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); + //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; + } + if(null == m) err(E, "No applicable method"); Object r = m.invoke(o, aa); Z = mkObj(r); - } catch(NoSuchMethodException e) { - err(E, "NoSuchMethodException"); } catch(IllegalAccessException e) { err(E, "IllegalAccessException"); } catch(InvocationTargetException e) { @@ -489,6 +535,9 @@ class wl implements Runnable { return z; } + final wl Wl = this; + final BlockingQueue<Any> Que = new LinkedBlockingQueue<Any>(); + public wl() { Sd.put("NIL", NIL); Sd.put("T", T); @@ -500,6 +549,7 @@ class wl implements Runnable { Sd.put("*Out", Out); Sd.put("*Env", Env); Sd.put("*Stk", Stk); + Sd.put("*Scl", Scl); Sd.put("java.lang.Class", mkIsym("java.lang.Class", mkObj(Class.class))); fn("run", new Fn() {public Any fn(Any E) { @@ -627,6 +677,10 @@ class wl implements Runnable { } return mkObj(Z); }}); + fn("str", new Fn() {public Any fn(Any E) { // TODO + Any I = E.cdr(); + return mkObj(str(eval(I.car()))); + }}); fn("def", new Fn() {public Any fn(Any E) { Any X = E.cdr(); Any A = eval(X.car()); @@ -640,7 +694,7 @@ class wl implements Runnable { Any X = eval(E.cdr().car()); if(X.isCons()) Z = X.car(); else if(X.isSym()) Z = X.val(); - else if(X.isObj()) Z = X; + //else if(X.isObj()) Z = X; else err(E, "Don't know how to val"); return Z; }}); @@ -665,6 +719,30 @@ class wl implements Runnable { } else err(E, "Don't know how to pop"); return Z; }}); + fn("push", new Fn() {public Any fn(Any E) { + Any Z = NIL; + Any I = E.cdr(); + Any K = eval(I.car()); + I = I.cdr(); + if(K.isCons()) { + Any V = K.car(); + while(I.isCons()) { + Z = eval(I.car()); + I = I.cdr(); + V = mkCons(Z, V); + } + K.car(V); + } else if(K.isSym()) { + Any V = K.val(); + while(I.isCons()) { + Z = eval(I.car()); + I = I.cdr(); + V = mkCons(Z, V); + } + K.val(V); + } else err(E, "Don't know how to push"); + return Z; + }}); fn("con", new Fn() {public Any fn(Any E) { Any I = E.cdr(); Any L = eval(I.car()); @@ -817,6 +895,7 @@ class wl implements Runnable { 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); Z = mkObj(r); @@ -851,8 +930,63 @@ class wl implements Runnable { } return Z; }}); + fn("jproxy", new Fn() {public Any fn(Any E) { // jproxy 'flg 'fn ['jcls...] + Any Z = NIL; + Any I = E.cdr(); + final Any A = eval(I.car()); + I = I.cdr(); + final Any F = eval(I.car()); + I = I.cdr(); + ArrayList<Class> a = new ArrayList(); + while(NIL != I) { + a.add((Class) eval(I.car()).obj()); + I = I.cdr(); + } + ClassLoader l = this.getClass().getClassLoader(); + Class[] c = (Class[]) a.toArray(new Class[a.size()]); + InvocationHandler h = new InvocationHandler() { + public Object invoke(Object p, Method m, Object[] a) + throws Throwable { + Any X = NIL; + if(null != a) + for(int i = a.length - 1; 0 <= i; i--) + X = mkCons(mkObj(a[i]), X); + //X = mkCons(mkObj(p), X); + //System.out.println(p); + X = mkCons(mkObj(m.getName()), X); + X = mkCons(F, X); + Any Z = NIL; + if(NIL == A) Z = eval(X); + else Que.offer(X); + return Z.isObj() ? Z.obj() : null; + } + }; + Object r = Proxy.newProxyInstance(l, c, h); + Z = mkObj(r); + return Z; + }}); + fn("wait", new Fn() {public Any fn(Any E) { // wait ['cnt] . prg + Any Z = NIL; + // TODO poll from Que with timeout cnt unless run(prg) + //Any I = E.cdr(); + try { + while(true) { + Any X = Que.take(); + Z = eval(X); + } + } catch(InterruptedException e) { + dbg("InterruptedException"); + } + return Z; + }}); + fn("bye", new Fn() {public Any fn(Any E) { // bye ['cnt] + Any I = E.cdr(); + Any Z = eval(I.car()); + System.exit(Z.isOnum() ? ((BigInteger) Z.obj()).intValue() : 0); + return Z; + }}); } - + void print(Any E) { PrintStream S = (PrintStream) Out.val().obj(); if(E.isCons()) { @@ -947,6 +1081,3 @@ class wl implements Runnable { //(new Thread(new wl())).start(); } } - -// // 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);};