Improve varargs handlnig in luajava bindings.
This commit is contained in:
@@ -36,7 +36,7 @@ public class CoerceJavaToLua {
|
|||||||
public LuaValue coerce( Object javaValue );
|
public LuaValue coerce( Object javaValue );
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Map COERCIONS = new HashMap();
|
static final Map COERCIONS = new HashMap();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Coercion boolCoercion = new Coercion() {
|
Coercion boolCoercion = new Coercion() {
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ public class CoerceLuaToJava {
|
|||||||
public int score( int paramType );
|
public int score( int paramType );
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Map COERCIONS = new HashMap();
|
static final Map COERCIONS = new HashMap();
|
||||||
private static Coercion OBJECT_COERCION;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Coercion boolCoercion = new Coercion() {
|
Coercion boolCoercion = new Coercion() {
|
||||||
@@ -232,7 +231,7 @@ public class CoerceLuaToJava {
|
|||||||
|
|
||||||
|
|
||||||
/** Score a single parameter, including array handling */
|
/** Score a single parameter, including array handling */
|
||||||
private static int scoreParam(int paramType, Class c) {
|
static int scoreParam(int paramType, Class c) {
|
||||||
if ( paramType == LuaValue.TUSERDATA && !c.isArray() )
|
if ( paramType == LuaValue.TUSERDATA && !c.isArray() )
|
||||||
return 0;
|
return 0;
|
||||||
Coercion co = (Coercion) COERCIONS.get( c );
|
Coercion co = (Coercion) COERCIONS.get( c );
|
||||||
@@ -277,11 +276,23 @@ public class CoerceLuaToJava {
|
|||||||
throw new LuaError("no coercion found for "+a.getClass()+" to "+c);
|
throw new LuaError("no coercion found for "+a.getClass()+" to "+c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object[] coerceArgs(Varargs suppliedArgs, Class[] parameterTypes) {
|
static Object[] coerceArgs(Varargs suppliedArgs, Class[] parameterTypes, boolean isvarargs) {
|
||||||
|
int nsupplied = suppliedArgs.narg();
|
||||||
int n = parameterTypes.length;
|
int n = parameterTypes.length;
|
||||||
|
int nplain = Math.min(isvarargs? n-1: n, nsupplied);
|
||||||
Object[] args = new Object[n];
|
Object[] args = new Object[n];
|
||||||
for ( int i=0; i<n; i++ )
|
for ( int i=0; i<nplain; i++ )
|
||||||
args[i] = coerceArg( suppliedArgs.arg(i+1), parameterTypes[i] );
|
args[i] = coerceArg( suppliedArgs.arg(i+1), parameterTypes[i] );
|
||||||
|
if ( isvarargs ) {
|
||||||
|
int nvar = Math.max(0, nsupplied - nplain);
|
||||||
|
Class typevar = parameterTypes[n-1].getComponentType();
|
||||||
|
Object array = Array.newInstance(typevar, nvar);
|
||||||
|
for ( int index=0; index<nvar; index++ ) {
|
||||||
|
Object value = coerceArg( suppliedArgs.arg(nplain+index+1), typevar );
|
||||||
|
Array.set(array, index, value);
|
||||||
|
}
|
||||||
|
args[n-1] = array;
|
||||||
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ import org.luaj.vm2.LuaTable;
|
|||||||
import org.luaj.vm2.LuaUserdata;
|
import org.luaj.vm2.LuaUserdata;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
import org.luaj.vm2.lib.BaseLib;
|
|
||||||
import org.luaj.vm2.lib.OneArgFunction;
|
|
||||||
import org.luaj.vm2.lib.PackageLib;
|
import org.luaj.vm2.lib.PackageLib;
|
||||||
import org.luaj.vm2.lib.ThreeArgFunction;
|
import org.luaj.vm2.lib.ThreeArgFunction;
|
||||||
import org.luaj.vm2.lib.TwoArgFunction;
|
import org.luaj.vm2.lib.TwoArgFunction;
|
||||||
@@ -52,14 +50,14 @@ import org.luaj.vm2.lib.VarArgFunction;
|
|||||||
|
|
||||||
public class LuajavaLib extends VarArgFunction {
|
public class LuajavaLib extends VarArgFunction {
|
||||||
|
|
||||||
private static final int INIT = 0;
|
static final int INIT = 0;
|
||||||
private static final int BINDCLASS = 1;
|
static final int BINDCLASS = 1;
|
||||||
private static final int NEWINSTANCE = 2;
|
static final int NEWINSTANCE = 2;
|
||||||
private static final int NEW = 3;
|
static final int NEW = 3;
|
||||||
private static final int CREATEPROXY = 4;
|
static final int CREATEPROXY = 4;
|
||||||
private static final int LOADLIB = 5;
|
static final int LOADLIB = 5;
|
||||||
|
|
||||||
private static final String[] NAMES = {
|
static final String[] NAMES = {
|
||||||
"bindClass",
|
"bindClass",
|
||||||
"newInstance",
|
"newInstance",
|
||||||
"new",
|
"new",
|
||||||
@@ -67,12 +65,17 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
"loadLib",
|
"loadLib",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Map classMetatables = new HashMap();
|
static final Map classMetatables = new HashMap();
|
||||||
|
|
||||||
private static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
||||||
|
|
||||||
private static LuaValue LENGTH = valueOf("length");
|
static final LuaValue LENGTH = valueOf("length");
|
||||||
|
|
||||||
|
static final Map consCache = new HashMap();
|
||||||
|
static final Map consIndex = new HashMap();
|
||||||
|
static final Map methCache = new HashMap();
|
||||||
|
static final Map methIndex = new HashMap();
|
||||||
|
|
||||||
public LuajavaLib() {
|
public LuajavaLib() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,10 +101,11 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
final Varargs consargs = args.subargs(2);
|
final Varargs consargs = args.subargs(2);
|
||||||
final long paramssig = LuajavaLib.paramsSignatureOf( consargs );
|
final long paramssig = LuajavaLib.paramsSignatureOf( consargs );
|
||||||
final Constructor con = resolveConstructor( clazz, paramssig );
|
final Constructor con = resolveConstructor( clazz, paramssig );
|
||||||
|
final boolean isvarargs = ((con.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
|
||||||
|
|
||||||
// coerce args, construct instance
|
// coerce args, construct instance
|
||||||
Object[] cargs = CoerceLuaToJava.coerceArgs( consargs, con.getParameterTypes() );
|
final Object[] cargs = CoerceLuaToJava.coerceArgs( consargs, con.getParameterTypes(), isvarargs );
|
||||||
Object o = con.newInstance( cargs );
|
final Object o = con.newInstance( cargs );
|
||||||
|
|
||||||
// return result
|
// return result
|
||||||
return toUserdata( o, clazz );
|
return toUserdata( o, clazz );
|
||||||
@@ -306,7 +310,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
return LuaValue.userdataOf(instance,mt);
|
return LuaValue.userdataOf(instance,mt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class LMethod extends VarArgFunction {
|
static final class LMethod extends VarArgFunction {
|
||||||
private final Class clazz;
|
private final Class clazz;
|
||||||
private final String s;
|
private final String s;
|
||||||
private LMethod(Class clazz, String s) {
|
private LMethod(Class clazz, String s) {
|
||||||
@@ -319,14 +323,15 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
try {
|
try {
|
||||||
// find the method
|
// find the method
|
||||||
Object instance = args.touserdata(1);
|
final Object instance = args.touserdata(1);
|
||||||
Varargs methargs = args.subargs(2);
|
final Varargs methargs = args.subargs(2);
|
||||||
long paramssig = LuajavaLib.paramsSignatureOf(methargs);
|
final long paramssig = LuajavaLib.paramsSignatureOf(methargs);
|
||||||
Method meth = resolveMethod( clazz, s, paramssig );
|
final Method meth = resolveMethod( clazz, s, paramssig );
|
||||||
|
final boolean isvarargs = ((meth.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
|
||||||
|
|
||||||
// coerce the arguments
|
// coerce the arguments
|
||||||
Object[] margs = CoerceLuaToJava.coerceArgs( methargs, meth.getParameterTypes() );
|
final Object[] margs = CoerceLuaToJava.coerceArgs( methargs, meth.getParameterTypes(), isvarargs );
|
||||||
Object result = meth.invoke( instance, margs );
|
final Object result = meth.invoke( instance, margs );
|
||||||
|
|
||||||
// coerce the result
|
// coerce the result
|
||||||
return CoerceJavaToLua.coerce(result);
|
return CoerceJavaToLua.coerce(result);
|
||||||
@@ -338,13 +343,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map consCache =
|
static Constructor resolveConstructor(Class clazz, long paramssig ) {
|
||||||
new HashMap();
|
|
||||||
|
|
||||||
private static Map consIndex =
|
|
||||||
new HashMap();
|
|
||||||
|
|
||||||
private static Constructor resolveConstructor(Class clazz, long paramssig ) {
|
|
||||||
|
|
||||||
// get the cache
|
// get the cache
|
||||||
Map cache = (Map) consCache.get( clazz );
|
Map cache = (Map) consCache.get( clazz );
|
||||||
@@ -357,31 +356,18 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
return c;
|
return c;
|
||||||
|
|
||||||
// get index
|
// get index
|
||||||
Map index = (Map) consIndex.get( clazz );
|
Constructor[] cons = (Constructor[]) consIndex.get( clazz );
|
||||||
if ( index == null ) {
|
if ( cons == null ) {
|
||||||
consIndex.put( clazz, index = new HashMap() );
|
consIndex.put( clazz, cons = clazz.getConstructors() );
|
||||||
Constructor[] cons = clazz.getConstructors();
|
if ( cons == null )
|
||||||
for ( int i=0; i<cons.length; i++ ) {
|
throw new IllegalArgumentException("no public constructors");
|
||||||
Constructor con = cons[i];
|
|
||||||
Integer n = new Integer( con.getParameterTypes().length );
|
|
||||||
List list = (List) index.get(n);
|
|
||||||
if ( list == null )
|
|
||||||
index.put( n, list = new ArrayList() );
|
|
||||||
list.add( con );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out best list of arguments == supplied args
|
|
||||||
Integer n = new Integer( LuajavaLib.paramsCountFromSig(paramssig) );
|
|
||||||
List list = (List) index.get(n);
|
|
||||||
if ( list == null )
|
|
||||||
throw new IllegalArgumentException("no constructor with "+n+" args");
|
|
||||||
|
|
||||||
// find constructor with best score
|
// find constructor with best score
|
||||||
int bests = Integer.MAX_VALUE;
|
int bests = Integer.MAX_VALUE;
|
||||||
int besti = 0;
|
int besti = 0;
|
||||||
for ( int i=0, size=list.size(); i<size; i++ ) {
|
for ( int i=0, size=cons.length; i<size; i++ ) {
|
||||||
Constructor con = (Constructor) list.get(i);
|
Constructor con = cons[i];
|
||||||
int paramType = LuajavaLib.paramTypeFromSig(paramssig, 0);
|
int paramType = LuajavaLib.paramTypeFromSig(paramssig, 0);
|
||||||
int s = CoerceLuaToJava.scoreParamTypes(paramType, con.getParameterTypes());
|
int s = CoerceLuaToJava.scoreParamTypes(paramType, con.getParameterTypes());
|
||||||
if ( s < bests ) {
|
if ( s < bests ) {
|
||||||
@@ -391,19 +377,12 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// put into cache
|
// put into cache
|
||||||
c = (Constructor) list.get(besti);
|
c = cons[besti];
|
||||||
cache.put( paramssig, c );
|
cache.put( paramssig, c );
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Map methCache =
|
static Method resolveMethod(Class clazz, String methodName, long paramssig ) {
|
||||||
new HashMap();
|
|
||||||
|
|
||||||
private static Map methIndex =
|
|
||||||
new HashMap();
|
|
||||||
|
|
||||||
private static Method resolveMethod(Class clazz, String methodName, long paramssig ) {
|
|
||||||
|
|
||||||
// get the cache
|
// get the cache
|
||||||
Map nameCache = (Map) methCache.get( clazz );
|
Map nameCache = (Map) methCache.get( clazz );
|
||||||
@@ -426,27 +405,19 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
for ( int i=0; i<meths.length; i++ ) {
|
for ( int i=0; i<meths.length; i++ ) {
|
||||||
Method meth = meths[i];
|
Method meth = meths[i];
|
||||||
String s = meth.getName();
|
String s = meth.getName();
|
||||||
Integer n = new Integer(meth.getParameterTypes().length);
|
List list = (List) index.get(s);
|
||||||
Map map = (Map) index.get(s);
|
|
||||||
if ( map == null )
|
|
||||||
index.put( s, map = new HashMap() );
|
|
||||||
List list = (List) map.get(n);
|
|
||||||
if ( list == null )
|
if ( list == null )
|
||||||
map.put( n, list = new ArrayList() );
|
index.put( s, list = new ArrayList() );
|
||||||
list.add( meth );
|
list.add( meth );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out best list of arguments == supplied args
|
// figure out best list of arguments == supplied args
|
||||||
Map map = (Map) index.get(methodName);
|
List list = (List) index.get(methodName);
|
||||||
if ( map == null )
|
|
||||||
throw new IllegalArgumentException("no method named '"+methodName+"'");
|
|
||||||
Integer n = new Integer( LuajavaLib.paramsCountFromSig( paramssig ) );
|
|
||||||
List list = (List) map.get(n);
|
|
||||||
if ( list == null )
|
if ( list == null )
|
||||||
throw new IllegalArgumentException("no method named '"+methodName+"' with "+n+" args");
|
throw new IllegalArgumentException("no method named '"+methodName+"'");
|
||||||
|
|
||||||
// find constructor with best score
|
// find method with best score
|
||||||
int bests = Integer.MAX_VALUE;
|
int bests = Integer.MAX_VALUE;
|
||||||
int besti = 0;
|
int besti = 0;
|
||||||
for ( int i=0, size=list.size(); i<size; i++ ) {
|
for ( int i=0, size=list.size(); i<size; i++ ) {
|
||||||
|
|||||||
Reference in New Issue
Block a user