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
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 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 unimplemented(String fun) { throw new LuaError("'"+fun+"' not implemented for "+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",
"sqrt", "tan" } );
bind( t, MathLib2.class, new String[] {
"fmod", "ldexp", "pow", "random", } );
"fmod", "ldexp", "pow", } );
bind( t, MathLibV.class, new String[] {
"frexp", "max", "min", "modf",
"randomseed" } );
((MathLib2) t.get("random" )).mathlib = this;
"randomseed", "random", } );
((MathLibV) t.get("randomseed")).mathlib = this;
((MathLibV) t.get("random" )).mathlib = this;
env.set("math", t);
return t;
}
@@ -67,16 +67,16 @@ public class MathLib extends OneArgFunction {
public static final class MathLib1 extends OneArgFunction {
public LuaValue call(LuaValue arg) {
switch ( opcode ) {
case 0: return valueOf(Math.abs(arg.todouble()));
case 1: return valueOf(Math.ceil(arg.todouble()));
case 2: return valueOf(Math.cos(arg.todouble()));
case 3: return valueOf(Math.toDegrees(arg.todouble()));
case 4: return dpow(Math.E,arg.todouble());
case 5: return valueOf(Math.floor(arg.todouble()));
case 6: return valueOf(Math.toRadians(arg.todouble()));
case 7: return valueOf(Math.sin(arg.todouble()));
case 8: return valueOf(Math.sqrt(arg.todouble()));
case 9: return valueOf(Math.tan(arg.todouble()));
case 0: return valueOf(Math.abs(arg.checkdouble()));
case 1: return valueOf(Math.ceil(arg.checkdouble()));
case 2: return valueOf(Math.cos(arg.checkdouble()));
case 3: return valueOf(Math.toDegrees(arg.checkdouble()));
case 4: return dpow(Math.E,arg.checkdouble());
case 5: return valueOf(Math.floor(arg.checkdouble()));
case 6: return valueOf(Math.toRadians(arg.checkdouble()));
case 7: return valueOf(Math.sin(arg.checkdouble()));
case 8: return valueOf(Math.sqrt(arg.checkdouble()));
case 9: return valueOf(Math.tan(arg.checkdouble()));
}
return NIL;
}
@@ -100,18 +100,7 @@ public class MathLib extends OneArgFunction {
return valueOf(x * Double.longBitsToDouble(e << 52));
}
case 2: { // pow
return dpow(arg1.todouble(), arg2.todouble());
}
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 dpow(arg1.checkdouble(), arg2.checkdouble());
}
}
return NIL;
@@ -190,6 +179,26 @@ public class MathLib extends OneArgFunction {
mathlib.random = new Random(seed);
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;
}

View File

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

View File

@@ -127,7 +127,7 @@ public class StringLib extends OneArgFunction {
byte[] bytes = new byte[n];
for ( int i=0, a=1; i<n; i++, 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;
}
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 LuaValue call(LuaValue arg) {
switch ( opcode ) {
case 0: return valueOf(Math.acos(arg.todouble()));
case 1: return valueOf(Math.asin(arg.todouble()));
case 2: return valueOf(Math.atan(arg.todouble()));
case 3: return valueOf(Math.cosh(arg.todouble()));
case 4: return valueOf(Math.exp(arg.todouble()));
case 5: return valueOf(Math.log(arg.todouble()));
case 6: return valueOf(Math.log10(arg.todouble()));
case 7: return valueOf(Math.sinh(arg.todouble()));
case 8: return valueOf(Math.tanh(arg.todouble()));
case 0: return valueOf(Math.acos(arg.checkdouble()));
case 1: return valueOf(Math.asin(arg.checkdouble()));
case 2: return valueOf(Math.atan(arg.checkdouble()));
case 3: return valueOf(Math.cosh(arg.checkdouble()));
case 4: return valueOf(Math.exp(arg.checkdouble()));
case 5: return valueOf(Math.log(arg.checkdouble()));
case 6: return valueOf(Math.log10(arg.checkdouble()));
case 7: return valueOf(Math.sinh(arg.checkdouble()));
case 8: return valueOf(Math.tanh(arg.checkdouble()));
}
return NIL;
}
@@ -67,8 +67,8 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
public static final class JseMathLib2 extends TwoArgFunction {
public LuaValue call(LuaValue arg1, LuaValue arg2) {
switch ( opcode ) {
case 0: return valueOf(Math.atan2(arg1.todouble(), arg2.todouble()));
case 1: return valueOf(Math.pow(arg1.todouble(), arg2.todouble()));
case 0: return valueOf(Math.atan2(arg1.checkdouble(), arg2.checkdouble()));
case 1: return valueOf(Math.pow(arg1.checkdouble(), arg2.checkdouble()));
}
return NIL;
}

View File

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

View File

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