Improve math lib error reporting.

This commit is contained in:
James Roseborough
2010-05-12 03:21:12 +00:00
parent 719ec63d5d
commit 536b27330d
7 changed files with 71 additions and 64 deletions

View File

@@ -161,10 +161,9 @@ public class LuaValue extends Varargs {
// errors // errors
public static LuaValue error(String message) { throw new LuaError(message); } public static LuaValue error(String message) { throw new LuaError(message); }
public static LuaValue error(int iarg, String message) { throw new LuaError("bad argument #"+iarg+": "+message); }
public static void assert_(boolean b,String msg) { if(!b) throw new LuaError(msg); } public static void assert_(boolean b,String msg) { if(!b) throw new LuaError(msg); }
public static void argerror(int iarg,String msg) { throw new LuaError("bad argument #"+iarg+": "+msg); } public static void argerror(int iarg,String msg) { throw new LuaError("bad argument #"+iarg+": "+msg); }
protected LuaValue typerror(String expected) { throw new LuaError(expected+" expected, got "+typename()); } protected LuaValue typerror(String expected) { throw new LuaError("bad argument: "+expected+" expected, got "+typename()); }
protected LuaValue typerror(int iarg, String expected) { throw new LuaError("bad argument #"+iarg+": "+expected+" expected, got "+typename()); } protected LuaValue typerror(int iarg, String expected) { throw new LuaError("bad argument #"+iarg+": "+expected+" expected, got "+typename()); }
protected LuaValue unimplemented(String fun) { throw new LuaError("'"+fun+"' not implemented for "+typename()); } protected LuaValue unimplemented(String fun) { throw new LuaError("'"+fun+"' not implemented for "+typename()); }
protected LuaValue aritherror() { throw new LuaError("attempt to perform arithmetic on "+typename()); } protected LuaValue aritherror() { throw new LuaError("attempt to perform arithmetic on "+typename()); }

View File

@@ -54,12 +54,12 @@ public class MathLib extends OneArgFunction {
"exp", "floor", "rad", "sin", "exp", "floor", "rad", "sin",
"sqrt", "tan" } ); "sqrt", "tan" } );
bind( t, MathLib2.class, new String[] { bind( t, MathLib2.class, new String[] {
"fmod", "ldexp", "pow", "random", } ); "fmod", "ldexp", "pow", } );
bind( t, MathLibV.class, new String[] { bind( t, MathLibV.class, new String[] {
"frexp", "max", "min", "modf", "frexp", "max", "min", "modf",
"randomseed" } ); "randomseed", "random", } );
((MathLib2) t.get("random" )).mathlib = this;
((MathLibV) t.get("randomseed")).mathlib = this; ((MathLibV) t.get("randomseed")).mathlib = this;
((MathLibV) t.get("random" )).mathlib = this;
env.set("math", t); env.set("math", t);
return t; return t;
} }
@@ -67,16 +67,16 @@ public class MathLib extends OneArgFunction {
public static final class MathLib1 extends OneArgFunction { public static final class MathLib1 extends OneArgFunction {
public LuaValue call(LuaValue arg) { public LuaValue call(LuaValue arg) {
switch ( opcode ) { switch ( opcode ) {
case 0: return valueOf(Math.abs(arg.todouble())); case 0: return valueOf(Math.abs(arg.checkdouble()));
case 1: return valueOf(Math.ceil(arg.todouble())); case 1: return valueOf(Math.ceil(arg.checkdouble()));
case 2: return valueOf(Math.cos(arg.todouble())); case 2: return valueOf(Math.cos(arg.checkdouble()));
case 3: return valueOf(Math.toDegrees(arg.todouble())); case 3: return valueOf(Math.toDegrees(arg.checkdouble()));
case 4: return dpow(Math.E,arg.todouble()); case 4: return dpow(Math.E,arg.checkdouble());
case 5: return valueOf(Math.floor(arg.todouble())); case 5: return valueOf(Math.floor(arg.checkdouble()));
case 6: return valueOf(Math.toRadians(arg.todouble())); case 6: return valueOf(Math.toRadians(arg.checkdouble()));
case 7: return valueOf(Math.sin(arg.todouble())); case 7: return valueOf(Math.sin(arg.checkdouble()));
case 8: return valueOf(Math.sqrt(arg.todouble())); case 8: return valueOf(Math.sqrt(arg.checkdouble()));
case 9: return valueOf(Math.tan(arg.todouble())); case 9: return valueOf(Math.tan(arg.checkdouble()));
} }
return NIL; return NIL;
} }
@@ -100,18 +100,7 @@ public class MathLib extends OneArgFunction {
return valueOf(x * Double.longBitsToDouble(e << 52)); return valueOf(x * Double.longBitsToDouble(e << 52));
} }
case 2: { // pow case 2: { // pow
return dpow(arg1.todouble(), arg2.todouble()); return dpow(arg1.checkdouble(), arg2.checkdouble());
}
case 3: { // random
if ( mathlib.random == null )
mathlib.random = new Random();
if ( arg1.isnil() )
return valueOf( mathlib.random.nextDouble() );
int m = arg1.toint();
if ( arg2.isnil() )
return valueOf( 1 + mathlib.random.nextInt(m) );
else
return valueOf( m + mathlib.random.nextInt(arg2.toint()-m) );
} }
} }
return NIL; return NIL;
@@ -190,6 +179,26 @@ public class MathLib extends OneArgFunction {
mathlib.random = new Random(seed); mathlib.random = new Random(seed);
return NONE; return NONE;
} }
case 5: { // random
if ( mathlib.random == null )
mathlib.random = new Random();
switch ( args.narg() ) {
case 0:
return valueOf( mathlib.random.nextDouble() );
case 1: {
int m = args.checkint(1);
if (m<1) argerror(1, "interval is empty");
return valueOf( 1 + mathlib.random.nextInt(m) );
}
default: {
int m = args.checkint(1);
int n = args.checkint(2);
if (n<m) argerror(2, "interval is empty");
return valueOf( m + mathlib.random.nextInt(n+1-m) );
}
}
}
} }
return NONE; return NONE;
} }

