diff --git a/src/jvm/clojure/lang/Reflector.java b/src/jvm/clojure/lang/Reflector.java index e47c264..95a8b6d 100644 --- a/src/jvm/clojure/lang/Reflector.java +++ b/src/jvm/clojure/lang/Reflector.java @@ -18,6 +18,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; public class Reflector{ @@ -26,7 +27,7 @@ public static Object invokeInstanceMethod(Object target, String methodName, Obje try { Class c = target.getClass(); - List methods = getMethods(c, args.length, methodName, false); + List methods = getMethods(c, methodName, false); return invokeMatchingMethod(methodName, methods, target, args); } catch(Exception e) @@ -43,19 +44,27 @@ private static String noMethodReport(String methodName, Object target){ return "No matching method found: " + methodName + (target==null?"":" for " + target.getClass()); } + +private static String arityMismatchReport(String methodName, Object target) { + return methodName + (target == null?"": " for " + target.getClass()); +} + +private static String parameterTypeMismatchReport(String methodName, Object target) { + StringBuilder builder = new StringBuilder(); + builder.append("No matching method found: ").append(methodName).append((target == null?"": " for " + target.getClass())) + .append(" because the parameter types did not match."); + return builder.toString(); +} + static Object invokeMatchingMethod(String methodName, List methods, Object target, Object[] args) { Method m = null; Object[] boxedArgs = null; + boolean arityMatch = false; if(methods.isEmpty()) { throw new IllegalArgumentException(noMethodReport(methodName,target)); } - else if(methods.size() == 1) - { - m = (Method) methods.get(0); - boxedArgs = boxArgs(m.getParameterTypes(), args); - } else //overloaded w/same arity { Method foundm = null; @@ -64,6 +73,9 @@ static Object invokeMatchingMethod(String methodName, List methods, Object targe m = (Method) i.next(); Class[] params = m.getParameterTypes(); + if (params.length == args.length) { + arityMatch = true; + } if(isCongruent(params, args)) { if(foundm == null || Compiler.subsumes(params, foundm.getParameterTypes())) @@ -75,8 +87,15 @@ static Object invokeMatchingMethod(String methodName, List methods, Object targe } m = foundm; } - if(m == null) - throw new IllegalArgumentException(noMethodReport(methodName,target)); + if(m == null) { + if (!arityMatch) { + throw new ArityException(args.length, arityMismatchReport(methodName, target)); + } else { + throw new IllegalArgumentException(parameterTypeMismatchReport(methodName, target)); + } + + } + if(!Modifier.isPublic(m.getDeclaringClass().getModifiers())) { @@ -371,16 +390,15 @@ static public Field getField(Class c, String name, boolean getStatics){ return null; } -static public List getMethods(Class c, int arity, String name, boolean getStatics){ +static public List getMethods(Class c, String name, boolean getStatics){ Method[] allmethods = c.getMethods(); - ArrayList methods = new ArrayList(); - ArrayList bridgeMethods = new ArrayList(); + LinkedList methods = new LinkedList(); + LinkedList bridgeMethods = new LinkedList(); for(int i = 0; i < allmethods.length; i++) { Method method = allmethods[i]; if(name.equals(method.getName()) - && Modifier.isStatic(method.getModifiers()) == getStatics - && method.getParameterTypes().length == arity) + && Modifier.isStatic(method.getModifiers()) == getStatics) { try { @@ -413,8 +431,7 @@ static public List getMethods(Class c, int arity, String name, boolean getStatic for(int i = 0; i < allmethods.length; i++) { if(name.equals(allmethods[i].getName()) - && Modifier.isStatic(allmethods[i].getModifiers()) == getStatics - && allmethods[i].getParameterTypes().length == arity) + && Modifier.isStatic(allmethods[i].getModifiers()) == getStatics) { methods.add(allmethods[i]); } @@ -423,6 +440,16 @@ static public List getMethods(Class c, int arity, String name, boolean getStatic return methods; } +static public List getMethods(Class c, int arity, String name, boolean getStatics){ + List methods = getMethods(c, name, getStatics); + for(Iterator i = methods.iterator(); i.hasNext();) { + Method method = (Method) i.next(); + if (method.getParameterTypes().length != arity) { + i.remove(); + } + } + return methods; +} static Object boxArg(Class paramType, Object arg){ if(!paramType.isPrimitive())