diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-01-03 18:32:22 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-01-03 18:32:22 +0000 |
commit | 368c7989e33ecb50b59de48a71fe3c96c6b0c483 (patch) | |
tree | 0d74ed0db4b5bd66ea79c65d1084874a3afff306 /src | |
parent | 3d14de92f6d7ce58b9f56f9e6112ddb8c5721a38 (diff) |
same arity overload resolution in ctors and methods
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 60 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 3 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Reflector.java | 36 |
4 files changed, 78 insertions, 23 deletions
diff --git a/src/boot.clj b/src/boot.clj index c1df6230..9e71bb93 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -908,7 +908,7 @@ (. q (put (f (first job)))) (recur)))) tasks (doseq dnu (map (fn [task] - (. exec (submit task))) + (. exec (submit #^java.util.concurrent.Callable task))) (replicate nthreads produce))) consume (fn [] (if (sync nil (and (or @todo (pos? @out)) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 3df045ce..d9567c31 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -67,6 +67,7 @@ static final Symbol HASHMAP = Symbol.create("clojure", "hash-map"); static final Symbol VECTOR = Symbol.create("clojure", "vector"); static final Symbol _AMP_ = Symbol.create("&"); +static final Symbol ISEQ = Symbol.create("clojure.lang.ISeq"); //static final Symbol IMPORT = Symbol.create("import"); //static final Symbol USE = Symbol.create("use"); @@ -867,7 +868,17 @@ static class InstanceMethodExpr extends MethodExpr{ method = null; //throw new IllegalArgumentException("No matching method found"); else - method = (java.lang.reflect.Method) ((methods.size() == 1) ? methods.get(0) : null); + { + int methodidx = 0; + if(methods.size() > 1) + { + ArrayList<Class[]> params = new ArrayList(); + for(int i = 0; i < methods.size(); i++) + params.add(((java.lang.reflect.Method) methods.get(i)).getParameterTypes()); + methodidx = getMatchingParams(params, args); + } + method = (java.lang.reflect.Method) (methodidx >= 0 ? methods.get(methodidx) : null); + } } else method = null; @@ -928,7 +939,7 @@ static class StaticMethodExpr extends MethodExpr{ public StaticMethodExpr(int line, String className, String methodName, IPersistentVector args) - throws ClassNotFoundException{ + throws Exception{ this.className = className; this.methodName = methodName; this.args = args; @@ -937,7 +948,16 @@ static class StaticMethodExpr extends MethodExpr{ List methods = Reflector.getMethods(Class.forName(className), args.count(), methodName, true); if(methods.isEmpty()) throw new IllegalArgumentException("No matching method: " + methodName); - method = (java.lang.reflect.Method) ((methods.size() == 1) ? methods.get(0) : null); + + int methodidx = 0; + if(methods.size() > 1) + { + ArrayList<Class[]> params = new ArrayList(); + for(int i = 0; i < methods.size(); i++) + params.add(((java.lang.reflect.Method) methods.get(i)).getParameterTypes()); + methodidx = getMatchingParams(params, args); + } + method = (java.lang.reflect.Method) (methodidx >= 0 ? methods.get(methodidx) : null); } public Object eval() throws Exception{ @@ -1525,6 +1545,24 @@ static class ClassExpr implements Expr{ } } +static int getMatchingParams(ArrayList<Class[]> paramlists, IPersistentVector argexprs) throws Exception{ + //presumes matching lengths + for(int i = 0; i < paramlists.size(); i++) + { + boolean match = true; + ISeq aseq = argexprs.seq(); + for(int p = 0; match && p < argexprs.count() && aseq != null; ++p, aseq = aseq.rest()) + { + Expr arg = (Expr) aseq.first(); + Class aclass = arg.hasJavaClass()? arg.getJavaClass():Object.class; + match = Reflector.paramArgTypeMatch(paramlists.get(i)[p], aclass); + } + if(match) + return i; + } + return -1; +} + static class NewExpr implements Expr{ final String className; final IPersistentVector args; @@ -1535,22 +1573,32 @@ static class NewExpr implements Expr{ final static Method forNameMethod = Method.getMethod("Class forName(String)"); - public NewExpr(String className, IPersistentVector args) throws ClassNotFoundException{ + public NewExpr(String className, IPersistentVector args) throws Exception{ this.args = args; this.className = className; this.c = Class.forName(className); Constructor[] allctors = c.getConstructors(); ArrayList ctors = new ArrayList(); + ArrayList<Class[]> params = new ArrayList(); for(int i = 0; i < allctors.length; i++) { Constructor ctor = allctors[i]; if(ctor.getParameterTypes().length == args.count()) + { ctors.add(ctor); + params.add(ctor.getParameterTypes()); + } } if(ctors.isEmpty()) throw new IllegalArgumentException("No matching ctor found"); - this.ctor = (ctors.size() == 1) ? (Constructor) ctors.get(0) : null; + int ctoridx = 0; + if(ctors.size() > 1) + { + ctoridx = getMatchingParams(params, args); + } + + this.ctor = ctoridx >= 0 ? (Constructor) ctors.get(ctoridx) : null; } public Object eval() throws Exception{ @@ -2415,7 +2463,7 @@ static class FnMethod{ else { - LocalBinding lb = registerLocal(p, tagOf(p), null); + LocalBinding lb = registerLocal(p, state==PSTATE.REST?ISEQ:tagOf(p), null); argLocals = argLocals.cons(lb); switch(state) { diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 48a6b71f..9f517012 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -162,6 +162,9 @@ static public final Object[] EMPTY_ARRAY = new Object[]{}; //static public final Character[] chars; static AtomicInteger id = new AtomicInteger(1); +static{ +OUT.setTag(Symbol.create("java.io.PrintStream")); +} //static // { // chars = new Character[256]; diff --git a/src/jvm/clojure/lang/Reflector.java b/src/jvm/clojure/lang/Reflector.java index 3c3239ab..32560cdb 100644 --- a/src/jvm/clojure/lang/Reflector.java +++ b/src/jvm/clojure/lang/Reflector.java @@ -288,21 +288,25 @@ static Object[] boxArgs(Class[] params, Object[] args){ return ret; } -static public boolean primBoxTypeMatch(Class primType, Class boxType){ - if(primType == int.class) - return boxType == Integer.class || boxType == FixNum.class; - else if(primType == float.class) - return boxType == Float.class; - else if(primType == double.class) - return boxType == Double.class || boxType == DoubleNum.class; - else if(primType == long.class) - return boxType == Long.class || boxType == BigNum.class; - else if(primType == char.class) - return boxType == Character.class; - else if(primType == short.class) - return boxType == Short.class; - else if(primType == byte.class) - return boxType == Byte.class; +static public boolean paramArgTypeMatch(Class paramType, Class argType){ + if(paramType == argType || paramType.isAssignableFrom(argType)) + return true; + if(paramType == int.class) + return argType == Integer.class || argType == FixNum.class; + else if(paramType == float.class) + return argType == Float.class; + else if(paramType == double.class) + return argType == Double.class || argType == DoubleNum.class; + else if(paramType == long.class) + return argType == Long.class || argType == BigNum.class; + else if(paramType == char.class) + return argType == Character.class; + else if(paramType == short.class) + return argType == Short.class; + else if(paramType == byte.class) + return argType == Byte.class; + else if(paramType == boolean.class) + return argType == Boolean.class; return false; } @@ -327,7 +331,7 @@ static boolean isCongruent(Class[] params, Object[] args){ if(arg == null) ret = false; else - ret = primBoxTypeMatch(paramType, argType); + ret = paramArgTypeMatch(paramType, argType); } else { |