Mercurial Hosting > luan
changeset 1:2df768b926aa
start Luan
git-svn-id: https://luan-java.googlecode.com/svn/trunk@2 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Tue, 13 Nov 2012 05:54:32 +0000 |
parents | a89d06646ff3 |
children | 4da26b11d12a |
files | src/luan/Lua.java src/luan/LuaException.java src/luan/LuaFunction.java src/luan/LuaJavaFunction.java src/luan/LuaNumber.java src/luan/LuaTable.java |
diffstat | 6 files changed, 359 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/Lua.java Tue Nov 13 05:54:32 2012 +0000 @@ -0,0 +1,56 @@ +package luan; + + +public class Lua { + + public static String toString(Object obj) { + if( obj == null ) + return "nil"; + return obj.toString(); + } + + public static String type(Object obj) { + if( obj == null ) + return "nil"; + if( obj instanceof String ) + return "string"; + if( obj instanceof Boolean ) + return "boolean"; + if( obj instanceof LuaNumber ) + return "number"; + return "userdata"; + } + + public static int length(Object obj) throws LuaException { + if( obj instanceof String ) { + String s = (String)obj; + return s.length(); + } + if( obj instanceof LuaTable ) { + LuaTable t = (LuaTable)obj; + return t.length(); + } + throw new LuaException( "attempt to get length of a " + type(obj) + " value" ); + } + + static LuaNumber toNumber(Object obj) throws LuaException { + if( obj instanceof LuaNumber ) + return (LuaNumber)obj; + if( obj instanceof String ) { + String s = (String)obj; + try { + return new LuaNumber( Double.parseDouble(s) ); + } catch(NumberFormatException e) {} + } + throw new LuaException( "attempt to perform arithmetic on a " + type(obj) + " value" ); + } + + static LuaNumber add(Object n1,Object n2) throws LuaException { + return new LuaNumber( toNumber(n1).n + toNumber(n2).n ); + } + + static LuaNumber sub(Object n1,Object n2) throws LuaException { + return new LuaNumber( toNumber(n1).n - toNumber(n2).n ); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaException.java Tue Nov 13 05:54:32 2012 +0000 @@ -0,0 +1,10 @@ +package luan; + + +public class LuaException extends Exception { + + LuaException(String msg) { + super(msg); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaFunction.java Tue Nov 13 05:54:32 2012 +0000 @@ -0,0 +1,12 @@ +package luan; + + +public abstract class LuaFunction { + + public abstract Object[] call(Object... args); + + @Override public String toString() { + return "function: " + Integer.toHexString(hashCode()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaJavaFunction.java Tue Nov 13 05:54:32 2012 +0000 @@ -0,0 +1,209 @@ +package luan; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + + +public final class LuaJavaFunction extends LuaFunction { + private final Method method; + private final Object obj; + private final RtnConverter rtnConverter; + private final ArgConverter[] argConverters; + + public LuaJavaFunction(Method method,Object obj) { + this.method = method; + this.obj = obj; + rtnConverter = getRtnConverter(method); + argConverters = getArgConverters(method); + } + + public Object[] call(Object... args) { + args = fixArgs(args); + Object rtn; + try { + rtn = method.invoke(obj,args); + } catch(IllegalAccessException e) { + throw new RuntimeException(e); + } catch(InvocationTargetException e) { + throw new RuntimeException(e); + } + return rtnConverter.convert(rtn); + } + + private Object[] fixArgs(Object[] args) { + if( args.length != argConverters.length ) { + Object[] t = new Object[argConverters.length]; + System.arraycopy(args,0,t,0,Math.min(args.length,t.length)); + args = t; + } + for( int i=0; i<args.length; i++ ) { + args[i] = argConverters[i].convert(args[i]); + } + return args; + } + + + private interface RtnConverter { + public Object[] convert(Object obj); + } + + private static final Object[] EMPTY = new Object[0]; + + private static final RtnConverter RTN_EMPTY = new RtnConverter() { + public Object[] convert(Object obj) { + return EMPTY; + } + }; + + private static final RtnConverter RTN_SAME = new RtnConverter() { + public Object[] convert(Object obj) { + return new Object[]{obj}; + } + }; + + private static final RtnConverter RTN_NUMBER = new RtnConverter() { + public Object[] convert(Object obj) { + if( obj == null ) + return new Object[1]; + Number n = (Number)obj; + LuaNumber ln = new LuaNumber(n.doubleValue()); + return new Object[]{ln}; + } + }; + + private static RtnConverter getRtnConverter(Method m) { + Class<?> rtnType = m.getReturnType(); + if( rtnType == Void.TYPE ) + return RTN_EMPTY; + if( Number.class.isAssignableFrom(rtnType) + || rtnType == Short.TYPE + || rtnType == Integer.TYPE + || rtnType == Long.TYPE + || rtnType == Float.TYPE + || rtnType == Double.TYPE + ) + return RTN_NUMBER; + return RTN_SAME; + } + + + private interface ArgConverter { + public Object convert(Object obj); + } + + private static final ArgConverter ARG_SAME = new ArgConverter() { + public Object convert(Object obj) { + return obj; + } + }; + + private static final ArgConverter ARG_DOUBLE = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaNumber ) { + LuaNumber ln = (LuaNumber)obj; + return Double.valueOf(ln.n); + } + if( obj instanceof String ) { + String s = (String)obj; + try { + return Double.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_FLOAT = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaNumber ) { + LuaNumber ln = (LuaNumber)obj; + return Float.valueOf((float)ln.n); + } + if( obj instanceof String ) { + String s = (String)obj; + try { + return Float.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_LONG = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaNumber ) { + LuaNumber ln = (LuaNumber)obj; + long i = (long)ln.n; + if( i == ln.n ) + return Long.valueOf(i); + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Long.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_INTEGER = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaNumber ) { + LuaNumber ln = (LuaNumber)obj; + int i = (int)ln.n; + if( i == ln.n ) + return Integer.valueOf(i); + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Integer.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_SHORT = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaNumber ) { + LuaNumber ln = (LuaNumber)obj; + short i = (short)ln.n; + if( i == ln.n ) + return Short.valueOf(i); + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Short.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static ArgConverter[] getArgConverters(Method m) { + Class<?>[] paramTypes = m.getParameterTypes(); + ArgConverter[] a = new ArgConverter[paramTypes.length]; + for( int i=0; i<a.length; i++ ) { + a[i] = getArgConverter(paramTypes[i]); + } + return a; + } + + private static ArgConverter getArgConverter(Class<?> cls) { + if( cls == Double.TYPE || cls.equals(Double.class) ) + return ARG_DOUBLE; + if( cls == Float.TYPE || cls.equals(Float.class) ) + return ARG_FLOAT; + if( cls == Long.TYPE || cls.equals(Long.class) ) + return ARG_LONG; + if( cls == Integer.TYPE || cls.equals(Integer.class) ) + return ARG_INTEGER; + if( cls == Short.TYPE || cls.equals(Short.class) ) + return ARG_SHORT; + return ARG_SAME; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaNumber.java Tue Nov 13 05:54:32 2012 +0000 @@ -0,0 +1,38 @@ +package luan; + + +public class LuaNumber { + final double n; + + public LuaNumber(double n) { + this.n = n; + } + + // convert to Lua format + @Override public String toString() { + String s = Double.toString(n); + int iE = s.indexOf('E'); + String ending = null; + if( iE != -1 ) { + ending = s.substring(iE); + s = s.substring(0,iE); + } + if( s.endsWith(".0") ) + s = s.substring(0,s.length()-2); + if( ending != null ) + s += ending; + return s; + } + + @Override public boolean equals(Object obj) { + if( !(obj instanceof LuaNumber) ) + return false; + LuaNumber ln = (LuaNumber)obj; + return n == ln.n; + } + + @Override public int hashCode() { + return Double.valueOf(n).hashCode(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaTable.java Tue Nov 13 05:54:32 2012 +0000 @@ -0,0 +1,34 @@ +package luan; + +import java.util.Map; +import java.util.HashMap; + + +public class LuaTable { + private final Map<Object,Object> map = new HashMap<Object,Object>(); + + @Override public String toString() { + return "table: " + Integer.toHexString(hashCode()); + } + + public Object get(Object key) { + return map.get(key); + } + + public void set(Object key,Object val) { + if( val == null ) { + map.remove(key); + } else { + map.put(key,val); + } + } + + public int length() { + int i = 0; + while( map.containsKey( new LuaNumber(i) ) ) { + i++; + } + return i; + } + +}