Java method resolution algorithm used by JCALL extracted to a method and...

Java method resolution algorithm used by JCALL extracted to a method and exposed as the Lisp function JAVA:JRESOLVE-METHOD
parent 1006b491
......@@ -13,7 +13,7 @@
</parent>
<groupId>org.armedbear.lisp</groupId>
<artifactId>abcl</artifactId>
<version>0.25.0-SNAPSHOT</version>
<version>0.26.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ABCL - Armed Bear Common Lisp</name>
<description>Common Lisp implementation running on the JVM</description>
......
......@@ -105,16 +105,16 @@ public class FaslClassLoader extends JavaClassLoader {
}
public LispObject loadFunction(int fnNumber) {
try {
//Function name is fnIndex + 1
String name = baseName + "_" + (fnNumber + 1);
try {
Function f = (Function) loadClass(name).newInstance();
f.setClassBytes(getFunctionClassBytes(name));
return f;
} catch(Exception e) {
} catch(Throwable e) {
if(e instanceof ControlTransfer) { throw (ControlTransfer) e; }
Debug.trace(e);
return error(new LispError("Compiled function can't be loaded: " + baseName + "_" + (fnNumber + 1) + " " + Symbol.LOAD_TRUENAME.symbolValue()));
return error(new LispError("Compiled function can't be loaded: " + name + " from " + Symbol.LOAD_TRUENAME.symbolValue()));
}
}
......
......@@ -455,7 +455,7 @@ public final class Java
}
}
if(staticMethods.size() > 0) {
m = findMethod(staticMethods.toArray(new Method[staticMethods.size()]), methodName, args);
m = findMethod(staticMethods.toArray(new Method[staticMethods.size()]), methodName, args, 2);
}
if (m == null)
error(new LispError("no such method"));
......@@ -770,15 +770,61 @@ public final class Java
}
};
private static final Primitive JRESOLVE_METHOD = new pf_jresolve_method();
@DocString(name="jresolve_method", args="method-name instance &rest args",
doc="Finds the most specific Java method METHOD-NAME on INSTANCE " +
"applicable to arguments ARGS. Returns NIL if no suitable method is " +
"found. The algorithm used for resolution is the same used by JCALL " +
"when it is called with a string as the first parameter (METHOD-REF).")
private static final class pf_jresolve_method extends Primitive {
pf_jresolve_method() {
super(Symbol.JRESOLVE_METHOD);
}
@Override
public LispObject execute(LispObject[] args) {
if (args.length < 2) {
error(new WrongNumberOfArgumentsException(this, 2));
}
final LispObject methodArg = args[0];
final LispObject instanceArg = args[1];
final Object instance;
Class<?> intendedClass = null;
if (instanceArg instanceof AbstractString) {
instance = instanceArg.getStringValue();
} else if (instanceArg instanceof JavaObject) {
JavaObject jobj = ((JavaObject)instanceArg);
instance = jobj.getObject();
intendedClass = jobj.getIntendedClass();
} else {
instance = instanceArg.javaInstance();
}
if(instance == null) {
return error(new ProgramError("JRESOLVE-METHOD: instance must not be null"));
}
String methodName = methodArg.getStringValue();
Object[] methodArgs = translateMethodArguments(args, 2);
Method method = findMethod(instance, intendedClass, methodName, methodArgs);
if (method != null) {
return JavaObject.getInstance(method);
} else {
return NIL;
}
}
};
static LispObject jcall(Primitive fun, LispObject[] args, boolean translate)
{
if (args.length < 2)
error(new WrongNumberOfArgumentsException(fun));
error(new WrongNumberOfArgumentsException(fun, 2));
try {
final LispObject methodArg = args[0];
final LispObject instanceArg = args[1];
final Object instance;
Method method;
Object[] methodArgs;
Class<?> intendedClass = null;
if (instanceArg instanceof AbstractString) {
instance = instanceArg.getStringValue();
......@@ -792,31 +838,18 @@ public final class Java
if(instance == null) {
throw new NullPointerException(); //Handled below
}
Method method;
Object[] methodArgs;
if (methodArg instanceof AbstractString) {
methodArgs = translateMethodArguments(args, 2);
String methodName = methodArg.getStringValue();
if(intendedClass == null) {
intendedClass = instance.getClass();
}
method = findMethod(intendedClass, methodName, methodArgs);
Class actualClass = null;
if(method == null) {
actualClass = instance.getClass();
if(intendedClass != actualClass &&
Modifier.isPublic(actualClass.getModifiers())) {
method = findMethod(actualClass, methodName, methodArgs);
}
}
methodArgs = translateMethodArguments(args, 2);
method = findMethod(instance, intendedClass, methodName, methodArgs);
if (method == null) {
String classes = intendedClass.getName();
if(actualClass != null && actualClass != intendedClass) {
Class<?> actualClass = instance.getClass();
if(actualClass != intendedClass) {
classes += " or " + actualClass.getName();
}
throw new NoSuchMethodException("No applicable method named " + methodName + " found in " + classes);
}
} else
method = (Method) JavaObject.getObject(methodArg);
Class<?>[] argTypes = (Class<?>[])method.getParameterTypes();
......@@ -896,18 +929,34 @@ public final class Java
return result;
}
private static Method findMethod(Object instance, Class<?> intendedClass, String methodName, Object[] methodArgs) {
if(intendedClass == null) {
intendedClass = instance.getClass();
}
Method method = findMethod(intendedClass, methodName, methodArgs);
Class actualClass = null;
if(method == null) {
actualClass = instance.getClass();
if(intendedClass != actualClass &&
Modifier.isPublic(actualClass.getModifiers())) {
method = findMethod(actualClass, methodName, methodArgs);
}
}
return method;
}
private static Method findMethod(Class<?> c, String methodName, Object[] javaArgs) {
Method[] methods = c.getMethods();
return findMethod(methods, methodName, javaArgs);
}
private static Method findMethod(Class<?> c, String methodName, LispObject[] args) {
Object[] javaArgs = translateMethodArguments(args, 2);
private static Method findMethod(Class<?> c, String methodName, LispObject[] args, int offset) {
Object[] javaArgs = translateMethodArguments(args, offset);
return findMethod(c, methodName, javaArgs);
}
private static Method findMethod(Method[] methods, String methodName, LispObject[] args) {
Object[] javaArgs = translateMethodArguments(args, 2);
private static Method findMethod(Method[] methods, String methodName, LispObject[] args, int offset) {
Object[] javaArgs = translateMethodArguments(args, offset);
return findMethod(methods, methodName, javaArgs);
}
......
......@@ -2983,6 +2983,8 @@ public class Symbol extends LispObject implements java.io.Serializable
PACKAGE_JAVA.addExternalSymbol("JCLASS-OF");
public static final Symbol JMETHOD_RETURN_TYPE =
PACKAGE_JAVA.addExternalSymbol("JMETHOD-RETURN-TYPE");
public static final Symbol JRESOLVE_METHOD =
PACKAGE_JAVA.addExternalSymbol("JRESOLVE-METHOD");
// External symbols in SYSTEM package.
public static final Symbol _ENABLE_AUTOCOMPILE_ =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment