Major refactor of luajava type coercion logic, and method selection logic.
This commit is contained in:
@@ -724,10 +724,10 @@ and LuaForge:
|
|||||||
<tr valign="top"><td> <b>2.0.2</b></td><td><ul>
|
<tr valign="top"><td> <b>2.0.2</b></td><td><ul>
|
||||||
<li>JSR-223 bindings change: non Java-primitives will now be passed as LuaValue </li>
|
<li>JSR-223 bindings change: non Java-primitives will now be passed as LuaValue </li>
|
||||||
<li>JSR-223 enhancement: allow both ".lua" and "lua" as extensions in getScriptEngine() </li>
|
<li>JSR-223 enhancement: allow both ".lua" and "lua" as extensions in getScriptEngine() </li>
|
||||||
|
<li>JSR-223 fix: use system class loader to support using luaj as JRE extension </li>
|
||||||
<li>Improve selection logic when binding to overloaded functions using luajava</li>
|
<li>Improve selection logic when binding to overloaded functions using luajava</li>
|
||||||
<li>Enhance javadoc, put it <a href="http://luaj.sourceforge.net/api/2.0/index.html">online</a>
|
<li>Enhance javadoc, put it <a href="docs/api/index.html">in distribution</a> and <a href="http://luaj.sourceforge.net/api/2.0/index.html">on line</a></li>
|
||||||
and <a href="docs/api/index.html">in distribution</a>
|
<li>Major refactor of luajava type coercion logic, improve method selection.</li>
|
||||||
</li>
|
|
||||||
<li>Add lib/luaj-sources-2.0.2.jar for easier integration into an IDE such as Netbeans </li>
|
<li>Add lib/luaj-sources-2.0.2.jar for easier integration into an IDE such as Netbeans </li>
|
||||||
</ul></td></tr>
|
</ul></td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public class LuaUserdata extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void set( LuaValue key, LuaValue value ) {
|
public void set( LuaValue key, LuaValue value ) {
|
||||||
if ( m_metatable!=null && ! settable(this,key,value) )
|
if ( m_metatable==null || ! settable(this,key,value) )
|
||||||
error( "cannot set "+key+" for userdata" );
|
error( "cannot set "+key+" for userdata" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,15 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.lib.jse;
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.luaj.vm2.LuaDouble;
|
import org.luaj.vm2.LuaDouble;
|
||||||
import org.luaj.vm2.LuaInteger;
|
import org.luaj.vm2.LuaInteger;
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
|
import org.luaj.vm2.LuaTable;
|
||||||
|
import org.luaj.vm2.LuaUserdata;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,6 +106,7 @@ public class CoerceJavaToLua {
|
|||||||
COERCIONS.put( Character.class, charCoercion );
|
COERCIONS.put( Character.class, charCoercion );
|
||||||
COERCIONS.put( Short.class, intCoercion );
|
COERCIONS.put( Short.class, intCoercion );
|
||||||
COERCIONS.put( Integer.class, intCoercion );
|
COERCIONS.put( Integer.class, intCoercion );
|
||||||
|
COERCIONS.put( Long.class, doubleCoercion );
|
||||||
COERCIONS.put( Float.class, doubleCoercion );
|
COERCIONS.put( Float.class, doubleCoercion );
|
||||||
COERCIONS.put( Double.class, doubleCoercion );
|
COERCIONS.put( Double.class, doubleCoercion );
|
||||||
COERCIONS.put( String.class, stringCoercion );
|
COERCIONS.put( String.class, stringCoercion );
|
||||||
@@ -129,9 +133,25 @@ public class CoerceJavaToLua {
|
|||||||
return LuaValue.NIL;
|
return LuaValue.NIL;
|
||||||
Class clazz = o.getClass();
|
Class clazz = o.getClass();
|
||||||
Coercion c = (Coercion) COERCIONS.get( clazz );
|
Coercion c = (Coercion) COERCIONS.get( clazz );
|
||||||
if ( c != null )
|
if ( c == null ) {
|
||||||
return c.coerce( o );
|
c = o instanceof Class? JavaClass.forClass((Class)o):
|
||||||
return LuajavaLib.toUserdata( o, clazz );
|
clazz.isArray()? arrayCoercion:
|
||||||
|
instanceCoercion;
|
||||||
|
COERCIONS.put( clazz, c );
|
||||||
|
}
|
||||||
|
return c.coerce(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final Coercion instanceCoercion = new Coercion() {
|
||||||
|
public LuaValue coerce(Object javaValue) {
|
||||||
|
return new JavaInstance(javaValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// should be userdata?
|
||||||
|
static final Coercion arrayCoercion = new Coercion() {
|
||||||
|
public LuaValue coerce(Object javaValue) {
|
||||||
|
return new JavaArray(javaValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,16 @@
|
|||||||
package org.luaj.vm2.lib.jse;
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.luaj.vm2.LuaError;
|
import org.luaj.vm2.LuaError;
|
||||||
|
import org.luaj.vm2.LuaString;
|
||||||
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
@@ -58,187 +64,272 @@ import org.luaj.vm2.Varargs;
|
|||||||
*/
|
*/
|
||||||
public class CoerceLuaToJava {
|
public class CoerceLuaToJava {
|
||||||
|
|
||||||
|
static int SCORE_NULL_VALUE = 0x10;
|
||||||
|
static int SCORE_WRONG_TYPE = 0x100;
|
||||||
|
static int SCORE_UNCOERCIBLE = 0x10000;
|
||||||
|
|
||||||
static interface Coercion {
|
static interface Coercion {
|
||||||
|
public int score( LuaValue value );
|
||||||
public Object coerce( LuaValue value );
|
public Object coerce( LuaValue value );
|
||||||
public int score( int paramType );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coerce a LuaValue value to a specified java class
|
||||||
|
* @param value LuaValue to coerce
|
||||||
|
* @param clazz Class to coerce into
|
||||||
|
* @return Object of type clazz (or a subclass) with the corresponding value.
|
||||||
|
*/
|
||||||
|
public static Object coerce(LuaValue value, Class clazz) {
|
||||||
|
return getCoercion(clazz).coerce(value);
|
||||||
|
}
|
||||||
|
|
||||||
static final Map COERCIONS = new HashMap();
|
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
|
||||||
|
|
||||||
static {
|
static final class BoolCoercion implements Coercion {
|
||||||
Coercion boolCoercion = new Coercion() {
|
public String toString() {
|
||||||
public Object coerce(LuaValue value) {
|
return "BoolCoercion()";
|
||||||
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
}
|
||||||
}
|
public int score( LuaValue value ) {
|
||||||
public int score(int paramType) {
|
switch ( value.type() ) {
|
||||||
switch ( paramType ) {
|
case LuaValue.TBOOLEAN:
|
||||||
case LuaValue.TNIL:
|
return 0;
|
||||||
case LuaValue.TBOOLEAN:
|
}
|
||||||
return 0;
|
return 1;
|
||||||
case LuaValue.TINT:
|
}
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 1;
|
public Object coerce(LuaValue value) {
|
||||||
default:
|
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
||||||
return 4;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class NumericCoercion implements Coercion {
|
||||||
|
static final int TARGET_TYPE_BYTE = 0;
|
||||||
|
static final int TARGET_TYPE_CHAR = 1;
|
||||||
|
static final int TARGET_TYPE_SHORT = 2;
|
||||||
|
static final int TARGET_TYPE_INT = 3;
|
||||||
|
static final int TARGET_TYPE_LONG = 4;
|
||||||
|
static final int TARGET_TYPE_FLOAT = 5;
|
||||||
|
static final int TARGET_TYPE_DOUBLE = 6;
|
||||||
|
static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" };
|
||||||
|
final int targetType;
|
||||||
|
public String toString() {
|
||||||
|
return "NumericCoercion("+TYPE_NAMES[targetType]+")";
|
||||||
|
}
|
||||||
|
NumericCoercion(int targetType) {
|
||||||
|
this.targetType = targetType;
|
||||||
|
}
|
||||||
|
public int score( LuaValue value ) {
|
||||||
|
if ( value.isint() ) {
|
||||||
|
switch ( targetType ) {
|
||||||
|
case TARGET_TYPE_BYTE: {
|
||||||
|
int i = value.toint();
|
||||||
|
return (i==(byte)i)? 0: SCORE_WRONG_TYPE;
|
||||||
}
|
}
|
||||||
}
|
case TARGET_TYPE_CHAR: {
|
||||||
};
|
int i = value.toint();
|
||||||
Coercion byteCoercion = new Coercion() {
|
return (i==(byte)i)? 1: (i==(char)i)? 0: SCORE_WRONG_TYPE;
|
||||||
public Object coerce(LuaValue value) {
|
|
||||||
return new Byte( (byte) value.toint() );
|
|
||||||
}
|
|
||||||
public int score(int paramType) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TINT:
|
|
||||||
return 1;
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
case TARGET_TYPE_SHORT: {
|
||||||
};
|
int i = value.toint();
|
||||||
Coercion charCoercion = new Coercion() {
|
return (i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE;
|
||||||
public Object coerce(LuaValue value) {
|
|
||||||
return new Character( (char) value.toint() );
|
|
||||||
}
|
|
||||||
public int score(int paramType) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TINT:
|
|
||||||
return 1;
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
case TARGET_TYPE_INT: {
|
||||||
};
|
int i = value.toint();
|
||||||
Coercion shortCoercion = new Coercion() {
|
return (i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0;
|
||||||
public Object coerce(LuaValue value) {
|
|
||||||
return new Short( (short) value.toint() );
|
|
||||||
}
|
|
||||||
public int score(int paramType) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TINT:
|
|
||||||
return 1;
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
case TARGET_TYPE_FLOAT: return 1;
|
||||||
};
|
case TARGET_TYPE_LONG: return 1;
|
||||||
Coercion intCoercion = new Coercion() {
|
case TARGET_TYPE_DOUBLE: return 2;
|
||||||
public Object coerce(LuaValue value) {
|
default: return SCORE_WRONG_TYPE;
|
||||||
return new Integer( value.toint() );
|
|
||||||
}
|
|
||||||
public int score(int paramType) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TINT:
|
|
||||||
return 0;
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 1;
|
|
||||||
case LuaValue.TBOOLEAN:
|
|
||||||
case LuaValue.TNIL:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
} else if ( value.isnumber() ) {
|
||||||
};
|
switch ( targetType ) {
|
||||||
Coercion longCoercion = new Coercion() {
|
case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE;
|
||||||
public Object coerce(LuaValue value) {
|
case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE;
|
||||||
return new Long( value.tolong() );
|
case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE;
|
||||||
}
|
case TARGET_TYPE_INT: return SCORE_WRONG_TYPE;
|
||||||
public int score(int paramType) {
|
case TARGET_TYPE_LONG: {
|
||||||
switch ( paramType ) {
|
double d = value.todouble();
|
||||||
case LuaValue.TINT:
|
return (d==(long)d)? 0: SCORE_WRONG_TYPE;
|
||||||
return 1;
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
case TARGET_TYPE_FLOAT: {
|
||||||
};
|
double d = value.todouble();
|
||||||
Coercion floatCoercion = new Coercion() {
|
return (d==(float)d)? 0: SCORE_WRONG_TYPE;
|
||||||
public Object coerce(LuaValue value) {
|
|
||||||
return new Float( value.tofloat() );
|
|
||||||
}
|
|
||||||
public int score( int paramType ) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TINT:
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 1;
|
|
||||||
case LuaValue.TBOOLEAN:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
case TARGET_TYPE_DOUBLE: {
|
||||||
};
|
double d = value.todouble();
|
||||||
Coercion doubleCoercion = new Coercion() {
|
return ((d==(long)d) || (d==(float)d))? 1: 0;
|
||||||
public Object coerce(LuaValue value) {
|
|
||||||
return new Double( value.todouble() );
|
|
||||||
}
|
|
||||||
public int score(int paramType) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TINT:
|
|
||||||
return 1;
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return 0;
|
|
||||||
case LuaValue.TBOOLEAN:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
|
default: return SCORE_WRONG_TYPE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return SCORE_UNCOERCIBLE;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Coercion stringCoercion = new Coercion() {
|
|
||||||
public Object coerce(LuaValue value) {
|
public Object coerce(LuaValue value) {
|
||||||
|
switch ( targetType ) {
|
||||||
|
case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() );
|
||||||
|
case TARGET_TYPE_CHAR: return new Character( (char) value.toint() );
|
||||||
|
case TARGET_TYPE_SHORT: return new Short( (short) value.toint() );
|
||||||
|
case TARGET_TYPE_INT: return new Integer( (int) value.toint() );
|
||||||
|
case TARGET_TYPE_LONG: return new Long( (long) value.todouble() );
|
||||||
|
case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() );
|
||||||
|
case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() );
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class StringCoercion implements Coercion {
|
||||||
|
public static final int TARGET_TYPE_STRING = 0;
|
||||||
|
public static final int TARGET_TYPE_BYTES = 1;
|
||||||
|
final int targetType;
|
||||||
|
public StringCoercion(int targetType) {
|
||||||
|
this.targetType = targetType;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")";
|
||||||
|
}
|
||||||
|
public int score(LuaValue value) {
|
||||||
|
switch ( value.type() ) {
|
||||||
|
case LuaValue.TSTRING:
|
||||||
|
return value.checkstring().isValidUtf8()?
|
||||||
|
(targetType==TARGET_TYPE_STRING? 0: 1):
|
||||||
|
(targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE);
|
||||||
|
case LuaValue.TNIL:
|
||||||
|
return SCORE_NULL_VALUE;
|
||||||
|
default:
|
||||||
|
return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object coerce(LuaValue value) {
|
||||||
|
if ( value.isnil() )
|
||||||
|
return null;
|
||||||
|
if ( targetType == TARGET_TYPE_STRING )
|
||||||
return value.tojstring();
|
return value.tojstring();
|
||||||
}
|
LuaString s = value.checkstring();
|
||||||
public int score(int paramType) {
|
byte[] b = new byte[s.m_length];
|
||||||
switch ( paramType ) {
|
s.copyInto(0, b, 0, b.length);
|
||||||
case LuaValue.TSTRING:
|
return b;
|
||||||
return 0;
|
}
|
||||||
case LuaValue.TUSERDATA:
|
}
|
||||||
return 1;
|
|
||||||
default:
|
static final class ArrayCoercion implements Coercion {
|
||||||
return 2;
|
final Class componentType;
|
||||||
}
|
final Coercion componentCoercion;
|
||||||
|
public ArrayCoercion(Class componentType) {
|
||||||
|
this.componentType = componentType;
|
||||||
|
this.componentCoercion = getCoercion(componentType);
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "ArrayCoercion("+componentType.getName()+")";
|
||||||
|
}
|
||||||
|
public int score(LuaValue value) {
|
||||||
|
switch ( value.type() ) {
|
||||||
|
case LuaValue.TTABLE:
|
||||||
|
return value.length()==0? 0: componentCoercion.score( value.get(1) );
|
||||||
|
case LuaValue.TUSERDATA:
|
||||||
|
return inheritanceLevels( componentType, value.touserdata().getClass().getComponentType() );
|
||||||
|
case LuaValue.TNIL:
|
||||||
|
return SCORE_NULL_VALUE;
|
||||||
|
default:
|
||||||
|
return SCORE_UNCOERCIBLE;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Coercion objectCoercion = new Coercion() {
|
public Object coerce(LuaValue value) {
|
||||||
public Object coerce(LuaValue value) {
|
switch ( value.type() ) {
|
||||||
switch ( value.type() ) {
|
case LuaValue.TTABLE: {
|
||||||
case LuaValue.TUSERDATA:
|
int n = value.length();
|
||||||
return value.optuserdata(Object.class, null);
|
Object a = Array.newInstance(componentType, n);
|
||||||
case LuaValue.TSTRING:
|
for ( int i=0; i<n; i++ )
|
||||||
return value.tojstring();
|
Array.set(a, i, componentCoercion.coerce(value.get(i+1)));
|
||||||
case LuaValue.TINT:
|
return a;
|
||||||
return new Integer(value.toint());
|
|
||||||
case LuaValue.TNUMBER:
|
|
||||||
return new Double(value.todouble());
|
|
||||||
case LuaValue.TBOOLEAN:
|
|
||||||
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
|
||||||
case LuaValue.TNIL:
|
|
||||||
return null;
|
|
||||||
default:
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public int score(int paramType) {
|
|
||||||
switch ( paramType ) {
|
|
||||||
case LuaValue.TUSERDATA:
|
|
||||||
return 0;
|
|
||||||
case LuaValue.TSTRING:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0x10;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
case LuaValue.TUSERDATA:
|
||||||
|
return value.touserdata();
|
||||||
|
case LuaValue.TNIL:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine levels of inheritance between a base class and a subclass
|
||||||
|
* @param baseclass base class to look for
|
||||||
|
* @param subclass class from which to start looking
|
||||||
|
* @return number of inheritance levels between subclass and baseclass,
|
||||||
|
* or SCORE_UNCOERCIBLE if not a subclass
|
||||||
|
*/
|
||||||
|
static final int inheritanceLevels( Class baseclass, Class subclass ) {
|
||||||
|
if ( subclass == null )
|
||||||
|
return SCORE_UNCOERCIBLE;
|
||||||
|
if ( baseclass == subclass )
|
||||||
|
return 0;
|
||||||
|
int min = Math.min( SCORE_UNCOERCIBLE, inheritanceLevels( baseclass, subclass.getSuperclass() ) + 1 );
|
||||||
|
Class[] ifaces = subclass.getInterfaces();
|
||||||
|
for ( int i=0; i<ifaces.length; i++ )
|
||||||
|
min = Math.min(min, inheritanceLevels(baseclass, ifaces[i]) + 1 );
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class ObjectCoercion implements Coercion {
|
||||||
|
final Class targetType;
|
||||||
|
ObjectCoercion(Class targetType) {
|
||||||
|
this.targetType = targetType;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "ObjectCoercion("+targetType.getName()+")";
|
||||||
|
}
|
||||||
|
public int score(LuaValue value) {
|
||||||
|
switch ( value.type() ) {
|
||||||
|
case LuaValue.TNUMBER:
|
||||||
|
return inheritanceLevels( targetType, value.isint()? Integer.class: Double.class );
|
||||||
|
case LuaValue.TBOOLEAN:
|
||||||
|
return inheritanceLevels( targetType, Boolean.class );
|
||||||
|
case LuaValue.TSTRING:
|
||||||
|
return inheritanceLevels( targetType, String.class );
|
||||||
|
case LuaValue.TUSERDATA:
|
||||||
|
return inheritanceLevels( targetType, value.touserdata().getClass() );
|
||||||
|
case LuaValue.TNIL:
|
||||||
|
return SCORE_NULL_VALUE;
|
||||||
|
default:
|
||||||
|
return inheritanceLevels( targetType, value.getClass() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object coerce(LuaValue value) {
|
||||||
|
switch ( value.type() ) {
|
||||||
|
case LuaValue.TNUMBER:
|
||||||
|
return value.isint()? (Object)new Integer(value.toint()): (Object)new Double(value.todouble());
|
||||||
|
case LuaValue.TBOOLEAN:
|
||||||
|
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
||||||
|
case LuaValue.TSTRING:
|
||||||
|
return value.tojstring();
|
||||||
|
case LuaValue.TUSERDATA:
|
||||||
|
return value.optuserdata(targetType, null);
|
||||||
|
case LuaValue.TNIL:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
Coercion boolCoercion = new BoolCoercion();
|
||||||
|
Coercion byteCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_BYTE);
|
||||||
|
Coercion charCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_CHAR);
|
||||||
|
Coercion shortCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_SHORT);
|
||||||
|
Coercion intCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_INT);
|
||||||
|
Coercion longCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_LONG);
|
||||||
|
Coercion floatCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_FLOAT);
|
||||||
|
Coercion doubleCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_DOUBLE);
|
||||||
|
Coercion stringCoercion = new StringCoercion(StringCoercion.TARGET_TYPE_STRING);
|
||||||
|
Coercion bytesCoercion = new StringCoercion(StringCoercion.TARGET_TYPE_BYTES);
|
||||||
|
|
||||||
COERCIONS.put( Boolean.TYPE, boolCoercion );
|
COERCIONS.put( Boolean.TYPE, boolCoercion );
|
||||||
COERCIONS.put( Boolean.class, boolCoercion );
|
COERCIONS.put( Boolean.class, boolCoercion );
|
||||||
COERCIONS.put( Byte.TYPE, byteCoercion );
|
COERCIONS.put( Byte.TYPE, byteCoercion );
|
||||||
@@ -256,95 +347,21 @@ public class CoerceLuaToJava {
|
|||||||
COERCIONS.put( Double.TYPE, doubleCoercion );
|
COERCIONS.put( Double.TYPE, doubleCoercion );
|
||||||
COERCIONS.put( Double.class, doubleCoercion );
|
COERCIONS.put( Double.class, doubleCoercion );
|
||||||
COERCIONS.put( String.class, stringCoercion );
|
COERCIONS.put( String.class, stringCoercion );
|
||||||
COERCIONS.put( Object.class, objectCoercion );
|
COERCIONS.put( byte[].class, bytesCoercion );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Coercion getCoercion(Class c) {
|
||||||
/** Score a single parameter, including array handling */
|
|
||||||
static int scoreParam(int paramType, Class c) {
|
|
||||||
if ( paramType == LuaValue.TUSERDATA && !c.isArray() )
|
|
||||||
return 0;
|
|
||||||
Coercion co = (Coercion) COERCIONS.get( c );
|
Coercion co = (Coercion) COERCIONS.get( c );
|
||||||
if ( co != null ) {
|
if ( co != null ) {
|
||||||
int b = LuajavaLib.paramBaseTypeFromParamType(paramType);
|
return co;
|
||||||
int d = LuajavaLib.paramDepthFromParamType(paramType);
|
|
||||||
int s = co.score(b);
|
|
||||||
return s * (d+1);
|
|
||||||
}
|
}
|
||||||
if ( c.isArray() ) {
|
if ( c.isArray() ) {
|
||||||
Class typ = c.getComponentType();
|
Class typ = c.getComponentType();
|
||||||
int d = LuajavaLib.paramDepthFromParamType(paramType);
|
co = new ArrayCoercion(c.getComponentType());
|
||||||
if ( d > 0 )
|
} else {
|
||||||
return scoreParam( LuajavaLib.paramComponentTypeOfParamType(paramType), typ );
|
co = new ObjectCoercion(c);
|
||||||
else
|
|
||||||
return 0x10 + (scoreParam(paramType, typ) << 8);
|
|
||||||
}
|
}
|
||||||
return 0x1000;
|
COERCIONS.put( c, co );
|
||||||
}
|
return co;
|
||||||
|
|
||||||
/** Do a conversion */
|
|
||||||
static Object coerceArg(LuaValue a, Class c) {
|
|
||||||
if ( a.isuserdata(c) )
|
|
||||||
return a.touserdata(c);
|
|
||||||
Coercion co = (Coercion) COERCIONS.get( c );
|
|
||||||
if ( co != null ) {
|
|
||||||
return co.coerce( a );
|
|
||||||
}
|
|
||||||
if ( c.isArray() ) {
|
|
||||||
boolean istable = a.istable();
|
|
||||||
int n = istable? a.length(): 1;
|
|
||||||
Class typ = c.getComponentType();
|
|
||||||
Object arr = Array.newInstance(typ, n);
|
|
||||||
for ( int i=0; i<n; i++ ) {
|
|
||||||
LuaValue ele = (istable? a.checktable().get(i+1): a);
|
|
||||||
if ( ele != null )
|
|
||||||
Array.set(arr, i, coerceArg(ele, typ));
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
if ( a.isnil() )
|
|
||||||
return null;
|
|
||||||
throw new LuaError("no coercion found for "+a.getClass()+" to "+c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Object[] coerceArgs(Varargs suppliedArgs, Class[] parameterTypes, boolean isvarargs) {
|
|
||||||
int nsupplied = suppliedArgs.narg();
|
|
||||||
int n = parameterTypes.length;
|
|
||||||
int nplain = Math.min(isvarargs? n-1: n, nsupplied);
|
|
||||||
Object[] args = new Object[n];
|
|
||||||
for ( int i=0; i<nplain; 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Score parameter types for match with supplied parameter list
|
|
||||||
*
|
|
||||||
* 1) exact number of args
|
|
||||||
* 2) java has more args
|
|
||||||
* 3) java has less args
|
|
||||||
* 4) types coerce well
|
|
||||||
*/
|
|
||||||
static int scoreParamTypes(long paramssig, Class[] paramTypes) {
|
|
||||||
int nargs = LuajavaLib.paramsCountFromSig(paramssig);
|
|
||||||
int njava = paramTypes.length;
|
|
||||||
int score = (njava == nargs? 0: njava > nargs? 0x4000: 0x8000);
|
|
||||||
for ( int i=0; i<nargs && i<njava; i++ ) {
|
|
||||||
int paramType = LuajavaLib.paramTypeFromSig(paramssig, i);
|
|
||||||
Class c = paramTypes[i];
|
|
||||||
int s = scoreParam( paramType, c );
|
|
||||||
score += s;
|
|
||||||
}
|
|
||||||
return score;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
src/jse/org/luaj/vm2/lib/jse/JavaArray.java
Normal file
65
src/jse/org/luaj/vm2/lib/jse/JavaArray.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaUserdata;
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuaValue that represents a Java instance of array type.
|
||||||
|
* <p>
|
||||||
|
* Can get elements by their integer key index, as well as the length.
|
||||||
|
*/
|
||||||
|
public class JavaArray extends LuaUserdata {
|
||||||
|
|
||||||
|
static final LuaValue LENGTH = valueOf("length");
|
||||||
|
|
||||||
|
JavaArray(Object instance) {
|
||||||
|
super(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue get(LuaValue key) {
|
||||||
|
if ( key.equals(LENGTH) )
|
||||||
|
return CoerceJavaToLua.coerce(Array.getLength(m_instance));
|
||||||
|
if ( key.isint() ) {
|
||||||
|
int i = key.toint() - 1;
|
||||||
|
return i>=0 && i<Array.getLength(m_instance)?
|
||||||
|
CoerceJavaToLua.coerce(Array.get(m_instance,key.toint()-1)):
|
||||||
|
NIL;
|
||||||
|
}
|
||||||
|
return super.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(LuaValue key, LuaValue value) {
|
||||||
|
if ( key.isint() ) {
|
||||||
|
int i = key.toint() - 1;
|
||||||
|
if ( i>=0 && i<Array.getLength(m_instance) )
|
||||||
|
Array.set(m_instance,i,CoerceLuaToJava.coerce(value, m_instance.getClass().getComponentType()));
|
||||||
|
else if ( m_metatable==null || ! settable(this,key,value) )
|
||||||
|
error("array index out of bounds");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
super.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/jse/org/luaj/vm2/lib/jse/JavaClass.java
Normal file
124
src/jse/org/luaj/vm2/lib/jse/JavaClass.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuaValue that represents a Java class.
|
||||||
|
* <p>
|
||||||
|
* Will respond to get() and set() by returning field values, or java methods.
|
||||||
|
*/
|
||||||
|
public class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
||||||
|
|
||||||
|
static final Map classes = Collections.synchronizedMap(new HashMap());
|
||||||
|
|
||||||
|
static final LuaValue NEW = valueOf("new");
|
||||||
|
|
||||||
|
Map fields;
|
||||||
|
Map methods;
|
||||||
|
|
||||||
|
static JavaClass forClass(Class c) {
|
||||||
|
JavaClass j = (JavaClass) classes.get(c);
|
||||||
|
if ( j == null )
|
||||||
|
classes.put( c, j = new JavaClass(c) );
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
JavaClass(Class c) {
|
||||||
|
super(c);
|
||||||
|
this.jclass = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue coerce(Object javaValue) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field getField(LuaValue key) {
|
||||||
|
if ( fields == null ) {
|
||||||
|
Map m = new HashMap();
|
||||||
|
Field[] f = ((Class)m_instance).getFields();
|
||||||
|
for ( int i=0; i<f.length; i++ )
|
||||||
|
if ( Modifier.isPublic(f[i].getModifiers()) )
|
||||||
|
m.put( LuaValue.valueOf(f[i].getName()), f[i] );
|
||||||
|
fields = m;
|
||||||
|
}
|
||||||
|
return (Field) fields.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaValue getMethod(LuaValue key) {
|
||||||
|
if ( methods == null ) {
|
||||||
|
Map namedlists = new HashMap();
|
||||||
|
Method[] m = ((Class)m_instance).getMethods();
|
||||||
|
for ( int i=0; i<m.length; i++ ) {
|
||||||
|
Method mi = m[i];
|
||||||
|
if ( Modifier.isPublic( mi.getModifiers()) ) {
|
||||||
|
String name = mi.getName();
|
||||||
|
List list = (List) namedlists.get(name);
|
||||||
|
if ( list == null )
|
||||||
|
namedlists.put(name, list = new ArrayList());
|
||||||
|
list.add( JavaMethod.forMethod(mi) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map map = new HashMap();
|
||||||
|
Constructor[] c = ((Class)m_instance).getConstructors();
|
||||||
|
List list = new ArrayList();
|
||||||
|
for ( int i=0; i<c.length; i++ )
|
||||||
|
if ( Modifier.isPublic(c[i].getModifiers()) )
|
||||||
|
list.add( JavaConstructor.forConstructor(c[i]) );
|
||||||
|
switch ( list.size() ) {
|
||||||
|
case 0: break;
|
||||||
|
case 1: map.put(NEW, list.get(0)); break;
|
||||||
|
default: map.put(NEW, JavaConstructor.forConstructors( (JavaConstructor[])list.toArray(new JavaConstructor[list.size()]) ) ); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Iterator it=namedlists.entrySet().iterator(); it.hasNext(); ) {
|
||||||
|
Entry e = (Entry) it.next();
|
||||||
|
String name = (String) e.getKey();
|
||||||
|
List methods = (List) e.getValue();
|
||||||
|
map.put( LuaValue.valueOf(name),
|
||||||
|
methods.size()==1?
|
||||||
|
methods.get(0):
|
||||||
|
JavaMethod.forMethods( (JavaMethod[])methods.toArray(new JavaMethod[methods.size()])) );
|
||||||
|
}
|
||||||
|
methods = map;
|
||||||
|
}
|
||||||
|
return (LuaValue) methods.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue getConstructor() {
|
||||||
|
return getMethod(NEW);
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/jse/org/luaj/vm2/lib/jse/JavaConstructor.java
Normal file
101
src/jse/org/luaj/vm2/lib/jse/JavaConstructor.java
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
import org.luaj.vm2.Varargs;
|
||||||
|
import org.luaj.vm2.lib.VarArgFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuaValue that represents a particular public Java constructor.
|
||||||
|
* <p>
|
||||||
|
* May be called with arguments to return a JavaInstance
|
||||||
|
* created by calling the constructor.
|
||||||
|
*/
|
||||||
|
public class JavaConstructor extends JavaMember {
|
||||||
|
|
||||||
|
static final Map constructors = Collections.synchronizedMap(new HashMap());
|
||||||
|
|
||||||
|
static JavaConstructor forConstructor(Constructor c) {
|
||||||
|
JavaConstructor j = (JavaConstructor) constructors.get(c);
|
||||||
|
if ( j == null )
|
||||||
|
constructors.put( c, j = new JavaConstructor(c) );
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LuaValue forConstructors(JavaConstructor[] array) {
|
||||||
|
return new Overload(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Constructor constructor;
|
||||||
|
|
||||||
|
private JavaConstructor(Constructor c) {
|
||||||
|
super( c.getParameterTypes(), c.getModifiers() );
|
||||||
|
this.constructor = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
Object[] a = convertArgs(args);
|
||||||
|
try {
|
||||||
|
return CoerceJavaToLua.coerce( constructor.newInstance(a) );
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new LuaError(e.getTargetException());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return LuaValue.error("coercion error "+e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Overload extends VarArgFunction {
|
||||||
|
final JavaConstructor[] constructors;
|
||||||
|
public Overload(JavaConstructor[] c) {
|
||||||
|
this.constructors = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
JavaConstructor best = null;
|
||||||
|
int score = CoerceLuaToJava.SCORE_UNCOERCIBLE;
|
||||||
|
for ( int i=0; i<constructors.length; i++ ) {
|
||||||
|
int s = constructors[i].score(args);
|
||||||
|
if ( s < score ) {
|
||||||
|
score = s;
|
||||||
|
best = constructors[i];
|
||||||
|
if ( score == 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// any match?
|
||||||
|
if ( best == null )
|
||||||
|
LuaValue.error("no coercible public method");
|
||||||
|
|
||||||
|
// invoke it
|
||||||
|
return best.invoke(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/jse/org/luaj/vm2/lib/jse/JavaInstance.java
Normal file
73
src/jse/org/luaj/vm2/lib/jse/JavaInstance.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
|
import org.luaj.vm2.LuaUserdata;
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuaValue that represents a Java instance.
|
||||||
|
* <p>
|
||||||
|
* Will respond to get() and set() by returning field values or methods.
|
||||||
|
*/
|
||||||
|
public class JavaInstance extends LuaUserdata {
|
||||||
|
|
||||||
|
JavaClass jclass;
|
||||||
|
|
||||||
|
JavaInstance(Object instance) {
|
||||||
|
super(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue get(LuaValue key) {
|
||||||
|
if ( jclass == null )
|
||||||
|
jclass = JavaClass.forClass(m_instance.getClass());
|
||||||
|
Field f = jclass.getField(key);
|
||||||
|
if ( f != null )
|
||||||
|
try {
|
||||||
|
return CoerceJavaToLua.coerce(f.get(m_instance));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new LuaError(e);
|
||||||
|
}
|
||||||
|
LuaValue m = jclass.getMethod(key);
|
||||||
|
if ( m != null )
|
||||||
|
return m;
|
||||||
|
return super.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(LuaValue key, LuaValue value) {
|
||||||
|
if ( jclass == null )
|
||||||
|
jclass = JavaClass.forClass(m_instance.getClass());
|
||||||
|
Field f = jclass.getField(key);
|
||||||
|
if ( f != null )
|
||||||
|
try {
|
||||||
|
f.set(m_instance, CoerceLuaToJava.coerce(value, f.getType()));
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new LuaError(e);
|
||||||
|
}
|
||||||
|
super.set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
77
src/jse/org/luaj/vm2/lib/jse/JavaMember.java
Normal file
77
src/jse/org/luaj/vm2/lib/jse/JavaMember.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import org.luaj.vm2.Varargs;
|
||||||
|
import org.luaj.vm2.lib.VarArgFunction;
|
||||||
|
import org.luaj.vm2.lib.jse.CoerceLuaToJava.Coercion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java method or constructor.
|
||||||
|
* <p>
|
||||||
|
* Primarily handles argument coercion for parameter lists including scoring of compatibility and
|
||||||
|
* java varargs handling.
|
||||||
|
*/
|
||||||
|
abstract
|
||||||
|
class JavaMember extends VarArgFunction {
|
||||||
|
|
||||||
|
static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
||||||
|
|
||||||
|
final Coercion[] fixedargs;
|
||||||
|
final Coercion varargs;
|
||||||
|
|
||||||
|
protected JavaMember(Class[] params, int modifiers) {
|
||||||
|
boolean isvarargs = ((modifiers & METHOD_MODIFIERS_VARARGS) != 0);
|
||||||
|
fixedargs = new CoerceLuaToJava.Coercion[isvarargs? params.length-1: params.length];
|
||||||
|
for ( int i=0; i<fixedargs.length; i++ )
|
||||||
|
fixedargs[i] = CoerceLuaToJava.getCoercion( params[i] );
|
||||||
|
varargs = isvarargs? CoerceLuaToJava.getCoercion( params[params.length-1] ): null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int score(Varargs args) {
|
||||||
|
int n = args.narg();
|
||||||
|
int s = n>fixedargs.length? CoerceLuaToJava.SCORE_WRONG_TYPE * (n-fixedargs.length): 0;
|
||||||
|
for ( int j=0; j<fixedargs.length; j++ )
|
||||||
|
s += fixedargs[j].score( args.arg(j+1) );
|
||||||
|
if ( varargs != null )
|
||||||
|
for ( int k=fixedargs.length; k<n; k++ )
|
||||||
|
s += varargs.score( args.arg(k+1) );
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object[] convertArgs(Varargs args) {
|
||||||
|
Object[] a;
|
||||||
|
if ( varargs == null ) {
|
||||||
|
a = new Object[fixedargs.length];
|
||||||
|
for ( int i=0; i<a.length; i++ )
|
||||||
|
a[i] = fixedargs[i].coerce( args.arg(i+1) );
|
||||||
|
} else {
|
||||||
|
int n = Math.max(fixedargs.length,args.narg());
|
||||||
|
a = new Object[n];
|
||||||
|
for ( int i=0; i<fixedargs.length; i++ )
|
||||||
|
a[i] = fixedargs[i].coerce( args.arg(i+1) );
|
||||||
|
for ( int i=fixedargs.length; i<n; i++ )
|
||||||
|
a[i] = varargs.coerce( args.arg(i+1) );
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
149
src/jse/org/luaj/vm2/lib/jse/JavaMethod.java
Normal file
149
src/jse/org/luaj/vm2/lib/jse/JavaMethod.java
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
|
import org.luaj.vm2.LuaFunction;
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
import org.luaj.vm2.Varargs;
|
||||||
|
import org.luaj.vm2.lib.jse.CoerceLuaToJava.Coercion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuaValue that represents a Java method.
|
||||||
|
* <p>
|
||||||
|
* Can be invoked.
|
||||||
|
*/
|
||||||
|
public class JavaMethod extends JavaMember {
|
||||||
|
|
||||||
|
static final Map methods = Collections.synchronizedMap(new HashMap());
|
||||||
|
|
||||||
|
static JavaMethod forMethod(Method m) {
|
||||||
|
JavaMethod j = (JavaMethod) methods.get(m);
|
||||||
|
if ( j == null )
|
||||||
|
methods.put( m, j = new JavaMethod(m) );
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LuaFunction forMethods(JavaMethod[] m) {
|
||||||
|
return new Overload(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Method method;
|
||||||
|
|
||||||
|
private JavaMethod(Method m) {
|
||||||
|
super( m.getParameterTypes(), m.getModifiers() );
|
||||||
|
this.method = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call() {
|
||||||
|
return error("method cannot be called without instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
return invokeMethod(arg.checkuserdata(), LuaValue.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
|
return invokeMethod(arg1.checkuserdata(), arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
|
||||||
|
return invokeMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
return invokeMethod(args.checkuserdata(1), args.subargs(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaValue invokeMethod(Object instance, Varargs args) {
|
||||||
|
Object[] a = convertArgs(args);
|
||||||
|
try {
|
||||||
|
return CoerceJavaToLua.coerce( method.invoke(instance, a) );
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new LuaError(e.getTargetException());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return LuaValue.error("coercion error "+e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LuaValue that represents an overloaded Java method.
|
||||||
|
* <p>
|
||||||
|
* On invocation, will pick the best method fromi the list, and invoke it.
|
||||||
|
*/
|
||||||
|
static class Overload extends LuaFunction {
|
||||||
|
|
||||||
|
final JavaMethod[] methods;
|
||||||
|
|
||||||
|
Overload(JavaMethod[] methods) {
|
||||||
|
this.methods = methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call() {
|
||||||
|
return error("method cannot be called without instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
return invokeBestMethod(arg.checkuserdata(), LuaValue.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
|
return invokeBestMethod(arg1.checkuserdata(), arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
|
||||||
|
return invokeBestMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
return invokeBestMethod(args.checkuserdata(1), args.subargs(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private LuaValue invokeBestMethod(Object instance, Varargs args) {
|
||||||
|
JavaMethod best = null;
|
||||||
|
int score = CoerceLuaToJava.SCORE_UNCOERCIBLE;
|
||||||
|
for ( int i=0; i<methods.length; i++ ) {
|
||||||
|
int s = methods[i].score(args);
|
||||||
|
if ( s < score ) {
|
||||||
|
score = s;
|
||||||
|
best = methods[i];
|
||||||
|
if ( score == 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// any match?
|
||||||
|
if ( best == null )
|
||||||
|
LuaValue.error("no coercible public method");
|
||||||
|
|
||||||
|
// invoke it
|
||||||
|
return best.invokeMethod(instance, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,28 +23,22 @@ package org.luaj.vm2.lib.jse;
|
|||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.luaj.vm2.LuaError;
|
import org.luaj.vm2.LuaError;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
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.compiler.LuaC;
|
import org.luaj.vm2.compiler.LuaC;
|
||||||
import org.luaj.vm2.lib.LibFunction;
|
import org.luaj.vm2.lib.LibFunction;
|
||||||
import org.luaj.vm2.lib.PackageLib;
|
import org.luaj.vm2.lib.PackageLib;
|
||||||
import org.luaj.vm2.lib.ThreeArgFunction;
|
|
||||||
import org.luaj.vm2.lib.TwoArgFunction;
|
|
||||||
import org.luaj.vm2.lib.VarArgFunction;
|
import org.luaj.vm2.lib.VarArgFunction;
|
||||||
|
import org.luaj.vm2.lib.jme.JmePlatform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the features of the luajava package.
|
* Subclass of {@link LibFunction} which implements the features of the luajava package.
|
||||||
@@ -124,7 +118,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
}
|
}
|
||||||
case BINDCLASS: {
|
case BINDCLASS: {
|
||||||
final Class clazz = classForName(args.checkjstring(1));
|
final Class clazz = classForName(args.checkjstring(1));
|
||||||
return toUserdata( clazz, clazz );
|
return JavaClass.forClass(clazz);
|
||||||
}
|
}
|
||||||
case NEWINSTANCE:
|
case NEWINSTANCE:
|
||||||
case NEW: {
|
case NEW: {
|
||||||
@@ -132,16 +126,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
final LuaValue c = args.checkvalue(1);
|
final LuaValue c = args.checkvalue(1);
|
||||||
final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
|
final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
|
||||||
final Varargs consargs = args.subargs(2);
|
final Varargs consargs = args.subargs(2);
|
||||||
final long paramssig = LuajavaLib.paramsSignatureOf( consargs );
|
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
|
||||||
final Constructor con = resolveConstructor( clazz, paramssig );
|
|
||||||
final boolean isvarargs = ((con.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
|
|
||||||
|
|
||||||
// coerce args, construct instance
|
|
||||||
final Object[] cargs = CoerceLuaToJava.coerceArgs( consargs, con.getParameterTypes(), isvarargs );
|
|
||||||
final Object o = con.newInstance( cargs );
|
|
||||||
|
|
||||||
// return result
|
|
||||||
return toUserdata( o, clazz );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case CREATEPROXY: {
|
case CREATEPROXY: {
|
||||||
@@ -179,7 +164,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
v[i] = CoerceJavaToLua.coerce(args[i]);
|
v[i] = CoerceJavaToLua.coerce(args[i]);
|
||||||
}
|
}
|
||||||
LuaValue result = func.invoke(v).arg1();
|
LuaValue result = func.invoke(v).arg1();
|
||||||
return CoerceLuaToJava.coerceArg(result, method.getReturnType());
|
return CoerceLuaToJava.coerce(result, method.getReturnType());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -218,258 +203,5 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
protected Class classForName(String name) throws ClassNotFoundException {
|
protected Class classForName(String name) throws ClassNotFoundException {
|
||||||
return Class.forName(name, true, ClassLoader.getSystemClassLoader());
|
return Class.forName(name, true, ClassLoader.getSystemClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
// params signature is
|
|
||||||
// - low 6-bits are number of parameters
|
|
||||||
// - each of next 9 6-bit fields encode a parameter type:
|
|
||||||
// - low 4 bits are lua type
|
|
||||||
// - high 2 bits are number of indexes deep (0,1,2, or 3)
|
|
||||||
|
|
||||||
public static long paramsSignatureOf( Varargs args ) {
|
|
||||||
long sig = 0;
|
|
||||||
int narg = args.narg();
|
|
||||||
int n = Math.min( narg, 9 );
|
|
||||||
for ( int i=1; i<=n; i++ ) {
|
|
||||||
LuaValue a = args.arg(i);
|
|
||||||
sig |= (paramTypeOf(a) << (i*6));
|
|
||||||
}
|
|
||||||
return sig | Math.min( narg, 0x3F );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int paramTypeOf( LuaValue arg ) {
|
|
||||||
int type = arg.type();
|
|
||||||
int tabledepth = 0;
|
|
||||||
if ( type == TTABLE ) {
|
|
||||||
for ( tabledepth=1; (type=(arg=arg.get(1)).type()) == TTABLE && (tabledepth<3); )
|
|
||||||
++tabledepth;
|
|
||||||
}
|
|
||||||
if ( type == TNUMBER && arg.isinttype() )
|
|
||||||
type = TINT;
|
|
||||||
if ( type == TUSERDATA ) {
|
|
||||||
Class c = arg.touserdata().getClass();
|
|
||||||
for ( ; c.isArray() && (tabledepth<3); ) {
|
|
||||||
c = c.getComponentType();
|
|
||||||
++tabledepth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (type & 0xF) | (tabledepth << 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int paramsCountFromSig( long paramssig ) {
|
|
||||||
return ((int) paramssig) & 0x3F;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int paramTypeFromSig(long paramssig, int argindex) {
|
|
||||||
return ((int) (paramssig>>(6*(argindex+1)))) & 0x3F;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int paramBaseTypeFromParamType(int paramType) {
|
|
||||||
int t = paramType & 0xf;
|
|
||||||
return t == (TINT & 0xF)? TINT: t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int paramDepthFromParamType(int paramType) {
|
|
||||||
return (paramType >> 4) & 0x3;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int paramComponentTypeOfParamType(int paramType) {
|
|
||||||
int b = paramBaseTypeFromParamType( paramType );
|
|
||||||
int d = paramDepthFromParamType( paramType );
|
|
||||||
d = d>0? d-1: 0;
|
|
||||||
return (d<<4) | (b&0xF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static LuaUserdata toUserdata(Object instance, final Class clazz) {
|
|
||||||
LuaTable mt = (LuaTable) classMetatables.get(clazz);
|
|
||||||
if ( mt == null ) {
|
|
||||||
mt = new LuaTable();
|
|
||||||
mt.set( LuaValue.INDEX, new TwoArgFunction() {
|
|
||||||
private Map methods;
|
|
||||||
public LuaValue call(LuaValue table, LuaValue key) {
|
|
||||||
Object instance = table.touserdata();
|
|
||||||
if ( key.isinttype() ) {
|
|
||||||
if ( clazz.isArray() ) {
|
|
||||||
int index = key.toint() - 1;
|
|
||||||
if ( index >= 0 && index < Array.getLength(instance) )
|
|
||||||
return CoerceJavaToLua.coerce( Array.get(instance, index) );
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String s = key.tojstring();
|
|
||||||
try {
|
|
||||||
Field f = clazz.getField(s);
|
|
||||||
Object o = f.get(instance);
|
|
||||||
return CoerceJavaToLua.coerce( o );
|
|
||||||
} catch (NoSuchFieldException nsfe) {
|
|
||||||
if ( clazz.isArray() && key.equals(LENGTH) )
|
|
||||||
return LuaValue.valueOf( Array.getLength(instance) );
|
|
||||||
if ( methods == null )
|
|
||||||
methods = new HashMap();
|
|
||||||
LMethod m = (LMethod) methods.get(s);
|
|
||||||
if ( m == null ) {
|
|
||||||
m = new LMethod(clazz,s);
|
|
||||||
// not safe - param list needs to
|
|
||||||
// distinguish between more cases
|
|
||||||
// methods.put(s, m);
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new LuaError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mt.set( LuaValue.NEWINDEX, new ThreeArgFunction() {
|
|
||||||
public LuaValue call(LuaValue table, LuaValue key, LuaValue val) {
|
|
||||||
Object instance = table.touserdata();
|
|
||||||
if ( key.isinttype() ) {
|
|
||||||
if ( clazz.isArray() ) {
|
|
||||||
Object v = CoerceLuaToJava.coerceArg(val, clazz.getComponentType());
|
|
||||||
int index = key.toint() - 1;
|
|
||||||
if ( index >= 0 && index < Array.getLength(instance) )
|
|
||||||
Array.set(instance, index, v);
|
|
||||||
else
|
|
||||||
throw new LuaError("array bounds exceeded "+index);
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String s = key.tojstring();
|
|
||||||
try {
|
|
||||||
Field f = clazz.getField(s);
|
|
||||||
Object v = CoerceLuaToJava.coerceArg(val, f.getType());
|
|
||||||
f.set(table.checkuserdata(Object.class),v);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new LuaError(e);
|
|
||||||
}
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
classMetatables.put(clazz, mt);
|
|
||||||
}
|
|
||||||
return LuaValue.userdataOf(instance,mt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class LMethod extends VarArgFunction {
|
|
||||||
private final Class clazz;
|
|
||||||
private final String s;
|
|
||||||
private LMethod(Class clazz, String s) {
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.s = s;
|
|
||||||
}
|
|
||||||
public String tojstring() {
|
|
||||||
return clazz.getName()+"."+s+"()";
|
|
||||||
}
|
|
||||||
public Varargs invoke(Varargs args) {
|
|
||||||
try {
|
|
||||||
// find the method
|
|
||||||
final Object instance = args.touserdata(1);
|
|
||||||
final Varargs methargs = args.subargs(2);
|
|
||||||
final long paramssig = LuajavaLib.paramsSignatureOf(methargs);
|
|
||||||
final Method meth = resolveMethod( clazz, s, paramssig );
|
|
||||||
final boolean isvarargs = ((meth.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
|
|
||||||
|
|
||||||
// coerce the arguments
|
|
||||||
final Object[] margs = CoerceLuaToJava.coerceArgs( methargs, meth.getParameterTypes(), isvarargs );
|
|
||||||
final Object result = meth.invoke( instance, margs );
|
|
||||||
|
|
||||||
// coerce the result
|
|
||||||
return CoerceJavaToLua.coerce(result);
|
|
||||||
} catch (InvocationTargetException ite) {
|
|
||||||
throw new LuaError(ite.getTargetException());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new LuaError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Constructor resolveConstructor(Class clazz, long paramssig ) {
|
|
||||||
|
|
||||||
// get the cache
|
|
||||||
Map cache = (Map) consCache.get( clazz );
|
|
||||||
if ( cache == null )
|
|
||||||
consCache.put( clazz, cache = new HashMap() );
|
|
||||||
|
|
||||||
// look up in the cache
|
|
||||||
Constructor c = (Constructor) cache.get( Long.valueOf(paramssig) );
|
|
||||||
if ( c != null )
|
|
||||||
return c;
|
|
||||||
|
|
||||||
// get index
|
|
||||||
Constructor[] cons = (Constructor[]) consIndex.get( clazz );
|
|
||||||
if ( cons == null ) {
|
|
||||||
consIndex.put( clazz, cons = clazz.getConstructors() );
|
|
||||||
if ( cons == null )
|
|
||||||
throw new IllegalArgumentException("no public constructors");
|
|
||||||
}
|
|
||||||
|
|
||||||
// find constructor with best score
|
|
||||||
int bests = Integer.MAX_VALUE;
|
|
||||||
int besti = 0;
|
|
||||||
for ( int i=0, size=cons.length; i<size; i++ ) {
|
|
||||||
Constructor con = cons[i];
|
|
||||||
int s = CoerceLuaToJava.scoreParamTypes(paramssig, con.getParameterTypes());
|
|
||||||
if ( s < bests ) {
|
|
||||||
bests = s;
|
|
||||||
besti = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// put into cache
|
|
||||||
c = cons[besti];
|
|
||||||
cache.put( Long.valueOf(paramssig), c );
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Method resolveMethod(Class clazz, String methodName, long paramssig ) {
|
|
||||||
|
|
||||||
// get the cache
|
|
||||||
Map nameCache = (Map) methCache.get( clazz );
|
|
||||||
if ( nameCache == null )
|
|
||||||
methCache.put( clazz, nameCache = new HashMap() );
|
|
||||||
Map cache = (Map) nameCache.get( methodName );
|
|
||||||
if ( cache == null )
|
|
||||||
nameCache.put( methodName, cache = new HashMap() );
|
|
||||||
|
|
||||||
// look up in the cache
|
|
||||||
Method m = (Method) cache.get( Long.valueOf(paramssig) );
|
|
||||||
if ( m != null )
|
|
||||||
return m;
|
|
||||||
|
|
||||||
// get index
|
|
||||||
Map index = (Map) methIndex.get( clazz );
|
|
||||||
if ( index == null ) {
|
|
||||||
methIndex.put( clazz, index = new HashMap() );
|
|
||||||
Method[] meths = clazz.getMethods();
|
|
||||||
for ( int i=0; i<meths.length; i++ ) {
|
|
||||||
Method meth = meths[i];
|
|
||||||
String s = meth.getName();
|
|
||||||
List list = (List) index.get(s);
|
|
||||||
if ( list == null )
|
|
||||||
index.put( s, list = new ArrayList() );
|
|
||||||
list.add( meth );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out best list of arguments == supplied args
|
|
||||||
List list = (List) index.get(methodName);
|
|
||||||
if ( list == null )
|
|
||||||
throw new IllegalArgumentException("no method named '"+methodName+"'");
|
|
||||||
|
|
||||||
// find method with best score
|
|
||||||
int bests = Integer.MAX_VALUE;
|
|
||||||
int besti = 0;
|
|
||||||
for ( int i=0, size=list.size(); i<size; i++ ) {
|
|
||||||
Method meth = (Method) list.get(i);
|
|
||||||
int s = CoerceLuaToJava.scoreParamTypes(paramssig, meth.getParameterTypes());
|
|
||||||
if ( s < bests ) {
|
|
||||||
bests = s;
|
|
||||||
besti = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// put into cache
|
|
||||||
m = (Method) list.get(besti);
|
|
||||||
cache.put( Long.valueOf(paramssig), m );
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,7 @@ import org.luaj.vm2.compiler.DumpLoadEndianIntTest;
|
|||||||
import org.luaj.vm2.compiler.RegressionTests;
|
import org.luaj.vm2.compiler.RegressionTests;
|
||||||
import org.luaj.vm2.compiler.SimpleTests;
|
import org.luaj.vm2.compiler.SimpleTests;
|
||||||
import org.luaj.vm2.lib.jse.LuaJavaCoercionTest;
|
import org.luaj.vm2.lib.jse.LuaJavaCoercionTest;
|
||||||
|
import org.luaj.vm2.lib.jse.LuajavaClassMembersTest;
|
||||||
import org.luaj.vm2.vm1.Luajvm1CompatibilityTest;
|
import org.luaj.vm2.vm1.Luajvm1CompatibilityTest;
|
||||||
|
|
||||||
public class AllTests {
|
public class AllTests {
|
||||||
@@ -72,6 +73,7 @@ public class AllTests {
|
|||||||
|
|
||||||
// library tests
|
// library tests
|
||||||
TestSuite lib = new TestSuite("Library Tests");
|
TestSuite lib = new TestSuite("Library Tests");
|
||||||
|
lib.addTestSuite(LuajavaClassMembersTest.class);
|
||||||
lib.addTestSuite(LuaJavaCoercionTest.class);
|
lib.addTestSuite(LuaJavaCoercionTest.class);
|
||||||
lib.addTestSuite(RequireClassTest.class);
|
lib.addTestSuite(RequireClassTest.class);
|
||||||
suite.addTest(lib);
|
suite.addTest(lib);
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
|
|
||||||
public void testLuaIntToJavaInt() {
|
public void testLuaIntToJavaInt() {
|
||||||
LuaInteger i = LuaInteger.valueOf(777);
|
LuaInteger i = LuaInteger.valueOf(777);
|
||||||
Object o = CoerceLuaToJava.coerceArg(i, int.class);
|
Object o = CoerceLuaToJava.coerce(i, int.class);
|
||||||
assertEquals( Integer.class, o.getClass() );
|
assertEquals( Integer.class, o.getClass() );
|
||||||
assertEquals( 777, ((Number)o).intValue() );
|
assertEquals( 777, ((Number)o).intValue() );
|
||||||
o = CoerceLuaToJava.coerceArg(i, Integer.class);
|
o = CoerceLuaToJava.coerce(i, Integer.class);
|
||||||
assertEquals( Integer.class, o.getClass() );
|
assertEquals( Integer.class, o.getClass() );
|
||||||
assertEquals( new Integer(777), o );
|
assertEquals( new Integer(777), o );
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
|
|
||||||
public void testLuaStringToJavaString() {
|
public void testLuaStringToJavaString() {
|
||||||
LuaString s = LuaValue.valueOf("777");
|
LuaString s = LuaValue.valueOf("777");
|
||||||
Object o = CoerceLuaToJava.coerceArg(s, String.class);
|
Object o = CoerceLuaToJava.coerce(s, String.class);
|
||||||
assertEquals( String.class, o.getClass() );
|
assertEquals( String.class, o.getClass() );
|
||||||
assertEquals( "777", o );
|
assertEquals( "777", o );
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,7 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
public void testJavaIntArrayToLuaTable() {
|
public void testJavaIntArrayToLuaTable() {
|
||||||
int[] i = { 222, 333 };
|
int[] i = { 222, 333 };
|
||||||
LuaValue v = CoerceJavaToLua.coerce(i);
|
LuaValue v = CoerceJavaToLua.coerce(i);
|
||||||
assertEquals( LuaUserdata.class, v.getClass() );
|
assertEquals( JavaArray.class, v.getClass() );
|
||||||
assertNotNull( v.getmetatable() );
|
|
||||||
assertEquals( LuaInteger.valueOf(222), v.get(ONE) );
|
assertEquals( LuaInteger.valueOf(222), v.get(ONE) );
|
||||||
assertEquals( LuaInteger.valueOf(333), v.get(TWO) );
|
assertEquals( LuaInteger.valueOf(333), v.get(TWO) );
|
||||||
assertEquals( TWO, v.get(LENGTH));
|
assertEquals( TWO, v.get(LENGTH));
|
||||||
@@ -90,7 +89,7 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
t.set(1, LuaInteger.valueOf(222) );
|
t.set(1, LuaInteger.valueOf(222) );
|
||||||
t.set(2, LuaInteger.valueOf(333) );
|
t.set(2, LuaInteger.valueOf(333) );
|
||||||
int[] i = null;
|
int[] i = null;
|
||||||
Object o = CoerceLuaToJava.coerceArg(t, int[].class);
|
Object o = CoerceLuaToJava.coerce(t, int[].class);
|
||||||
assertEquals( int[].class, o.getClass() );
|
assertEquals( int[].class, o.getClass() );
|
||||||
i = (int[]) o;
|
i = (int[]) o;
|
||||||
assertEquals( 2, i.length );
|
assertEquals( 2, i.length );
|
||||||
@@ -98,48 +97,52 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
assertEquals( 333, i[1] );
|
assertEquals( 333, i[1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIntArrayScoringTables() {
|
||||||
public void testArrayParamScoring() {
|
int a = 5;
|
||||||
|
LuaValue la = LuaInteger.valueOf(a);
|
||||||
|
LuaTable tb = new LuaTable();
|
||||||
|
tb.set( 1, la );
|
||||||
|
LuaTable tc = new LuaTable();
|
||||||
|
tc.set( 1, tb );
|
||||||
|
|
||||||
|
int saa = CoerceLuaToJava.getCoercion(int.class).score(la);
|
||||||
|
int sab = CoerceLuaToJava.getCoercion(int[].class).score(la);
|
||||||
|
int sac = CoerceLuaToJava.getCoercion(int[][].class).score(la);
|
||||||
|
assertTrue( saa < sab );
|
||||||
|
assertTrue( saa < sac );
|
||||||
|
int sba = CoerceLuaToJava.getCoercion(int.class).score(tb);
|
||||||
|
int sbb = CoerceLuaToJava.getCoercion(int[].class).score(tb);
|
||||||
|
int sbc = CoerceLuaToJava.getCoercion(int[][].class).score(tb);
|
||||||
|
assertTrue( sbb < sba );
|
||||||
|
assertTrue( sbb < sbc );
|
||||||
|
int sca = CoerceLuaToJava.getCoercion(int.class).score(tc);
|
||||||
|
int scb = CoerceLuaToJava.getCoercion(int[].class).score(tc);
|
||||||
|
int scc = CoerceLuaToJava.getCoercion(int[][].class).score(tc);
|
||||||
|
assertTrue( scc < sca );
|
||||||
|
assertTrue( scc < scb );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIntArrayScoringUserdata() {
|
||||||
int a = 5;
|
int a = 5;
|
||||||
int[] b = { 44, 66 };
|
int[] b = { 44, 66 };
|
||||||
int[][] c = { { 11, 22 }, { 33, 44 } };
|
int[][] c = { { 11, 22 }, { 33, 44 } };
|
||||||
LuaValue la = LuaInteger.valueOf(a);
|
|
||||||
LuaTable tb = new LuaTable();
|
|
||||||
LuaTable tc = new LuaTable();
|
|
||||||
LuaValue va = CoerceJavaToLua.coerce(a);
|
LuaValue va = CoerceJavaToLua.coerce(a);
|
||||||
LuaValue vb = CoerceJavaToLua.coerce(b);
|
LuaValue vb = CoerceJavaToLua.coerce(b);
|
||||||
LuaValue vc = CoerceJavaToLua.coerce(c);
|
LuaValue vc = CoerceJavaToLua.coerce(c);
|
||||||
tc.set( 1, new LuaTable() );
|
|
||||||
|
int vaa = CoerceLuaToJava.getCoercion(int.class).score(va);
|
||||||
int saa = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(la), new Class[] { int.class } );
|
int vab = CoerceLuaToJava.getCoercion(int[].class).score(va);
|
||||||
int sab = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(la), new Class[] { int[].class } );
|
int vac = CoerceLuaToJava.getCoercion(int[][].class).score(va);
|
||||||
int sac = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(la), new Class[] { int[][].class } );
|
|
||||||
assertTrue( saa < sab );
|
|
||||||
assertTrue( saa < sac );
|
|
||||||
int sba = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(tb), new Class[] { int.class } );
|
|
||||||
int sbb = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(tb), new Class[] { int[].class } );
|
|
||||||
int sbc = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(tb), new Class[] { int[][].class } );
|
|
||||||
assertTrue( sbb < sba );
|
|
||||||
assertTrue( sbb < sbc );
|
|
||||||
int sca = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(tc), new Class[] { int.class } );
|
|
||||||
int scb = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(tc), new Class[] { int[].class } );
|
|
||||||
int scc = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(tc), new Class[] { int[][].class } );
|
|
||||||
assertTrue( scc < sca );
|
|
||||||
assertTrue( scc < scb );
|
|
||||||
|
|
||||||
int vaa = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(va), new Class[] { int.class } );
|
|
||||||
int vab = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(va), new Class[] { int[].class } );
|
|
||||||
int vac = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(va), new Class[] { int[][].class } );
|
|
||||||
assertTrue( vaa < vab );
|
assertTrue( vaa < vab );
|
||||||
assertTrue( vaa < vac );
|
assertTrue( vaa < vac );
|
||||||
int vba = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(vb), new Class[] { int.class } );
|
int vba = CoerceLuaToJava.getCoercion(int.class).score(vb);
|
||||||
int vbb = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(vb), new Class[] { int[].class } );
|
int vbb = CoerceLuaToJava.getCoercion(int[].class).score(vb);
|
||||||
int vbc = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(vb), new Class[] { int[][].class } );
|
int vbc = CoerceLuaToJava.getCoercion(int[][].class).score(vb);
|
||||||
assertTrue( vbb < vba );
|
assertTrue( vbb < vba );
|
||||||
assertTrue( vbb < vbc );
|
assertTrue( vbb < vbc );
|
||||||
int vca = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(vc), new Class[] { int.class } );
|
int vca = CoerceLuaToJava.getCoercion(int.class).score(vc);
|
||||||
int vcb = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(vc), new Class[] { int[].class } );
|
int vcb = CoerceLuaToJava.getCoercion(int[].class).score(vc);
|
||||||
int vcc = CoerceLuaToJava.scoreParamTypes( LuajavaLib.paramsSignatureOf(vc), new Class[] { int[][].class } );
|
int vcc = CoerceLuaToJava.getCoercion(int[][].class).score(vc);
|
||||||
assertTrue( vcc < vca );
|
assertTrue( vcc < vca );
|
||||||
assertTrue( vcc < vcb );
|
assertTrue( vcc < vcb );
|
||||||
}
|
}
|
||||||
@@ -151,27 +154,30 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
public String sample(int[][] a) { return "int-array-array-args "+a[0][0]+","+a[0][1]+","+a[1][0]+","+a[1][1]; }
|
public String sample(int[][] a) { return "int-array-array-args "+a[0][0]+","+a[0][1]+","+a[1][0]+","+a[1][1]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMatchVoidArgs() {
|
||||||
public void testIntArrayParameterMatching() {
|
|
||||||
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
|
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
|
||||||
|
|
||||||
// get sample field, call with no arguments
|
|
||||||
LuaValue result = v.method("sample");
|
LuaValue result = v.method("sample");
|
||||||
assertEquals( "void-args", result.toString() );
|
assertEquals( "void-args", result.toString() );
|
||||||
|
}
|
||||||
// get sample field, call with one arguments
|
|
||||||
|
public void testMatchIntArgs() {
|
||||||
|
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
|
||||||
LuaValue arg = CoerceJavaToLua.coerce(new Integer(123));
|
LuaValue arg = CoerceJavaToLua.coerce(new Integer(123));
|
||||||
result = v.method("sample",arg);
|
LuaValue result = v.method("sample",arg);
|
||||||
assertEquals( "int-args 123", result.toString() );
|
assertEquals( "int-args 123", result.toString() );
|
||||||
|
}
|
||||||
// get sample field, call with array argument
|
|
||||||
arg = CoerceJavaToLua.coerce(new int[]{345,678});
|
public void testMatchIntArrayArgs() {
|
||||||
result = v.method("sample",arg);
|
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
|
||||||
|
LuaValue arg = CoerceJavaToLua.coerce(new int[]{345,678});
|
||||||
|
LuaValue result = v.method("sample",arg);
|
||||||
assertEquals( "int-array-args 345,678", result.toString() );
|
assertEquals( "int-array-args 345,678", result.toString() );
|
||||||
|
}
|
||||||
// get sample field, call with two-d array argument
|
|
||||||
arg = CoerceJavaToLua.coerce(new int[][]{{22,33},{44,55}});
|
public void testMatchIntArrayArrayArgs() {
|
||||||
result = v.method("sample",arg);
|
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
|
||||||
|
LuaValue arg = CoerceJavaToLua.coerce(new int[][]{{22,33},{44,55}});
|
||||||
|
LuaValue result = v.method("sample",arg);
|
||||||
assertEquals( "int-array-array-args 22,33,44,55", result.toString() );
|
assertEquals( "int-array-array-args 22,33,44,55", result.toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +194,8 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testExceptionMessage() {
|
public void testExceptionMessage() {
|
||||||
String script = "return pcall( luajava.bindClass( \""+SomeClass.class.getName()+"\").someMethod )";
|
String script = "local c = luajava.bindClass( \""+SomeClass.class.getName()+"\" )\n" +
|
||||||
|
"return pcall( c.someMethod, c )";
|
||||||
Varargs vresult = _G.get("loadstring").call(LuaValue.valueOf(script)).invoke(LuaValue.NONE);
|
Varargs vresult = _G.get("loadstring").call(LuaValue.valueOf(script)).invoke(LuaValue.NONE);
|
||||||
LuaValue status = vresult.arg1();
|
LuaValue status = vresult.arg1();
|
||||||
LuaValue message = vresult.arg(2);
|
LuaValue message = vresult.arg(2);
|
||||||
@@ -198,7 +205,7 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testLuaErrorCause() {
|
public void testLuaErrorCause() {
|
||||||
String script = "luajava.bindClass( \""+SomeClass.class.getName()+"\").someMethod()";
|
String script = "luajava.bindClass( \""+SomeClass.class.getName()+"\"):someMethod()";
|
||||||
LuaValue chunk = _G.get("loadstring").call(LuaValue.valueOf(script));
|
LuaValue chunk = _G.get("loadstring").call(LuaValue.valueOf(script));
|
||||||
try {
|
try {
|
||||||
chunk.invoke(LuaValue.NONE);
|
chunk.invoke(LuaValue.NONE);
|
||||||
@@ -267,16 +274,20 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
assertEquals( "152415787532388367501905199875019052100", sc );
|
assertEquals( "152415787532388367501905199875019052100", sc );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class A {
|
public interface IA {}
|
||||||
|
public interface IB extends IA {}
|
||||||
|
public interface IC extends IB {}
|
||||||
|
|
||||||
|
public static class A implements IA {
|
||||||
}
|
}
|
||||||
public static class B extends A{
|
public static class B extends A implements IB {
|
||||||
public String set( Object x ) { return "set(Object) "; }
|
public String set( Object x ) { return "set(Object) "; }
|
||||||
public String set( String x ) { return "set(String) "+x; }
|
public String set( String x ) { return "set(String) "+x; }
|
||||||
public String set( A x ) { return "set(A) "; }
|
public String set( A x ) { return "set(A) "; }
|
||||||
public String set( B x ) { return "set(B) "; }
|
public String set( B x ) { return "set(B) "; }
|
||||||
public String set( C x ) { return "set(C) "; }
|
public String set( C x ) { return "set(C) "; }
|
||||||
public String set( byte x ) { return "set(byte) "+x; }
|
public String set( byte x ) { return "set(byte) "+x; }
|
||||||
public String set( char x ) { return "set(char) "+x; }
|
public String set( char x ) { return "set(char) "+(int)x; }
|
||||||
public String set( short x ) { return "set(short) "+x; }
|
public String set( short x ) { return "set(short) "+x; }
|
||||||
public String set( int x ) { return "set(int) "+x; }
|
public String set( int x ) { return "set(int) "+x; }
|
||||||
public String set( long x ) { return "set(long) "+x; }
|
public String set( long x ) { return "set(long) "+x; }
|
||||||
@@ -288,7 +299,7 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
public String setr( long x ) { return "setr(long) "+x; }
|
public String setr( long x ) { return "setr(long) "+x; }
|
||||||
public String setr( int x ) { return "setr(int) "+x; }
|
public String setr( int x ) { return "setr(int) "+x; }
|
||||||
public String setr( short x ) { return "setr(short) "+x; }
|
public String setr( short x ) { return "setr(short) "+x; }
|
||||||
public String setr( char x ) { return "setr(char) "+x; }
|
public String setr( char x ) { return "setr(char) "+(int)x; }
|
||||||
public String setr( byte x ) { return "setr(byte) "+x; }
|
public String setr( byte x ) { return "setr(byte) "+x; }
|
||||||
public String setr( C x ) { return "setr(C) "; }
|
public String setr( C x ) { return "setr(C) "; }
|
||||||
public String setr( B x ) { return "setr(B) "; }
|
public String setr( B x ) { return "setr(B) "; }
|
||||||
@@ -298,18 +309,21 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
|
|
||||||
public Object getObject() { return new Object(); }
|
public Object getObject() { return new Object(); }
|
||||||
public String getString() { return "abc"; }
|
public String getString() { return "abc"; }
|
||||||
|
public byte[] getbytearray() { return new byte[] { 1, 2, 3 }; }
|
||||||
public A getA() { return new A(); }
|
public A getA() { return new A(); }
|
||||||
public B getB() { return new B(); }
|
public B getB() { return new B(); }
|
||||||
public C getC() { return new C(); }
|
public C getC() { return new C(); }
|
||||||
public byte getbyte() { return 1; }
|
public byte getbyte() { return 1; }
|
||||||
public char getchar() { return 2; }
|
public char getchar() { return 65000; }
|
||||||
public short getshort() { return 3; }
|
public short getshort() { return -32000; }
|
||||||
public int getint() { return 4; }
|
public int getint() { return 100000; }
|
||||||
public long getlong() { return 5; }
|
public long getlong() { return 50000000000L; }
|
||||||
public float getfloat() { return 6.5f; }
|
public float getfloat() { return 6.5f; }
|
||||||
public double getdouble() { return 7.5; }
|
public double getdouble() { return Math.PI; }
|
||||||
}
|
}
|
||||||
public static class C extends B {
|
public static class C extends B implements IC {
|
||||||
|
}
|
||||||
|
public static class D extends C implements IA {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOverloadedJavaMethodObject() { doOverloadedMethodTest( "Object", "" ); }
|
public void testOverloadedJavaMethodObject() { doOverloadedMethodTest( "Object", "" ); }
|
||||||
@@ -318,12 +332,12 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
public void testOverloadedJavaMethodB() { doOverloadedMethodTest( "B", "" ); }
|
public void testOverloadedJavaMethodB() { doOverloadedMethodTest( "B", "" ); }
|
||||||
public void testOverloadedJavaMethodC() { doOverloadedMethodTest( "C", "" ); }
|
public void testOverloadedJavaMethodC() { doOverloadedMethodTest( "C", "" ); }
|
||||||
public void testOverloadedJavaMethodByte() { doOverloadedMethodTest( "byte", "1" ); }
|
public void testOverloadedJavaMethodByte() { doOverloadedMethodTest( "byte", "1" ); }
|
||||||
public void testOverloadedJavaMethodChar() { doOverloadedMethodTest( "char", "2" ); }
|
public void testOverloadedJavaMethodChar() { doOverloadedMethodTest( "char", "65000" ); }
|
||||||
public void testOverloadedJavaMethodShort() { doOverloadedMethodTest( "short", "3" ); }
|
public void testOverloadedJavaMethodShort() { doOverloadedMethodTest( "short", "-32000" ); }
|
||||||
public void testOverloadedJavaMethodInt() { doOverloadedMethodTest( "int", "4" ); }
|
public void testOverloadedJavaMethodInt() { doOverloadedMethodTest( "int", "100000" ); }
|
||||||
public void testOverloadedJavaMethodLong() { doOverloadedMethodTest( "long", "5" ); }
|
public void testOverloadedJavaMethodLong() { doOverloadedMethodTest( "long", "50000000000" ); }
|
||||||
public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest( "float", "6.5" ); }
|
public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest( "float", "6.5" ); }
|
||||||
public void testOverloadedJavaMethodDouble() { doOverloadedMethodTest( "double", "7.5" ); }
|
public void testOverloadedJavaMethodDouble() { doOverloadedMethodTest( "double", "3.141592653589793" ); }
|
||||||
|
|
||||||
private void doOverloadedMethodTest( String typename, String value ) {
|
private void doOverloadedMethodTest( String typename, String value ) {
|
||||||
String script =
|
String script =
|
||||||
@@ -344,5 +358,50 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
assertEquals( "set("+typename+") "+value, sb );
|
assertEquals( "set("+typename+") "+value, sb );
|
||||||
assertEquals( "setr("+typename+") "+value, sc );
|
assertEquals( "setr("+typename+") "+value, sc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testClassInheritanceLevels() {
|
||||||
|
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(Object.class, Object.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, String.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, A.class) );
|
||||||
|
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(Object.class, B.class) );
|
||||||
|
assertEquals( 3, CoerceLuaToJava.inheritanceLevels(Object.class, C.class) );
|
||||||
|
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, Object.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, String.class) );
|
||||||
|
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(A.class, A.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(A.class, B.class) );
|
||||||
|
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(A.class, C.class) );
|
||||||
|
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, Object.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, String.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, A.class) );
|
||||||
|
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(B.class, B.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(B.class, C.class) );
|
||||||
|
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, Object.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, String.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, A.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, B.class) );
|
||||||
|
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(C.class, C.class) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInterfaceInheritanceLevels() {
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, A.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IB.class, B.class) );
|
||||||
|
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IA.class, B.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IC.class, C.class) );
|
||||||
|
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IB.class, C.class) );
|
||||||
|
assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IA.class, C.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, D.class) );
|
||||||
|
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IC.class, D.class) );
|
||||||
|
assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IB.class, D.class) );
|
||||||
|
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, A.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, A.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, B.class) );
|
||||||
|
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, IA.class) );
|
||||||
|
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, IB.class) );
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
226
test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java
Normal file
226
test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
|
public class LuajavaClassMembersTest extends TestCase {
|
||||||
|
public static class A {
|
||||||
|
protected A() {}
|
||||||
|
}
|
||||||
|
public static class B extends A {
|
||||||
|
public byte m_byte_field;
|
||||||
|
public int m_int_field;
|
||||||
|
public double m_double_field;
|
||||||
|
public String m_string_field;
|
||||||
|
|
||||||
|
protected B() {}
|
||||||
|
public B(int i) { m_int_field = i; }
|
||||||
|
|
||||||
|
public String setString( String x ) { return "setString(String) "+x; }
|
||||||
|
public String getString() { return "abc"; }
|
||||||
|
public int getint() { return 100000; }
|
||||||
|
|
||||||
|
public String uniq() { return "uniq()"; }
|
||||||
|
public String uniqs(String s) { return "uniqs(string:"+s+")"; }
|
||||||
|
public String uniqi(int i) { return "uniqi(int:"+i+")"; }
|
||||||
|
public String uniqsi(String s, int i) { return "uniqsi(string:"+s+",int:"+i+")"; }
|
||||||
|
public String uniqis(int i, String s) { return "uniqis(int:"+i+",string:"+s+")"; }
|
||||||
|
|
||||||
|
public String pick() { return "pick()"; }
|
||||||
|
public String pick(String s) { return "pick(string:"+s+")"; }
|
||||||
|
public String pick(int i) { return "pick(int:"+i+")"; }
|
||||||
|
public String pick(String s, int i) { return "pick(string:"+s+",int:"+i+")"; }
|
||||||
|
public String pick(int i, String s) { return "pick(int:"+i+",string:"+s+")"; }
|
||||||
|
|
||||||
|
public static String staticpick() { return "static-pick()"; }
|
||||||
|
public static String staticpick(String s) { return "static-pick(string:"+s+")"; }
|
||||||
|
public static String staticpick(int i) { return "static-pick(int:"+i+")"; }
|
||||||
|
public static String staticpick(String s, int i) { return "static-pick(string:"+s+",int:"+i+")"; }
|
||||||
|
public static String staticpick(int i, String s) { return "static-pick(int:"+i+",string:"+s+")"; }
|
||||||
|
}
|
||||||
|
public static class C extends B {
|
||||||
|
public C() {}
|
||||||
|
public C(String s) { m_string_field = s; }
|
||||||
|
public C(int i) { m_int_field = i; }
|
||||||
|
public C(String s, int i) { m_string_field = s; m_int_field = i; }
|
||||||
|
public int getint() { return 200000; }
|
||||||
|
|
||||||
|
public String pick(String s) { return "class-c-pick(string:"+s+")"; }
|
||||||
|
public String pick(int i) { return "class-c-pick(int:"+i+")"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static LuaValue ZERO = LuaValue.ZERO;
|
||||||
|
static LuaValue ONE = LuaValue.ONE;
|
||||||
|
static LuaValue PI = LuaValue.valueOf(Math.PI);
|
||||||
|
static LuaValue THREE = LuaValue.valueOf(3);
|
||||||
|
static LuaValue NUMS = LuaValue.valueOf(123);
|
||||||
|
static LuaValue ABC = LuaValue.valueOf("abc");
|
||||||
|
static LuaValue SOMEA = CoerceJavaToLua.coerce(new A());
|
||||||
|
static LuaValue SOMEB = CoerceJavaToLua.coerce(new B());
|
||||||
|
static LuaValue SOMEC = CoerceJavaToLua.coerce(new C());
|
||||||
|
|
||||||
|
public void testSetByteField() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance i = new JavaInstance(b);
|
||||||
|
i.set("m_byte_field", ONE ); assertEquals( 1, b.m_byte_field ); assertEquals( ONE, i.get("m_byte_field") );
|
||||||
|
i.set("m_byte_field", PI ); assertEquals( 3, b.m_byte_field ); assertEquals( THREE, i.get("m_byte_field") );
|
||||||
|
i.set("m_byte_field", ABC ); assertEquals( 0, b.m_byte_field ); assertEquals( ZERO, i.get("m_byte_field") );
|
||||||
|
}
|
||||||
|
public void testSetDoubleField() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance i = new JavaInstance(b);
|
||||||
|
i.set("m_double_field", ONE ); assertEquals( 1., b.m_double_field ); assertEquals( ONE, i.get("m_double_field") );
|
||||||
|
i.set("m_double_field", PI ); assertEquals( Math.PI, b.m_double_field ); assertEquals( PI, i.get("m_double_field") );
|
||||||
|
i.set("m_double_field", ABC ); assertEquals( 0., b.m_double_field ); assertEquals( ZERO, i.get("m_double_field") );
|
||||||
|
}
|
||||||
|
public void testNoFactory() {
|
||||||
|
JavaClass c = JavaClass.forClass(A.class);
|
||||||
|
try {
|
||||||
|
c.call();
|
||||||
|
fail( "did not throw lua error as expected" );
|
||||||
|
} catch ( LuaError e ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void testUniqueFactoryCoercible() {
|
||||||
|
JavaClass c = JavaClass.forClass(B.class);
|
||||||
|
assertEquals( JavaClass.class, c.getClass() );
|
||||||
|
LuaValue constr = c.get("new");
|
||||||
|
assertEquals( JavaConstructor.class, constr.getClass() );
|
||||||
|
LuaValue v = constr.call(NUMS);
|
||||||
|
Object b = v.touserdata();
|
||||||
|
assertEquals( B.class, b.getClass() );
|
||||||
|
assertEquals( 123, ((B)b).m_int_field );
|
||||||
|
Object b0 = constr.call().touserdata();
|
||||||
|
assertEquals( B.class, b0.getClass() );
|
||||||
|
assertEquals( 0, ((B)b0).m_int_field );
|
||||||
|
}
|
||||||
|
public void testUniqueFactoryUncoercible() {
|
||||||
|
JavaClass f = JavaClass.forClass(B.class);
|
||||||
|
LuaValue constr = f.get("new");
|
||||||
|
assertEquals( JavaConstructor.class, constr.getClass() );
|
||||||
|
try {
|
||||||
|
LuaValue v = constr.call(LuaValue.userdataOf(new Object()));
|
||||||
|
Object b = v.touserdata();
|
||||||
|
// fail( "did not throw lua error as expected" );
|
||||||
|
assertEquals( 0, ((B)b).m_int_field );
|
||||||
|
} catch ( LuaError e ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void testOverloadedFactoryCoercible() {
|
||||||
|
JavaClass f = JavaClass.forClass(C.class);
|
||||||
|
LuaValue constr = f.get("new");
|
||||||
|
assertEquals( JavaConstructor.Overload.class, constr.getClass() );
|
||||||
|
Object c = constr.call().touserdata();
|
||||||
|
Object ci = constr.call(LuaValue.valueOf(123)).touserdata();
|
||||||
|
Object cs = constr.call(LuaValue.valueOf("abc")).touserdata();
|
||||||
|
Object csi = constr.call( LuaValue.valueOf("def"), LuaValue.valueOf(456) ).touserdata();
|
||||||
|
assertEquals( C.class, c.getClass() );
|
||||||
|
assertEquals( C.class, ci.getClass() );
|
||||||
|
assertEquals( C.class, cs.getClass() );
|
||||||
|
assertEquals( C.class, csi.getClass() );
|
||||||
|
assertEquals( null, ((C)c).m_string_field );
|
||||||
|
assertEquals( 0, ((C)c).m_int_field );
|
||||||
|
assertEquals( "abc", ((C)cs).m_string_field );
|
||||||
|
assertEquals( 0, ((C)cs).m_int_field );
|
||||||
|
assertEquals( null, ((C)ci).m_string_field );
|
||||||
|
assertEquals( 123, ((C)ci).m_int_field );
|
||||||
|
assertEquals( "def", ((C)csi).m_string_field );
|
||||||
|
assertEquals( 456, ((C)csi).m_int_field );
|
||||||
|
}
|
||||||
|
public void testOverloadedFactoryUncoercible() {
|
||||||
|
JavaClass f = JavaClass.forClass(C.class);
|
||||||
|
try {
|
||||||
|
Object c = f.call(LuaValue.userdataOf(new Object()));
|
||||||
|
// fail( "did not throw lua error as expected" );
|
||||||
|
assertEquals( 0, ((C)c).m_int_field );
|
||||||
|
assertEquals( null, ((C)c).m_string_field );
|
||||||
|
} catch ( LuaError e ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNoAttribute() {
|
||||||
|
JavaClass f = JavaClass.forClass(A.class);
|
||||||
|
LuaValue v = f.get("bogus");
|
||||||
|
assertEquals( v, LuaValue.NIL );
|
||||||
|
try {
|
||||||
|
f.set("bogus",ONE);
|
||||||
|
fail( "did not throw lua error as expected" );
|
||||||
|
} catch ( LuaError e ) {}
|
||||||
|
}
|
||||||
|
public void testFieldAttributeCoercible() {
|
||||||
|
JavaInstance i = new JavaInstance(new B());
|
||||||
|
i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() );
|
||||||
|
i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() );
|
||||||
|
i = new JavaInstance(new C());
|
||||||
|
i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() );
|
||||||
|
i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() );
|
||||||
|
}
|
||||||
|
public void testUniqueMethodAttributeCoercible() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance ib = new JavaInstance(b);
|
||||||
|
LuaValue b_getString = ib.get("getString");
|
||||||
|
LuaValue b_getint = ib.get("getint");
|
||||||
|
assertEquals( JavaMethod.class, b_getString.getClass() );
|
||||||
|
assertEquals( JavaMethod.class, b_getint.getClass() );
|
||||||
|
assertEquals( "abc", b_getString.call(SOMEB).tojstring() );
|
||||||
|
assertEquals( 100000, b_getint.call(SOMEB).toint());
|
||||||
|
assertEquals( "abc", b_getString.call(SOMEC).tojstring() );
|
||||||
|
assertEquals( 200000, b_getint.call(SOMEC).toint());
|
||||||
|
}
|
||||||
|
public void testUniqueMethodAttributeArgsCoercible() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance ib = new JavaInstance(b);
|
||||||
|
LuaValue uniq = ib.get("uniq");
|
||||||
|
LuaValue uniqs = ib.get("uniqs");
|
||||||
|
LuaValue uniqi = ib.get("uniqi");
|
||||||
|
LuaValue uniqsi = ib.get("uniqsi");
|
||||||
|
LuaValue uniqis = ib.get("uniqis");
|
||||||
|
assertEquals( JavaMethod.class, uniq.getClass() );
|
||||||
|
assertEquals( JavaMethod.class, uniqs.getClass() );
|
||||||
|
assertEquals( JavaMethod.class, uniqi.getClass() );
|
||||||
|
assertEquals( JavaMethod.class, uniqsi.getClass() );
|
||||||
|
assertEquals( JavaMethod.class, uniqis.getClass() );
|
||||||
|
assertEquals( "uniq()", uniq.call(SOMEB).tojstring() );
|
||||||
|
assertEquals( "uniqs(string:abc)", uniqs.call(SOMEB,ABC).tojstring() );
|
||||||
|
assertEquals( "uniqi(int:1)", uniqi.call(SOMEB,ONE).tojstring() );
|
||||||
|
assertEquals( "uniqsi(string:abc,int:1)", uniqsi.call(SOMEB,ABC,ONE).tojstring() );
|
||||||
|
assertEquals( "uniqis(int:1,string:abc)", uniqis.call(SOMEB,ONE,ABC).tojstring() );
|
||||||
|
assertEquals( "uniqis(int:1,string:abc)", uniqis.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() );
|
||||||
|
}
|
||||||
|
public void testOverloadedMethodAttributeCoercible() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance ib = new JavaInstance(b);
|
||||||
|
LuaValue p = ib.get("pick");
|
||||||
|
assertEquals( "pick()", p.call(SOMEB).tojstring() );
|
||||||
|
assertEquals( "pick(string:abc)", p.call(SOMEB,ABC).tojstring() );
|
||||||
|
assertEquals( "pick(int:1)", p.call(SOMEB,ONE).tojstring() );
|
||||||
|
assertEquals( "pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() );
|
||||||
|
assertEquals( "pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() );
|
||||||
|
assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() );
|
||||||
|
}
|
||||||
|
public void testUnboundOverloadedMethodAttributeCoercible() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance ib = new JavaInstance(b);
|
||||||
|
LuaValue p = ib.get("pick");
|
||||||
|
assertEquals( JavaMethod.Overload.class, p.getClass() );
|
||||||
|
assertEquals( "pick()", p.call(SOMEC).tojstring() );
|
||||||
|
assertEquals( "class-c-pick(string:abc)", p.call(SOMEC,ABC).tojstring() );
|
||||||
|
assertEquals( "class-c-pick(int:1)", p.call(SOMEC,ONE).tojstring() );
|
||||||
|
assertEquals( "pick(string:abc,int:1)", p.call(SOMEC,ABC,ONE).tojstring() );
|
||||||
|
assertEquals( "pick(int:1,string:abc)", p.call(SOMEC,ONE,ABC).tojstring() );
|
||||||
|
assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEC,ONE,ABC,ONE})).arg1().tojstring() );
|
||||||
|
}
|
||||||
|
public void testOverloadedStaticMethodAttributeCoercible() {
|
||||||
|
B b = new B();
|
||||||
|
JavaInstance ib = new JavaInstance(b);
|
||||||
|
LuaValue p = ib.get("staticpick");
|
||||||
|
assertEquals( "static-pick()", p.call(SOMEB).tojstring() );
|
||||||
|
assertEquals( "static-pick(string:abc)", p.call(SOMEB,ABC).tojstring() );
|
||||||
|
assertEquals( "static-pick(int:1)", p.call(SOMEB,ONE).tojstring() );
|
||||||
|
assertEquals( "static-pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() );
|
||||||
|
assertEquals( "static-pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() );
|
||||||
|
assertEquals( "static-pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() );
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user