diff --git a/src/core/org/luaj/compiler/FuncState.java b/src/core/org/luaj/compiler/FuncState.java index d6e30f04..cefecf99 100644 --- a/src/core/org/luaj/compiler/FuncState.java +++ b/src/core/org/luaj/compiler/FuncState.java @@ -35,6 +35,7 @@ import org.luaj.vm.LString; import org.luaj.vm.LValue; import org.luaj.vm.LocVars; import org.luaj.vm.Lua; +import org.luaj.vm.Platform; public class FuncState extends LuaC { @@ -840,11 +841,9 @@ public class FuncState extends LuaC { case OP_MOD: r = (LNumber) v2.luaBinOpUnknown(op, v1); break; - /* TODO: replace this with something reasonable. case OP_POW: - r = new LDouble( Math.pow(v1.luaAsDouble(), v2.luaAsDouble() ) ); + r = Platform.getInstance().mathPow( v1.toJavaDouble(), v2.toJavaDouble() ); break; - //*/ case OP_UNM: r = (LNumber) v1.luaUnaryMinus(); break; diff --git a/src/core/org/luaj/compiler/LuaC.java b/src/core/org/luaj/compiler/LuaC.java index 78735416..02727f7e 100644 --- a/src/core/org/luaj/compiler/LuaC.java +++ b/src/core/org/luaj/compiler/LuaC.java @@ -51,7 +51,8 @@ public class LuaC extends Lua implements LuaCompiler { } protected static void _assert(boolean b) { - if (!b) throw new LuaErrorException("compiler assert failed"); + if (!b) + throw new LuaErrorException("compiler assert failed"); } public static final int MAXSTACK = 250; diff --git a/src/core/org/luaj/lib/BaseLib.java b/src/core/org/luaj/lib/BaseLib.java index 06327652..9fb8dc83 100644 --- a/src/core/org/luaj/lib/BaseLib.java +++ b/src/core/org/luaj/lib/BaseLib.java @@ -199,7 +199,7 @@ public class BaseLib extends LFunction { } case ASSERT: { if ( ! vm.toboolean(2) ) - vm.error( vm.gettop()>2? vm.tostring(3): "assertion failed!", 0 ); + vm.error( vm.gettop()>2? vm.tostring(3): "assertion failed!" ); vm.remove(1); break; } diff --git a/src/core/org/luaj/vm/LDouble.java b/src/core/org/luaj/vm/LDouble.java index df83265c..17bbfe55 100644 --- a/src/core/org/luaj/vm/LDouble.java +++ b/src/core/org/luaj/vm/LDouble.java @@ -39,19 +39,20 @@ public class LDouble extends LNumber { } public String toJavaString() { + if ( Double.isNaN(m_value) ) + return "-1.#IND"; + if ( Double.isInfinite(m_value) ) + return (m_value>0? "1.#INF": "-1.#INF"); long l = (long) m_value; - if ( m_value == (double) l ) { - // TODO: is this a good idea? + if ( (m_value == (double) l) && (m_value <= Long.MAX_VALUE) && (m_value >= Long.MIN_VALUE) ) { return Long.toString( l ); } else { return Double.toString( m_value ); } } - + // return true if value survives as an integer public boolean isInteger() { - // Cast to int and then back to double and see if the value - // survives the round trip. return ( (double) ( (int) m_value ) ) == m_value; } @@ -77,13 +78,17 @@ public class LDouble extends LNumber { case Lua.OP_MUL: return new LDouble( lhs * rhs ); case Lua.OP_DIV: return new LDouble( lhs / rhs ); case Lua.OP_MOD: return new LDouble( lhs - Math.floor(lhs/rhs) * rhs ); - case Lua.OP_POW: throw new LuaErrorException("math.pow() not implemented for doubles"); + case Lua.OP_POW: { + // allow platform to override math.pow() + LValue result = Platform.getInstance().mathPow(lhs, rhs); + if ( result == null ) + return new LDouble( dpow( lhs, rhs ) ); + } } LuaState.vmerror( "bad bin opcode" ); return null; } - /* warning: NOT TESTED public static double dpow(double a, double b) { if ( b < 0 ) return 1 / dpow( a, -b ); @@ -102,8 +107,6 @@ public class LDouble extends LNumber { } return p; } - */ - public int toJavaInt() { return (int) m_value; diff --git a/src/core/org/luaj/vm/LInteger.java b/src/core/org/luaj/vm/LInteger.java index 2eb55a2a..6b5809d6 100644 --- a/src/core/org/luaj/vm/LInteger.java +++ b/src/core/org/luaj/vm/LInteger.java @@ -81,21 +81,14 @@ public class LInteger extends LNumber { case Lua.OP_ADD: return LInteger.valueOf( m_value + rhs ); case Lua.OP_SUB: return LInteger.valueOf( m_value - rhs ); case Lua.OP_MUL: return LInteger.valueOf( m_value * rhs ); - case Lua.OP_DIV: return LInteger.valueOf( m_value / rhs ); - case Lua.OP_MOD: return LInteger.valueOf( m_value - ((int) Math.floor(m_value/(double)rhs)) * rhs ); - case Lua.OP_POW: return LInteger.valueOf( ipow(m_value, rhs) ); + case Lua.OP_DIV: + case Lua.OP_MOD: + case Lua.OP_POW: + return LDouble.luaBinOpDoubleDouble(opcode, m_value, rhs); } LuaState.vmerror( "bad bin opcode" ); return null; } - - private static int ipow(int v, int rhs) { - int p = 1; - for ( ; rhs > 0; rhs>>=1, v=v*v ) - if ( (rhs & 1) != 0 ) - p *= v; - return p; - } // binary operations on mixed integer, double public LValue luaBinOpDouble(int opcode, double rhs) { diff --git a/src/core/org/luaj/vm/Platform.java b/src/core/org/luaj/vm/Platform.java index 518a1fec..07e68893 100644 --- a/src/core/org/luaj/vm/Platform.java +++ b/src/core/org/luaj/vm/Platform.java @@ -139,4 +139,14 @@ abstract public class Platform { } return port; } + + /** + * Compute math.pow() for two numbers using double math when available. + * @param lhs LNumber base + * @param rhs LNumber exponent + * @return base ^ exponent as a LNumber, or null if not implemented + */ + public LNumber mathPow(double lhs, double rhs) { + return null; + } } diff --git a/src/sample/org/luaj/sample/LuaRunner.java b/src/sample/org/luaj/sample/LuaRunner.java index dd6af5bf..2bd065d7 100644 --- a/src/sample/org/luaj/sample/LuaRunner.java +++ b/src/sample/org/luaj/sample/LuaRunner.java @@ -21,6 +21,8 @@ ******************************************************************************/ package org.luaj.sample; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -29,6 +31,7 @@ import org.luaj.vm.LClosure; import org.luaj.vm.LPrototype; import org.luaj.vm.LValue; import org.luaj.vm.LoadState; +import org.luaj.vm.LuaErrorException; import org.luaj.vm.LuaState; @@ -45,23 +48,39 @@ public class LuaRunner { LuaState state = LuaState.newState(); // get script name - String script = (args.length>0? args[0]: "/test2.luac"); - System.out.println("loading '"+script+"'"); - - // add standard bindings - state.installStandardLibs(); - LuaC.install(); + for ( int i=0; i