Improve math lib argument type checking.

This commit is contained in:
James Roseborough
2008-07-17 23:12:48 +00:00
parent 1885f9b618
commit 41ed2fa8ad
2 changed files with 76 additions and 54 deletions

View File

@@ -88,37 +88,64 @@ public class MathLib extends LFunction {
vm.pushlvalue( value ); vm.pushlvalue( value );
} }
private static void setResult( LuaState vm, double d ) {
vm.resettop();
vm.pushlvalue( LDouble.valueOf(d) );
}
private static void setResult( LuaState vm, int i ) {
vm.resettop();
vm.pushlvalue( LInteger.valueOf(i) );
}
public boolean luaStackCall( LuaState vm ) { public boolean luaStackCall( LuaState vm ) {
double x;
switch ( id ) { switch ( id ) {
case INSTALL: case INSTALL:
install( vm._G ); install( vm._G );
break; break;
case ABS: case ABS:
setResult( vm, abs( vm.topointer( 2 ) ) ); setResult( vm, Math.abs ( vm.checkdouble(2) ) );
break; break;
case COS: case COS:
setResult( vm, new LDouble( Math.cos ( vm.tonumber(2) ) ) ); setResult( vm, Math.cos ( vm.checkdouble(2) ) );
break; break;
case MAX: case MAX: {
setResult( vm, max( vm.topointer(2), vm.topointer(3) ) ); int n = vm.gettop();
x = vm.checkdouble(2);
for ( int i=3; i<=n; i++ )
x = Math.max(x, vm.checkdouble(i));
setResult( vm, x );
break; break;
case MIN: }
setResult( vm, min( vm.topointer(2), vm.topointer(3) ) ); case MIN: {
int n = vm.gettop();
x = vm.checkdouble(2);
for ( int i=3; i<=n; i++ )
x = Math.min(x, vm.checkdouble(i));
setResult(vm,x);
break; break;
case MODF: }
modf( vm ); case MODF: {
double v = vm.checkdouble(2);
double intPart = ( v > 0 ) ? Math.floor( v ) : Math.ceil( v );
double fracPart = v - intPart;
vm.resettop();
vm.pushnumber( intPart );
vm.pushnumber( fracPart );
break; break;
}
case SIN: case SIN:
setResult( vm, new LDouble( Math.sin( vm.tonumber(2) ) ) ); setResult( vm, Math.sin( vm.checkdouble(2) ) );
break; break;
case SQRT: case SQRT:
setResult( vm, new LDouble( Math.sqrt( vm.tonumber(2) ) ) ); setResult( vm, Math.sqrt( vm.checkdouble(2) ) );
break; break;
case CEIL: case CEIL:
setResult( vm, LInteger.valueOf( (int) Math.ceil( vm.tonumber(2) ) ) ); setResult( vm, (int) Math.ceil( vm.checkdouble(2) ) );
break; break;
case FLOOR: case FLOOR:
setResult( vm, LInteger.valueOf( (int) Math.floor( vm.tonumber(2) ) ) ); setResult( vm, (int) Math.floor( vm.checkdouble(2) ) );
break; break;
case RANDOM: { case RANDOM: {
if ( random == null ) if ( random == null )
@@ -129,14 +156,16 @@ public class MathLib extends LFunction {
vm.pushnumber(random.nextDouble()); vm.pushnumber(random.nextDouble());
break; break;
case 2: { case 2: {
int m = vm.tointeger(2); int m = vm.checkint(2);
vm.argcheck(1<=m, 1, "interval is empty");
vm.resettop(); vm.resettop();
vm.pushinteger(1+random.nextInt(m)); vm.pushinteger(1+random.nextInt(m));
break; break;
} }
default: { default: {
int m = vm.tointeger(2); int m = vm.checkint(2);
int n = vm.tointeger(3); int n = vm.checkint(3);
vm.argcheck(m<=n, 2, "interval is empty");
vm.resettop(); vm.resettop();
vm.pushinteger(m+random.nextInt(n+1-m)); vm.pushinteger(m+random.nextInt(n+1-m));
break; break;
@@ -145,7 +174,7 @@ public class MathLib extends LFunction {
break; break;
} }
case RANDOMSEED: case RANDOMSEED:
random = new Random( vm.tointeger(2) ); random = new Random( vm.checkint(2) );
vm.resettop(); vm.resettop();
break; break;
default: default:
@@ -153,27 +182,5 @@ public class MathLib extends LFunction {
} }
return false; return false;
} }
private LValue abs( final LValue v ) {
LValue nv = v.luaUnaryMinus();
return max( v, nv );
}
private LValue max( LValue lhs, LValue rhs ) {
return rhs.luaBinCmpUnknown( Lua.OP_LT, lhs ) ? rhs: lhs;
}
private LValue min( LValue lhs, LValue rhs ) {
return rhs.luaBinCmpUnknown( Lua.OP_LT, lhs ) ? lhs: rhs;
}
private void modf( LuaState vm ) {
LValue arg = vm.topointer(2);
double v = arg.toJavaDouble();
double intPart = ( v > 0 ) ? Math.floor( v ) : Math.ceil( v );
double fracPart = v - intPart;
vm.resettop();
vm.pushnumber( intPart );
vm.pushnumber( fracPart );
}
} }

View File

@@ -2617,23 +2617,30 @@ public class LuaState extends Lua {
/** /**
* Report an error with an argument. * Report an error with an argument.
* *
* @param narg * @param narg Stack index of the bad argument
* Stack index of the bad argument * @param extramsg String to include in error message
* @param extramsg
* String to include in error message
*/ */
public void argerror(int narg, String extramsg) { public void argerror(int narg, String extramsg) {
// TODO: port ldebug.c and provide mode useful error messages.
error("bad argument #" + (narg - 1) + " (" + extramsg + ")"); error("bad argument #" + (narg - 1) + " (" + extramsg + ")");
} }
/**
* Conditionally report an error with an argument.
*
* @param cond boolean condition that generates an error when false
* @param narg Stack index of the bad argument
* @param extramsg String to include in error message
*/
public void argcheck(boolean cond, int narg, String extramsg) {
if ( ! cond )
argerror(narg,extramsg);
}
/** /**
* Report a type error. * Report a type error.
* *
* @param narg * @param narg Stack index of the bad argument
* Stack index of the bad argument * @param typename Name of the type that was expected, such as "string"
* @param typename
* Name of the type that was expected
*/ */
public void typerror(int narg, String typename) { public void typerror(int narg, String typename) {
argerror(narg, typename + " expected, got " + typename(narg)); argerror(narg, typename + " expected, got " + typename(narg));
@@ -2642,11 +2649,8 @@ public class LuaState extends Lua {
/** /**
* Report a type error. * Report a type error.
* *
* @param narg * @param narg Stack index of the bad argument
* Stack index of the bad argument * @param typenum Constant value specifying the type of argument that was expected (i.e. LUA_TSTRING).
* @param typenum
* Constant value specifying the type of argument that was
* expected (i.e. LUA_TSTRING).
*/ */
public void typerror(int narg, int typenum) { public void typerror(int narg, int typenum) {
typerror(narg, TYPE_NAMES[typenum]); typerror(narg, TYPE_NAMES[typenum]);
@@ -2713,6 +2717,17 @@ public class LuaState extends Lua {
return checknumber(narg).toJavaLong(); return checknumber(narg).toJavaLong();
} }
/**
* Checks whether the function argument <code>narg</code> is a number and
* returns this number cast to a <code>double</code>.
* @param narg the argument number
* @throws LuaErrorException if the value cannot be converted to a double
* @return long value if the argument is a number or can be converted to double
*/
public double checkdouble(int narg) {
return checknumber(narg).toJavaDouble();
}
/** /**
* Checks whether the function argument <code>narg</code> is a number and * Checks whether the function argument <code>narg</code> is a number and
* returns this number. * returns this number.