View File

@@ -211,7 +211,7 @@ public class PackageLib extends OneArgFunction {
// set the environment of the current function // set the environment of the current function
LuaFunction f = LuaThread.getCallstackFunction(1); LuaFunction f = LuaThread.getCallstackFunction(1);
if ( f == null ) if ( f == null )
error(1, "no calling function"); error("no calling function");
f.setfenv(module); f.setfenv(module);
// apply the functions // apply the functions

View File

@@ -127,7 +127,7 @@ public class StringLib extends OneArgFunction {
byte[] bytes = new byte[n]; byte[] bytes = new byte[n];
for ( int i=0, a=1; i<n; i++, a++ ) { for ( int i=0, a=1; i<n; i++, a++ ) {
int c = args.checkint(a); int c = args.checkint(a);
if (c<0 || c>=256) error(a, "invalid value"); if (c<0 || c>=256) argerror(a, "invalid value");
bytes[i] = (byte) c; bytes[i] = (byte) c;
} }
return LuaString.valueOf( bytes ); return LuaString.valueOf( bytes );

View File

@@ -50,15 +50,15 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
public static final class JseMathLib1 extends OneArgFunction { public static final class JseMathLib1 extends OneArgFunction {
public LuaValue call(LuaValue arg) { public LuaValue call(LuaValue arg) {
switch ( opcode ) { switch ( opcode ) {
case 0: return valueOf(Math.acos(arg.todouble())); case 0: return valueOf(Math.acos(arg.checkdouble()));
case 1: return valueOf(Math.asin(arg.todouble())); case 1: return valueOf(Math.asin(arg.checkdouble()));
case 2: return valueOf(Math.atan(arg.todouble())); case 2: return valueOf(Math.atan(arg.checkdouble()));
case 3: return valueOf(Math.cosh(arg.todouble())); case 3: return valueOf(Math.cosh(arg.checkdouble()));
case 4: return valueOf(Math.exp(arg.todouble())); case 4: return valueOf(Math.exp(arg.checkdouble()));
case 5: return valueOf(Math.log(arg.todouble())); case 5: return valueOf(Math.log(arg.checkdouble()));
case 6: return valueOf(Math.log10(arg.todouble())); case 6: return valueOf(Math.log10(arg.checkdouble()));
case 7: return valueOf(Math.sinh(arg.todouble())); case 7: return valueOf(Math.sinh(arg.checkdouble()));
case 8: return valueOf(Math.tanh(arg.todouble())); case 8: return valueOf(Math.tanh(arg.checkdouble()));
} }
return NIL; return NIL;
} }
@@ -67,8 +67,8 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
public static final class JseMathLib2 extends TwoArgFunction { public static final class JseMathLib2 extends TwoArgFunction {
public LuaValue call(LuaValue arg1, LuaValue arg2) { public LuaValue call(LuaValue arg1, LuaValue arg2) {
switch ( opcode ) { switch ( opcode ) {
case 0: return valueOf(Math.atan2(arg1.todouble(), arg2.todouble())); case 0: return valueOf(Math.atan2(arg1.checkdouble(), arg2.checkdouble()));
case 1: return valueOf(Math.pow(arg1.todouble(), arg2.todouble())); case 1: return valueOf(Math.pow(arg1.checkdouble(), arg2.checkdouble()));
} }
return NIL; return NIL;
} }

View File

@@ -21,7 +21,6 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
import org.luaj.vm2.lib.PackageLib;
import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.compiler.LuaC;

View File

@@ -29,7 +29,7 @@ for i,v in ipairs(singleargfunctions) do
local funcname = 'math.'..v local funcname = 'math.'..v
banner(funcname) banner(funcname)
checkallpass(funcname,{somenumber}) checkallpass(funcname,{somenumber})
checkallerrors(funcname,{notanumber},'bad argument #1') checkallerrors(funcname,{notanumber},'bad argument')
end end
-- single argument, positive domain tests -- single argument, positive domain tests
@@ -37,7 +37,7 @@ for i,v in ipairs(singleargposdomain) do
local funcname = 'math.'..v local funcname = 'math.'..v
banner(funcname) banner(funcname)
checkallpass(funcname,{somepositive}) checkallpass(funcname,{somepositive})
checkallerrors(funcname,{notanumber},'bad argument #1') checkallerrors(funcname,{notanumber},'bad argument')
end end
-- two-argument tests -- two-argument tests
@@ -45,11 +45,11 @@ for i,v in ipairs(twoargfunctions) do
local funcname = 'math.'..v local funcname = 'math.'..v
banner(funcname) banner(funcname)
checkallpass(funcname,{somenumber,somenumber}) checkallpass(funcname,{somenumber,somenumber})
checkallerrors(funcname,{},'bad argument #') checkallerrors(funcname,{},'bad argument')
checkallerrors(funcname,{notanumber},'bad argument #') checkallerrors(funcname,{notanumber},'bad argument')
checkallerrors(funcname,{notanumber,somenumber},'bad argument #1') checkallerrors(funcname,{notanumber,somenumber},'bad argument')
checkallerrors(funcname,{somenumber},'bad argument #2') checkallerrors(funcname,{somenumber},'bad argument')
checkallerrors(funcname,{somenumber,notanumber},'bad argument #2') checkallerrors(funcname,{somenumber,notanumber},'bad argument')
end end
-- two-argument, positive domain tests -- two-argument, positive domain tests
@@ -57,28 +57,28 @@ for i,v in ipairs(twoargsposdomain) do
local funcname = 'math.'..v local funcname = 'math.'..v
banner(funcname) banner(funcname)
checkallpass(funcname,{somepositive,somenumber}) checkallpass(funcname,{somepositive,somenumber})
checkallerrors(funcname,{},'bad argument #') checkallerrors(funcname,{},'bad argument')
checkallerrors(funcname,{notanumber},'bad argument #') checkallerrors(funcname,{notanumber},'bad argument')
checkallerrors(funcname,{notanumber,somenumber},'bad argument #1') checkallerrors(funcname,{notanumber,somenumber},'bad argument')
checkallerrors(funcname,{somenumber},'bad argument #2') checkallerrors(funcname,{somenumber},'bad argument')
checkallerrors(funcname,{somenumber,notanumber},'bad argument #2') checkallerrors(funcname,{somenumber,notanumber},'bad argument')
end end
-- math.max -- math.max
banner('math.max') banner('math.max')
checkallpass('math.max',{somenumber}) checkallpass('math.max',{somenumber})
checkallpass('math.max',{somenumber,somenumber}) checkallpass('math.max',{somenumber,somenumber})
checkallerrors('math.max',{},'bad argument #1') checkallerrors('math.max',{},'bad argument')
checkallerrors('math.max',{nonnumber},'bad argument #1') checkallerrors('math.max',{nonnumber},'bad argument')
checkallerrors('math.max',{somenumber,nonnumber},'bad argument #2') checkallerrors('math.max',{somenumber,nonnumber},'bad argument')
-- math.min -- math.min
banner('math.min') banner('math.min')
checkallpass('math.min',{somenumber}) checkallpass('math.min',{somenumber})
checkallpass('math.min',{somenumber,somenumber}) checkallpass('math.min',{somenumber,somenumber})
checkallerrors('math.min',{},'bad argument #1') checkallerrors('math.min',{},'bad argument')
checkallerrors('math.min',{nonnumber},'bad argument #1') checkallerrors('math.min',{nonnumber},'bad argument')
checkallerrors('math.min',{somenumber,nonnumber},'bad argument #2') checkallerrors('math.min',{somenumber,nonnumber},'bad argument')
-- math.random -- math.random
local somem = {3,4.5,'6.7'} local somem = {3,4.5,'6.7'}
@@ -91,8 +91,8 @@ checkallpass('math.random',{somem,somen},true)
checkallpass('math.random',{{-4,-5.6,'-7','-8.9'},{-1,100,23.45,'-1.23'}},true) checkallpass('math.random',{{-4,-5.6,'-7','-8.9'},{-1,100,23.45,'-1.23'}},true)
checkallerrors('math.random',{{-4,-5.6,'-7','-8.9'}},'interval is empty') checkallerrors('math.random',{{-4,-5.6,'-7','-8.9'}},'interval is empty')
checkallerrors('math.random',{somen,somem},'interval is empty') checkallerrors('math.random',{somen,somem},'interval is empty')
checkallerrors('math.random',{notamn,somen},'bad argument #1') checkallerrors('math.random',{notamn,somen},'bad argument')
checkallerrors('math.random',{somem,notamn},'bad argument #2') checkallerrors('math.random',{somem,notamn},'bad argument')
-- math.ldexp -- math.ldexp
local somee = {-3,0,3,9.10,'12.34'} local somee = {-3,0,3,9.10,'12.34'}
@@ -101,6 +101,6 @@ banner('math.ldexp')
checkallpass('math.ldexp',{somenumber,somee}) checkallpass('math.ldexp',{somenumber,somee})
checkallerrors('math.ldexp',{},'bad argument') checkallerrors('math.ldexp',{},'bad argument')
checkallerrors('math.ldexp',{notanumber},'bad argument') checkallerrors('math.ldexp',{notanumber},'bad argument')
checkallerrors('math.ldexp',{notanumber,somee},'bad argument #1') checkallerrors('math.ldexp',{notanumber,somee},'bad argument')
checkallerrors('math.ldexp',{somenumber},'bad argument #2') checkallerrors('math.ldexp',{somenumber},'bad argument')
checkallerrors('math.ldexp',{somenumber,notae},'bad argument #2') checkallerrors('math.ldexp',{somenumber,notae},'bad argument')