diff --git a/src/core/org/luaj/vm2/Varargs.java b/src/core/org/luaj/vm2/Varargs.java index 7b513fa3..cdaa61bf 100644 --- a/src/core/org/luaj/vm2/Varargs.java +++ b/src/core/org/luaj/vm2/Varargs.java @@ -22,15 +22,37 @@ package org.luaj.vm2; /** - * Class to encapsulate varargs values. + * Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values. + *
+ * To construct varargs, use one of the static methods such as + * {@code LuaValue.varargsOf(LuaValue,LuaValue)} + *
+ *
+ * Any LuaValue can be used as a stand-in for Varargs, for both calls and return values. + * When doing so, nargs() will return 1 and arg1() or arg(1) will return this. + * This simplifies the case when calling or implementing varargs functions with only + * 1 argument or 1 return value. + *
+ * Varargs can also be derived from other varargs by appending to the front with a call + * such as {@code LuaValue.varargsOf(LuaValue,Varargs)} + * or by taking a portion of the args using {@code Varargs.subargs(int start)} + *
+ * @see org.luaj.vm2.LuaValue#varargsOf(LuaValue[])
+ * @see org.luaj.vm2.LuaValue#varargsOf(LuaValue, Varargs)
+ * @see org.luaj.vm2.LuaValue#varargsOf(LuaValue[], Varargs)
+ * @see org.luaj.vm2.LuaValue#varargsOf(LuaValue, LuaValue, Varargs)
+ * @see org.luaj.vm2.LuaValue#varargsOf(LuaValue[], int, int)
+ * @see org.luaj.vm2.LuaValue#varargsOf(LuaValue[], int, int, Varargs)
+ * @see org.luaj.vm2.LuaValue#subargs(int)
*/
public abstract class Varargs {
/**
- * Get the n-th argument value (1-based)
- *
- * @param i 1 for the first argument, 2 for the second, etc.
- * @return Value at position i, or Value.NIL if there is none.
+ * Get the n-th argument value (1-based).
+ * @param i the index of the argument to get, 1 is the first argument
+ * @return Value at position i, or LuaValue.NIL if there is none.
+ * @see Varargs#arg1()
+ * @see LuaValue#NIL
*/
abstract public LuaValue arg( int i );
@@ -41,13 +63,15 @@ public abstract class Varargs {
abstract public int narg();
/**
- * Get the first argument
- * @return Value
+ * Get the first argument in the list.
+ * @return LuaValue which is first in the list, or LuaValue.NIL if there are no values.
+ * @see Varargs#arg(int)
+ * @see LuaValue#NIL
*/
abstract public LuaValue arg1();
/**
- * Evaluate any pending tail call and return result
+ * Evaluate any pending tail call and return result.
* @return the evaluated tail call result
*/
public Varargs eval() { return this; }
@@ -59,74 +83,402 @@ public abstract class Varargs {
public boolean isTailcall() {
return false;
}
+
// -----------------------------------------------------------------------
// utilities to get specific arguments and type-check them.
// -----------------------------------------------------------------------
- // argument types
+ /** Gets the type of argument {@code i}
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return int value corresponding to one of the LuaValue integer type values
+ * @see LuaValue.TNIL
+ * @see LuaValue.TBOOLEAN
+ * @see LuaValue.TNUMBER
+ * @see LuaValue.TSTRING
+ * @see LuaValue.TTABLE
+ * @see LuaValue.TFUNCTION
+ * @see LuaValue.TUSERDATA
+ * @see LuaValue.TTHREAD
+ * */
public int type(int i) { return arg(i).type(); }
+
+ /** Tests if argument i is nil.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument is nil or does not exist, false otherwise
+ * @see LuaValue.TNIL
+ * */
public boolean isnil(int i) { return arg(i).isnil(); }
+
+ /** Tests if argument i is a function.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists and is a function or closure, false otherwise
+ * @see LuaValue.TFUNCTION
+ * */
public boolean isfunction(int i) { return arg(i).isfunction(); }
+
+ /** Tests if argument i is a number.
+ * Since anywhere a number is required, a string can be used that
+ * is a number, this will return true for both numbers and
+ * strings that can be interpreted as numbers.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists and is a number or
+ * string that can be interpreted as a number, false otherwise
+ * @see LuaValue.TNUMBER
+ * @see LuaValue.TSTRING
+ * */
public boolean isnumber(int i) { return arg(i).isnumber(); }
+
+ /** Tests if argument i is a string.
+ * Since all lua numbers can be used where strings are used,
+ * this will return true for both strings and numbers.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists and is a string or number, false otherwise
+ * @see LuaValue.TNUMBER
+ * @see LuaValue.TSTRING
+ * */
public boolean isstring(int i) { return arg(i).isstring(); }
+
+ /** Tests if argument i is a table.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists and is a lua table, false otherwise
+ * @see LuaValue.TTABLE
+ * */
public boolean istable(int i) { return arg(i).istable(); }
+
+ /** Tests if argument i is a thread.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists and is a lua thread, false otherwise
+ * @see LuaValue.TTHREAD
+ * */
public boolean isthread(int i) { return arg(i).isthread(); }
+
+ /** Tests if argument i is a userdata.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists and is a userdata, false otherwise
+ * @see LuaValue.TUSERDATA
+ * */
public boolean isuserdata(int i) { return arg(i).isuserdata(); }
+
+ /** Tests if a value exists at argument i.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if the argument exists, false otherwise
+ * */
public boolean isvalue(int i) { return i>0 && i<=narg(); }
- // optional argument types
+ /** Return argument i as a boolean value, {@code defval} if nil, or throw a LuaError if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if argument i is boolean true, false if it is false, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a lua boolean
+ * */
public boolean optboolean(int i, boolean defval) { return arg(i).optboolean(defval); }
+
+ /** Return argument i as a closure, {@code defval} if nil, or throw a LuaError if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaClosure if argument i is a closure, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a lua closure
+ * */
public LuaClosure optclosure(int i, LuaClosure defval) { return arg(i).optclosure(defval); }
+
+ /** Return argument i as a double, {@code defval} if nil, or throw a LuaError if it cannot be converted to one.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return java double value if argument i is a number or string that converts to a number, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a number
+ * */
public double optdouble(int i, double defval) { return arg(i).optdouble(defval); }
+
+ /** Return argument i as a function, {@code defval} if nil, or throw a LuaError if an incompatible type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaValue that can be called if argument i is lua function or closure, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a lua function or closure
+ * */
public LuaFunction optfunction(int i, LuaFunction defval) { return arg(i).optfunction(defval); }
+
+ /** Return argument i as a java int value, discarding any fractional part, {@code defval} if nil, or throw a LuaError if not a number.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return int value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a number
+ * */
public int optint(int i, int defval) { return arg(i).optint(defval); }
+
+ /** Return argument i as a java int value, {@code defval} if nil, or throw a LuaError if not a number or is not representable by a java int.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaInteger value that fits in a java int without rounding, or defval if not supplied or nil
+ * @exception LuaError if the argument cannot be represented by a java int value
+ * */
public LuaInteger optinteger(int i, LuaInteger defval) { return arg(i).optinteger(defval); }
+
+ /** Return argument i as a java long value, discarding any fractional part, {@code defval} if nil, or throw a LuaError if not a number.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return long value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a number
+ * */
public long optlong(int i, long defval) { return arg(i).optlong(defval); }
+
+ /** Return argument i as a LuaNumber, {@code defval} if nil, or throw a LuaError if not a number or string that can be converted to a number.
+ * @param i the index of the argument to test, 1 is the first argument, or defval if not supplied or nil
+ * @return LuaNumber if argument i is number or can be converted to a number
+ * @exception LuaError if the argument is not a number
+ * */
public LuaNumber optnumber(int i, LuaNumber defval) { return arg(i).optnumber(defval); }
+
+ /** Return argument i as a java String if a string or number, {@code defval} if nil, or throw a LuaError if any other type
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return String value if argument i is a string or number, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a string or number
+ * */
public String optjstring(int i, String defval) { return arg(i).optjstring(defval); }
+
+ /** Return argument i as a LuaString if a string or number, {@code defval} if nil, or throw a LuaError if any other type
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaString value if argument i is a string or number, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a string or number
+ * */
public LuaString optstring(int i, LuaString defval) { return arg(i).optstring(defval); }
+
+ /** Return argument i as a LuaTable if a lua table, {@code defval} if nil, or throw a LuaError if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaTable value if a table, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a lua table
+ * */
public LuaTable opttable(int i, LuaTable defval) { return arg(i).opttable(defval); }
+
+ /** Return argument i as a LuaThread if a lua thread, {@code defval} if nil, or throw a LuaError if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaThread value if a thread, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a lua thread
+ * */
public LuaThread optthread(int i, LuaThread defval) { return arg(i).optthread(defval); }
+
+ /** Return argument i as a java Object if a userdata, {@code defval} if nil, or throw a LuaError if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return java Object value if argument i is a userdata, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a userdata
+ * */
public Object optuserdata(int i, Object defval) { return arg(i).optuserdata(defval); }
+
+ /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
+ * {@code defval} if nil, or throw a LuaError if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @param c the class to which the userdata instance must be assignable
+ * @return java Object value if argument i is a userdata whose instance Class c or a subclass, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable
+ * */
public Object optuserdata(int i, Class c, Object defval) { return arg(i).optuserdata(c,defval); }
+
+ /** Return argument i as a LuaValue if it exists, or {@code defval}.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaValue value if the argument exists, defval if not
+ * @exception LuaError if the argument does not exist.
+ * */
public LuaValue optvalue(int i, LuaValue defval) { return i>0 && i<=narg()? arg(i): defval; }
- // required argument types
+ /** Return argument i as a boolean value, or throw an error if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if argument i is boolean true, false if it is false
+ * @exception LuaError if the argument is not a lua boolean
+ * */
public boolean checkboolean(int i) { return arg(i).checkboolean(); }
+
+ /** Return argument i as a closure, or throw an error if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaClosure if argument i is a closure.
+ * @exception LuaError if the argument is not a lua closure
+ * */
public LuaClosure checkclosure(int i) { return arg(i).checkclosure(); }
+
+ /** Return argument i as a double, or throw an error if it cannot be converted to one.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return java double value if argument i is a number or string that converts to a number
+ * @exception LuaError if the argument is not a number
+ * */
public double checkdouble(int i) { return arg(i).checknumber().todouble(); }
+
+ /** Return argument i as a function, or throw an error if an incompatible type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaValue that can be called if argument i is lua function or closure
+ * @exception LuaError if the argument is not a lua function or closure
+ * */
public LuaValue checkfunction(int i) { return arg(i).checkfunction(); }
+
+ /** Return argument i as a java int value, discarding any fractional part, or throw an error if not a number.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return int value with fraction discarded and truncated if necessary if argument i is number
+ * @exception LuaError if the argument is not a number
+ * */
public int checkint(int i) { return arg(i).checknumber().toint(); }
+
+ /** Return argument i as a java int value, or throw an error if not a number or is not representable by a java int.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaInteger value that fits in a java int without rounding
+ * @exception LuaError if the argument cannot be represented by a java int value
+ * */
public LuaInteger checkinteger(int i) { return arg(i).checkinteger(); }
+
+ /** Return argument i as a java long value, discarding any fractional part, or throw an error if not a number.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return long value with fraction discarded and truncated if necessary if argument i is number
+ * @exception LuaError if the argument is not a number
+ * */
public long checklong(int i) { return arg(i).checknumber().tolong(); }
+
+ /** Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaNumber if argument i is number or can be converted to a number
+ * @exception LuaError if the argument is not a number
+ * */
public LuaNumber checknumber(int i) { return arg(i).checknumber(); }
+
+ /** Return argument i as a java String if a string or number, or throw an error if any other type
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return String value if argument i is a string or number
+ * @exception LuaError if the argument is not a string or number
+ * */
public String checkjstring(int i) { return arg(i).checkjstring(); }
+
+ /** Return argument i as a LuaString if a string or number, or throw an error if any other type
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaString value if argument i is a string or number
+ * @exception LuaError if the argument is not a string or number
+ * */
public LuaString checkstring(int i) { return arg(i).checkstring(); }
+
+ /** Return argument i as a LuaTable if a lua table, or throw an error if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaTable value if a table
+ * @exception LuaError if the argument is not a lua table
+ * */
public LuaTable checktable(int i) { return arg(i).checktable(); }
+
+ /** Return argument i as a LuaThread if a lua thread, or throw an error if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaThread value if a thread
+ * @exception LuaError if the argument is not a lua thread
+ * */
public LuaThread checkthread(int i) { return arg(i).checkthread(); }
+
+ /** Return argument i as a java Object if a userdata, or throw an error if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return java Object value if argument i is a userdata
+ * @exception LuaError if the argument is not a userdata
+ * */
public Object checkuserdata(int i) { return arg(i).checkuserdata(); }
+
+ /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
+ * or throw an error if any other type.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @param c the class to which the userdata instance must be assignable
+ * @return java Object value if argument i is a userdata whose instance Class c or a subclass
+ * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable
+ * */
public Object checkuserdata(int i,Class c) { return arg(i).checkuserdata(c); }
+
+ /** Return argument i as a LuaValue if it exists, or throw an error.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaValue value if the argument exists
+ * @exception LuaError if the argument does not exist.
+ * */
public LuaValue checkvalue(int i) { return i<=narg()? arg(i): LuaValue.argerror(i,"value expected"); }
+
+ /** Return argument i as a LuaValue if it is not nil, or throw an error if it is nil.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return LuaValue value if the argument is not nil
+ * @exception LuaError if the argument doesn't exist or evaluates to nil.
+ * */
public LuaValue checknotnil(int i) { return arg(i).checknotnil(); }
+ /** Return argument i as a LuaValue when a user-supplied assertion passes, or throw an error.
+ * @param test user supplied assertion to test against
+ * @param i the index to report in any error message
+ * @param msg the error message to use when the test fails
+ * @return LuaValue value if the value of {@code test} is {@code true}
+ * @exception LuaError if the the value of {@code test} is {@code false}
+ * */
public void argcheck(boolean test, int i, String msg) { if (!test) LuaValue.argerror(i,msg); }
+ /** Return true if there is no argument or nil at argument i.
+ * @param i the index of the argument to test, 1 is the first argument
+ * @return true if argument i contains either no argument or nil
+ * */
public boolean isnoneornil(int i) {
return i>narg() || arg(i).isnil();
}
+ /** Convert argument {@code i} to java boolean based on lua rules for boolean evaluation.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return {@code false} if argument i is nil or false, otherwise {@code true}
+ * */
public boolean toboolean(int i) { return arg(i).toboolean(); }
+
+ /** Return argument i as a java byte value, discarding any fractional part and truncating,
+ * or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+ * */
public byte tobyte(int i) { return arg(i).tobyte(); }
+
+ /** Return argument i as a java char value, discarding any fractional part and truncating,
+ * or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+ * */
public char tochar(int i) { return arg(i).tochar(); }
+
+ /** Return argument i as a java double value or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return double value if argument i is number, otherwise 0
+ * */
public double todouble(int i) { return arg(i).todouble(); }
+
+ /** Return argument i as a java float value, discarding excess fractional part and truncating,
+ * or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0
+ * */
public float tofloat(int i) { return arg(i).tofloat(); }
+
+ /** Return argument i as a java int value, discarding any fractional part and truncating,
+ * or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+ * */
public int toint(int i) { return arg(i).toint(); }
+
+ /** Return argument i as a java long value, discarding any fractional part and truncating,
+ * or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+ * */
public long tolong(int i) { return arg(i).tolong(); }
+
+ /** Return argument i as a java String based on the type of the argument.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return String value representing the type
+ * */
public String tojstring(int i) { return arg(i).tojstring(); }
+
+ /** Return argument i as a java short value, discarding any fractional part and truncating,
+ * or 0 if not a number.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+ * */
public short toshort(int i) { return arg(i).toshort(); }
+
+ /** Return argument i as a java Object if a userdata, or null.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return java Object value if argument i is a userdata, otherwise null
+ * */
public Object touserdata(int i) { return arg(i).touserdata(); }
+
+ /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null.
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @param c the class to which the userdata instance must be assignable
+ * @return java Object value if argument i is a userdata whose instance Class c or a subclass, otherwise null
+ * */
public Object touserdata(int i,Class c) { return arg(i).touserdata(c); }
+ /** Convert the list of varargs values to a human readable java String.
+ * @return String value in human readable form such as {1,2}.
+ */
public String tojstring() {
Buffer sb = new Buffer();
sb.append( "(" );
@@ -138,9 +490,17 @@ public abstract class Varargs {
return sb.tojstring();
}
- // Object.toString() maps to tojstring()
+ /** Convert the value or values to a java String using Varargs.tojstring()
+ * @return String value in human readable form.
+ * @see Varargs#tojstring()
+ */
public String toString() { return tojstring(); }
+ /**
+ * Create a {@code Varargs} instance containing arguments starting at index {@code start}
+ * @param start the index from which to include arguments, where 1 is the first argument.
+ * @return Varargs containing argument { start, start+1, ... , narg-start-1 }
+ */
public Varargs subargs(final int start) {
int end = narg();
switch ( end-start ) {
@@ -149,7 +509,11 @@ public abstract class Varargs {
}
return end