Changeset 13259 for trunk/abcl/src/org


Ignore:
Timestamp:
04/02/11 21:56:04 (10 years ago)
Author:
astalla
Message:

Java method resolution algorithm used by JCALL extracted to a method and exposed as the Lisp function JAVA:JRESOLVE-METHOD

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/FaslClassLoader.java

    r13149 r13259  
    106106
    107107    public LispObject loadFunction(int fnNumber) {
     108        //Function name is fnIndex + 1
     109        String name = baseName + "_" + (fnNumber + 1);
    108110        try {
    109             //Function name is fnIndex + 1
    110             String name = baseName + "_" + (fnNumber + 1);
    111111            Function f = (Function) loadClass(name).newInstance();
    112112            f.setClassBytes(getFunctionClassBytes(name));
    113113            return f;
    114         } catch(Exception e) {
     114        } catch(Throwable e) {
    115115            if(e instanceof ControlTransfer) { throw (ControlTransfer) e; }
    116116            Debug.trace(e);
    117             return error(new LispError("Compiled function can't be loaded: " + baseName + "_" + (fnNumber + 1) + " " + Symbol.LOAD_TRUENAME.symbolValue()));
     117            return error(new LispError("Compiled function can't be loaded: " + name + " from " + Symbol.LOAD_TRUENAME.symbolValue()));
    118118        }
    119119    }
  • trunk/abcl/src/org/armedbear/lisp/Java.java

    r13221 r13259  
    6363    @DocString(name="ensure-java-object", args="obj",
    6464    doc="Ensures OBJ is wrapped in a JAVA-OBJECT, wrapping it if necessary.")
    65     private static final class pf_ensure_java_object extends Primitive 
    66     {
    67         pf_ensure_java_object() 
     65    private static final class pf_ensure_java_object extends Primitive
     66    {
     67        pf_ensure_java_object()
    6868        {
    6969            super("ensure-java-object", PACKAGE_JAVA, true);
     
    7272        @Override
    7373        public LispObject execute(LispObject obj) {
    74       return obj instanceof JavaObject ? obj : new JavaObject(obj);
     74            return obj instanceof JavaObject ? obj : new JavaObject(obj);
    7575        }
    7676    };
     
    8181    doc="Registers the Java Throwable named by the symbol EXCEPTION-NAME as the condition " +
    8282        "designated by CONDITION-SYMBOL.  Returns T if successful, NIL if not.")
    83     private static final class pf_register_java_exception extends Primitive 
    84     {
    85         pf_register_java_exception() 
     83    private static final class pf_register_java_exception extends Primitive
     84    {
     85        pf_register_java_exception()
    8686        {
    8787            super("register-java-exception", PACKAGE_JAVA, true);
     
    109109    private static final class pf_unregister_java_exception extends Primitive
    110110    {
    111         pf_unregister_java_exception() 
     111        pf_unregister_java_exception()
    112112        {
    113113            super("unregister-java-exception", PACKAGE_JAVA, true);
     
    448448                    String methodName = methodRef.getStringValue();
    449449                    Method[] methods = c.getMethods();
    450         List<Method> staticMethods = new ArrayList<Method>();
     450                    List<Method> staticMethods = new ArrayList<Method>();
    451451                    int argCount = args.length - 2;
    452         for(Method m1 : methods) {
    453       if(Modifier.isStatic(m1.getModifiers())) {
    454           staticMethods.add(m1);
    455       }
    456         }
    457         if(staticMethods.size() > 0) {
    458       m = findMethod(staticMethods.toArray(new Method[staticMethods.size()]), methodName, args);
    459         }
     452                    for(Method m1 : methods) {
     453                        if(Modifier.isStatic(m1.getModifiers())) {
     454                            staticMethods.add(m1);
     455                        }
     456                    }
     457                    if(staticMethods.size() > 0) {
     458                        m = findMethod(staticMethods.toArray(new Method[staticMethods.size()]), methodName, args, 2);
     459                    }
    460460                    if (m == null)
    461461                        error(new LispError("no such method"));
     
    749749    };
    750750
    751     /** 
     751    /**
    752752     * Does no type conversion. The result of the call is simply wrapped in a
    753753     *   JavaObject.
     
    771771    };
    772772
     773    private static final Primitive JRESOLVE_METHOD = new pf_jresolve_method();
     774    @DocString(name="jresolve_method", args="method-name instance &rest args",
     775    doc="Finds the most specific Java method METHOD-NAME on INSTANCE " +
     776        "applicable to arguments ARGS. Returns NIL if no suitable method is " +
     777        "found. The algorithm used for resolution is the same used by JCALL " +
     778        "when it is called with a string as the first parameter (METHOD-REF).")
     779    private static final class pf_jresolve_method extends Primitive {
     780
     781        pf_jresolve_method() {
     782            super(Symbol.JRESOLVE_METHOD);
     783        }
     784
     785        @Override
     786        public LispObject execute(LispObject[] args) {
     787            if (args.length < 2) {
     788                error(new WrongNumberOfArgumentsException(this, 2));
     789            }
     790            final LispObject methodArg = args[0];
     791            final LispObject instanceArg = args[1];
     792            final Object instance;
     793            Class<?> intendedClass = null;
     794            if (instanceArg instanceof AbstractString) {
     795                instance = instanceArg.getStringValue();
     796            } else if (instanceArg instanceof JavaObject) {
     797                JavaObject jobj = ((JavaObject)instanceArg);
     798                instance = jobj.getObject();
     799                intendedClass = jobj.getIntendedClass();
     800            } else {
     801                instance = instanceArg.javaInstance();
     802            }
     803            if(instance == null) {
     804                return error(new ProgramError("JRESOLVE-METHOD: instance must not be null"));
     805            }
     806            String methodName = methodArg.getStringValue();
     807            Object[] methodArgs = translateMethodArguments(args, 2);
     808            Method method = findMethod(instance, intendedClass, methodName, methodArgs);
     809            if (method != null) {
     810                return JavaObject.getInstance(method);
     811            } else {
     812                return NIL;
     813            }
     814        }
     815    };
     816
    773817    static LispObject jcall(Primitive fun, LispObject[] args, boolean translate)
    774818
    775819    {
    776820        if (args.length < 2)
    777             error(new WrongNumberOfArgumentsException(fun));
     821            error(new WrongNumberOfArgumentsException(fun, 2));
    778822        try {
    779       final LispObject methodArg = args[0];
    780       final LispObject instanceArg = args[1];
    781       final Object instance;
    782       Class<?> intendedClass = null;
    783       if (instanceArg instanceof AbstractString) {
    784     instance = instanceArg.getStringValue();
    785       } else if (instanceArg instanceof JavaObject) {
    786     JavaObject jobj = ((JavaObject)instanceArg);
    787     instance = jobj.getObject();
    788     intendedClass = jobj.getIntendedClass();
    789       } else {
    790     instance = instanceArg.javaInstance();
    791       }
    792       if(instance == null) {
    793     throw new NullPointerException(); //Handled below
    794       }
     823            final LispObject methodArg = args[0];
     824            final LispObject instanceArg = args[1];
     825            final Object instance;
    795826            Method method;
    796       Object[] methodArgs;
     827            Object[] methodArgs;
     828            Class<?> intendedClass = null;
     829            if (instanceArg instanceof AbstractString) {
     830                instance = instanceArg.getStringValue();
     831            } else if (instanceArg instanceof JavaObject) {
     832                JavaObject jobj = ((JavaObject)instanceArg);
     833                instance = jobj.getObject();
     834                intendedClass = jobj.getIntendedClass();
     835            } else {
     836                instance = instanceArg.javaInstance();
     837            }
     838            if(instance == null) {
     839                throw new NullPointerException(); //Handled below
     840            }
    797841            if (methodArg instanceof AbstractString) {
    798     methodArgs = translateMethodArguments(args, 2);
    799842                String methodName = methodArg.getStringValue();
    800     if(intendedClass == null) {
    801         intendedClass = instance.getClass();
    802     }
    803                 method = findMethod(intendedClass, methodName, methodArgs);
    804     Class actualClass = null;
    805     if(method == null) {       
    806         actualClass = instance.getClass();
    807         if(intendedClass != actualClass &&
    808            Modifier.isPublic(actualClass.getModifiers())) {
    809       method = findMethod(actualClass, methodName, methodArgs);
    810         }
    811     }
    812     if (method == null) {
    813         String classes = intendedClass.getName();
    814         if(actualClass != null && actualClass != intendedClass) {
    815       classes += " or " + actualClass.getName();
    816         }
    817         throw new NoSuchMethodException("No applicable method named " + methodName + " found in " + classes);
    818     }
    819 
     843                methodArgs = translateMethodArguments(args, 2);
     844                method = findMethod(instance, intendedClass, methodName, methodArgs);
     845                if (method == null) {
     846                    String classes = intendedClass.getName();
     847                    Class<?> actualClass = instance.getClass();
     848                    if(actualClass != intendedClass) {
     849                        classes += " or " + actualClass.getName();
     850                    }
     851                    throw new NoSuchMethodException("No applicable method named " + methodName + " found in " + classes);
     852                }
    820853            } else
    821854                method = (Method) JavaObject.getObject(methodArg);
     
    834867            return JavaObject.getInstance(method.invoke(instance, methodArgs),
    835868                                          translate,
    836             method.getReturnType());
     869                                          method.getReturnType());
    837870        }
    838871        catch (ControlTransfer t) {
     
    876909
    877910    private static Method findMethod(Method[] methods, String methodName, Object[] javaArgs) {
    878   int argCount = javaArgs.length;
     911        int argCount = javaArgs.length;
    879912        Method result = null;
    880913        for (int i = methods.length; i-- > 0;) {
     
    897930    }
    898931
     932    private static Method findMethod(Object instance, Class<?> intendedClass, String methodName, Object[] methodArgs) {
     933        if(intendedClass == null) {
     934            intendedClass = instance.getClass();
     935        }
     936        Method method = findMethod(intendedClass, methodName, methodArgs);
     937        Class actualClass = null;
     938        if(method == null) {
     939            actualClass = instance.getClass();
     940            if(intendedClass != actualClass &&
     941               Modifier.isPublic(actualClass.getModifiers())) {
     942                method = findMethod(actualClass, methodName, methodArgs);
     943            }
     944        }
     945        return method;
     946    }
     947
    899948    private static Method findMethod(Class<?> c, String methodName, Object[] javaArgs) {
    900949        Method[] methods = c.getMethods();
    901   return findMethod(methods, methodName, javaArgs);
    902     }
    903 
    904     private static Method findMethod(Class<?> c, String methodName, LispObject[] args) {
    905         Object[] javaArgs = translateMethodArguments(args, 2);
    906   return findMethod(c, methodName, javaArgs);
    907     }
    908 
    909     private static Method findMethod(Method[] methods, String methodName, LispObject[] args) {
    910         Object[] javaArgs = translateMethodArguments(args, 2);
    911   return findMethod(methods, methodName, javaArgs);
     950        return findMethod(methods, methodName, javaArgs);
     951    }
     952
     953    private static Method findMethod(Class<?> c, String methodName, LispObject[] args, int offset) {
     954        Object[] javaArgs = translateMethodArguments(args, offset);
     955        return findMethod(c, methodName, javaArgs);
     956    }
     957
     958    private static Method findMethod(Method[] methods, String methodName, LispObject[] args, int offset) {
     959        Object[] javaArgs = translateMethodArguments(args, offset);
     960        return findMethod(methods, methodName, javaArgs);
    912961    }
    913962
    914963    static Constructor findConstructor(Class<?> c, LispObject[] args) throws NoSuchMethodException {
    915   int argCount = args.length - 1;
     964        int argCount = args.length - 1;
    916965        Object[] javaArgs = translateMethodArguments(args, 1);
    917966        Constructor[] ctors = c.getConstructors();
  • trunk/abcl/src/org/armedbear/lisp/Symbol.java

    r13246 r13259  
    29712971    PACKAGE_JAVA.addExternalSymbol("JAVA-OBJECT");
    29722972  public static final Symbol JAVA_CLASS =
    2973       PACKAGE_JAVA.addExternalSymbol("JAVA-CLASS");
     2973      PACKAGE_JAVA.addExternalSymbol("JAVA-CLASS");
    29742974  public static final Symbol JCALL =
    29752975    PACKAGE_JAVA.addExternalSymbol("JCALL");
     
    29842984  public static final Symbol JMETHOD_RETURN_TYPE =
    29852985    PACKAGE_JAVA.addExternalSymbol("JMETHOD-RETURN-TYPE");
     2986  public static final Symbol JRESOLVE_METHOD =
     2987    PACKAGE_JAVA.addExternalSymbol("JRESOLVE-METHOD");
    29862988
    29872989  // External symbols in SYSTEM package.
  • trunk/abcl/src/org/armedbear/lisp/WrongNumberOfArgumentsException.java

    r12431 r13259  
    4343
    4444    public WrongNumberOfArgumentsException(Operator operator) {
    45   this(operator, -1);
     45        this(operator, -1);
    4646    }
    4747
Note: See TracChangeset for help on using the changeset viewer.