All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.weeaboo.lua2.vm.Varargs Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2009 Luaj.org. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

package nl.weeaboo.lua2.vm;

import static nl.weeaboo.lua2.vm.LuaConstants.NONE;
import static nl.weeaboo.lua2.vm.LuaNil.NIL;

import java.io.Serializable;

import javax.annotation.Nullable;

import nl.weeaboo.lua2.LuaException;
import nl.weeaboo.lua2.io.LuaSerializable;

/**
 * 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 LuaValue#varargsOf(LuaValue[]) * @see LuaValue#varargsOf(LuaValue, Varargs) * @see LuaValue#varargsOf(LuaValue[], Varargs) * @see LuaValue#varargsOf(LuaValue, LuaValue, Varargs) * @see LuaValue#varargsOf(LuaValue[], int, int) * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) * @see LuaValue#subargs(int) */ public abstract class Varargs { /** * 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() */ public abstract LuaValue arg(int i); /** * Get the number of arguments, or 0 if there are none. * * @return number of arguments. */ public abstract int narg(); /** * 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) */ public abstract LuaValue arg1(); // ----------------------------------------------------------------------- // utilities to get specific arguments and type-check them. // ----------------------------------------------------------------------- /** * 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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(); } /** * 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException if the argument is not a userdata or from whose instance c is not assignable */ public T optuserdata(int i, Class c, T 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 LuaException if the argument does not exist. */ public LuaValue optvalue(int i, LuaValue defval) { return i > 0 && i <= narg() ? arg(i) : defval; } /** * 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException 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 LuaException if the argument is not a userdata or from whose instance c is not assignable */ public T 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 LuaException if the argument does not exist. */ public LuaValue checkvalue(int i) { if (i <= narg()) { return arg(i); } throw 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 LuaException 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 * @exception LuaException 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(); } /** * 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("("); for (int i = 1, n = narg(); i <= n; i++) { if (i > 1) { sb.append(","); } sb.append(arg(i).tojstring()); } sb.append(")"); return sb.tojstring(); } /** * 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 @Nullable 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 @Nullable T touserdata(int i, Class c) { return arg(i).touserdata(c); } /** * Convert the value or values to a java String using Varargs.tojstring() * * @return String value in human readable form. * @see Varargs#tojstring() */ @Override 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) { case 0: return arg(start); case 1: return new PairVarargs(arg(start), arg(end)); default: if (end < start) { return NONE; } else { return new SubVarargs(this, start, end); } } } /** * Implementation of Varargs for use in the Varargs.subargs() function. * * @see Varargs#subargs(int) */ @LuaSerializable private static class SubVarargs extends Varargs implements Serializable { private static final long serialVersionUID = 4816221998053924293L; private final Varargs v; private final int start; private final int end; public SubVarargs(Varargs varargs, int start, int end) { this.v = varargs; this.start = start; this.end = end; } @Override public LuaValue arg(int i) { i += start - 1; return i >= start && i <= end ? v.arg(i) : NIL; } @Override public LuaValue arg1() { return v.arg(start); } @Override public int narg() { return end + 1 - start; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy