/*******************************************************************************
* Copyright (c) 2009-2011 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 org.luaj.vm2;

/**
 * Base class for all concrete lua type values.
 * <p>
 * Establishes base implementations for all the operations on lua types.
 * This allows Java clients to deal essentially with one type for all Java values, namely {@link LuaValue}.
 * <p>
 * Constructors are provided as static methods for common Java types, such as
 * {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(String)}
 * to allow for instance pooling.
 * <p>
 * Constants are defined for the lua values
 * {@link #NIL}, {@link #TRUE}, and {@link #FALSE}.
 * A constant {@link #NONE} is defined which is a {@link Varargs} list having no values.
 * <p>
 * Operations are performed on values directly via their Java methods.
 * For example, the following code divides two numbers:
 * <pre> {@code
 * LuaValue a = LuaValue.valueOf( 5 );
 * LuaValue b = LuaValue.valueOf( 4 );
 * LuaValue c = a.div(b);
 * } </pre>
 * Note that in this example, c will be a {@link LuaDouble}, but would be a {@link LuaInteger}
 * if the value of a were changed to 8, say.
 * In general the value of c in practice will vary depending on both the types and values of a and b
 * as well as any metatable/metatag processing that occurs.
 * <p>
 * Field access and function calls are similar, with common overloads to simplify Java usage:
 * <pre> {@code
 * LuaValue globals = JsePlatform.standardGlobals();
 * LuaValue sqrt = globals.get("math").get("sqrt");
 * LuaValue print = globals.get("print");
 * LuaValue d = sqrt.call( a );
 * print.call( LuaValue.valueOf("sqrt(5):"), a );
 * } </pre>
 * <p>
 * To supply variable arguments or get multiple return values, use
 * {@link #invoke(Varargs)} or {@link #invokemethod(LuaValue, Varargs)} methods:
 * <pre> {@code
 * LuaValue modf = globals.get("math").get("modf");
 * Varargs r = modf.invoke( d );
 * print.call( r.arg(1), r.arg(2) );
 * } </pre>
 * <p>
 * To load and run a script, {@link LoadState} is used:
 * <pre> {@code
 * LoadState.load( new FileInputStream("main.lua"), "main.lua", globals ).call();
 * } </pre>
 * <p>
 * although {@code require} could also be used:
 * <pre> {@code
 * globals.get("require").call(LuaValue.valueOf("main"));
 * } </pre>
 * For this to work the file must be in the current directory, or in the class path,
 * dependening on the platform.
 * See {@link org.luaj.vm2.libs.jse.JsePlatform} and {@link org.luaj.vm2.libs.jme.JmePlatform} for details.
 * <p>
 * In general a {@link LuaError} may be thrown on any operation when the
 * types supplied to any operation are illegal from a lua perspective.
 * Examples could be attempting to concatenate a NIL value, or attempting arithmetic
 * on values that are not number.
 * <p>
 * There are several methods for preinitializing tables, such as:
 * <ul>
 * <li>{@link #listOf(LuaValue[])} for unnamed elements</li>
 * <li>{@link #tableOf(LuaValue[])} for named elements</li>
 * <li>{@link #tableOf(LuaValue[], LuaValue[], Varargs)} for mixtures</li>
 * </ul>
 * <p>
 * Predefined constants exist for the standard lua type constants
 * {@link #TNIL}, {@link #TBOOLEAN}, {@link #TLIGHTUSERDATA}, {@link #TNUMBER}, {@link #TSTRING},
 * {@link #TTABLE}, {@link #TFUNCTION}, {@link #TUSERDATA}, {@link #TTHREAD},
 * and extended lua type constants
 * {@link #TINT}, {@link #TNONE}, {@link #TVALUE}
 * <p>
 * Predefined constants exist for all strings used as metatags:
 * {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE},
 * {@link #ADD}, {@link #SUB}, {@link #DIV}, {@link #MUL}, {@link #POW},
 * {@link #MOD}, {@link #UNM}, {@link #LEN}, {@link #EQ}, {@link #LT},
 * {@link #LE}, {@link #TOSTRING}, {@link #CONCAT}, {@link #PAIRS}, and {@link #IPAIRS}.
 * 
 * @see org.luaj.vm2.libs.jse.JsePlatform
 * @see org.luaj.vm2.libs.jme.JmePlatform
 * @see LoadState
 * @see Varargs
 */
abstract
public class LuaValue extends Varargs {
	
	/** Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only */
	public static final int TINT            = (-2);
	
	/** Type enumeration constant for lua values that have no type, for example weak table entries */
	public static final int TNONE			= (-1);
	
	/** Type enumeration constant for lua nil */
	public static final int TNIL			= 0;
	
	/** Type enumeration constant for lua booleans */
	public static final int TBOOLEAN		= 1;
	
	/** Type enumeration constant for lua light userdata, for compatibility with C-based lua only */
	public static final int TLIGHTUSERDATA	= 2;
	
	/** Type enumeration constant for lua numbers */
	public static final int TNUMBER			= 3;
	
	/** Type enumeration constant for lua strings */
	public static final int TSTRING			= 4;
	
	/** Type enumeration constant for lua tables */
	public static final int TTABLE			= 5;
	
	/** Type enumeration constant for lua functions */
	public static final int TFUNCTION		= 6;
	
	/** Type enumeration constant for lua userdatas */
	public static final int TUSERDATA		= 7;
	
	/** Type enumeration constant for lua threads */
	public static final int TTHREAD			= 8;
	
	/** Type enumeration constant for unknown values, for compatibility with C-based lua only */
	public static final int TVALUE          = 9;

	/** String array constant containing names of each of the lua value types
	 * @see #type()
	 * @see #typename()
	 */
	public static final String[] TYPE_NAMES = {
		"nil",
		"boolean",
		"lightuserdata",
		"number",
		"string",
		"table",
		"function",
		"userdata",
		"thread",
		"value",
	};
	
	/** LuaValue constant corresponding to lua {@code #NIL} */
	public static final LuaValue   NIL       = LuaNil._NIL;
	
	/** LuaBoolean constant corresponding to lua {@code true} */
	public static final LuaBoolean TRUE      = LuaBoolean._TRUE;

	/** LuaBoolean constant corresponding to lua {@code false} */
	public static final LuaBoolean FALSE     = LuaBoolean._FALSE;

	/** LuaValue constant corresponding to a {@link Varargs} list of no values */
	public static final LuaValue   NONE      = None._NONE;
	
	/** LuaValue number constant equal to 0 */
	public static final LuaNumber  ZERO      = LuaInteger.valueOf(0);
	
	/** LuaValue number constant equal to 1 */
	public static final LuaNumber  ONE       = LuaInteger.valueOf(1);

	/** LuaValue number constant equal to -1 */
	public static final LuaNumber  MINUSONE  = LuaInteger.valueOf(-1);
	
	/** LuaValue array constant with no values */
	public static final LuaValue[] NOVALS    = {};

	/** The variable name of the environment. */
	public static LuaString ENV               = valueOf("_ENV");

	/** LuaString constant with value "__index" for use as metatag */
	public static final LuaString INDEX       = valueOf("__index");

	/** LuaString constant with value "__newindex" for use as metatag */
	public static final LuaString NEWINDEX    = valueOf("__newindex");

	/** LuaString constant with value "__call" for use as metatag */
	public static final LuaString CALL        = valueOf("__call");

	/** LuaString constant with value "__mode" for use as metatag */
	public static final LuaString MODE        = valueOf("__mode");

	/** LuaString constant with value "__metatable" for use as metatag */
	public static final LuaString METATABLE   = valueOf("__metatable");

	/** LuaString constant with value "__add" for use as metatag */
	public static final LuaString ADD         = valueOf("__add");

	/** LuaString constant with value "__sub" for use as metatag */
	public static final LuaString SUB         = valueOf("__sub");

	/** LuaString constant with value "__div" for use as metatag */
	public static final LuaString DIV         = valueOf("__div");

	/** LuaString constant with value "__idiv" for use as metatag */
	public static final LuaString IDIV        = valueOf("__idiv");

	/** LuaString constant with value "__band" for use as metatag */
	public static final LuaString BAND        = valueOf("__band");

	/** LuaString constant with value "__bor" for use as metatag */
	public static final LuaString BOR         = valueOf("__bor");

	/** LuaString constant with value "__bxor" for use as metatag */
	public static final LuaString BXOR        = valueOf("__bxor");

	/** LuaString constant with value "__shl" for use as metatag */
	public static final LuaString SHL         = valueOf("__shl");

	/** LuaString constant with value "__shr" for use as metatag */
	public static final LuaString SHR         = valueOf("__shr");

	/** LuaString constant with value "__bnot" for use as metatag */
	public static final LuaString BNOT        = valueOf("__bnot");

	/** LuaString constant with value "__mul" for use as metatag */
	public static final LuaString MUL         = valueOf("__mul");

	/** LuaString constant with value "__pow" for use as metatag */
	public static final LuaString POW         = valueOf("__pow");

	/** LuaString constant with value "__mod" for use as metatag */
	public static final LuaString MOD         = valueOf("__mod");

	/** LuaString constant with value "__unm" for use as metatag */
	public static final LuaString UNM         = valueOf("__unm");

	/** LuaString constant with value "__len" for use as metatag */
	public static final LuaString LEN         = valueOf("__len");

	/** LuaString constant with value "__eq" for use as metatag */
	public static final LuaString EQ          = valueOf("__eq");

	/** LuaString constant with value "__lt" for use as metatag */
	public static final LuaString LT          = valueOf("__lt");

	/** LuaString constant with value "__le" for use as metatag */
	public static final LuaString LE          = valueOf("__le");

	/** LuaString constant with value "__tostring" for use as metatag */
	public static final LuaString TOSTRING    = valueOf("__tostring");

	/** LuaString constant with value "__concat" for use as metatag */
	public static final LuaString CONCAT      = valueOf("__concat");

	/** LuaString constant with value "__pairs" for use as metatag */
	public static final LuaString PAIRS       = valueOf("__pairs");

	/** LuaString constant with value "__ipairs" for use as metatag */
	public static final LuaString IPAIRS      = valueOf("__ipairs");

	/** LuaString constant with value "__close" for use as metatag */
	public static final LuaString CLOSE       = valueOf("__close");
	
	/** LuaString constant with value "" */
	public static final LuaString EMPTYSTRING = valueOf("");

	/** Limit on lua stack size */
	private static int MAXSTACK = 250;
	
	/** Array of {@link #NIL} values to optimize filling stacks using System.arraycopy().
	 * Must not be modified.
	 */
	public static final LuaValue[] NILS = new LuaValue[MAXSTACK];
	static {
		for ( int i=0; i<MAXSTACK; i++ )
			NILS[i] = NIL;
	}
	
	// type
	/** Get the enumeration value for the type of this value.
	 * @return value for this type, one of
	 * {@link #TNIL},
	 * {@link #TBOOLEAN},
	 * {@link #TNUMBER},
	 * {@link #TSTRING},
	 * {@link #TTABLE},
	 * {@link #TFUNCTION},
	 * {@link #TUSERDATA},
	 * {@link #TTHREAD}
	 * @see #typename()
	 */
	abstract public int type();
	
	/** Get the String name of the type of this value.
	 * <p>
	 * 
	 * @return name from type name list {@link #TYPE_NAMES}
	 * corresponding to the type of this value:
	 * "nil", "boolean", "number", "string",
	 * "table", "function", "userdata", "thread"
	 * @see #type()
	 */
	abstract public String  typename();

	/** Check if {@code this} is a {@code boolean}
	 * @return true if this is a {@code boolean}, otherwise false
	 * @see #isboolean()
	 * @see #toboolean()
	 * @see #checkboolean()
	 * @see #optboolean(boolean)
	 * @see #TBOOLEAN
	 */
	public boolean isboolean()           { return false; }

	/** Check if {@code this} is a {@code function} that is a closure,
	 * meaning interprets lua bytecode for its execution
	 * @return true if this is a {@code closure}, otherwise false
	 * @see #isfunction()
	 * @see #checkclosure()
	 * @see #optclosure(LuaClosure)
	 * @see #TFUNCTION
	 */
	public boolean isclosure()           { return false; }

	/** Check if {@code this} is a {@code function}
	 * @return true if this is a {@code function}, otherwise false
	 * @see #isclosure()
	 * @see #checkfunction()
	 * @see #optfunction(LuaFunction)
	 * @see #TFUNCTION
	 */
	public boolean isfunction()          { return false; }
	
	/** Check if {@code this} is a {@code number} and is representable by java int
	 * without rounding or truncation
	 * @return true if this is a {@code number}
	 * meaning derives from {@link LuaNumber}
	 * or derives from {@link LuaString} and is convertible to a number,
	 * and can be represented by int,
	 * otherwise false
	 * @see #isinttype()
	 * @see #islong()
	 * @see #tonumber()
	 * @see #checkint()
	 * @see #optint(int)
	 * @see #TNUMBER
	 */
	public boolean isint()               { return false; }

	/** Check if {@code this} is a {@link LuaInteger}
	 * <p>
	 * No attempt to convert from string will be made by this call.
	 * @return true if this is a {@code LuaInteger},
	 * otherwise false
	 * @see #isint()
	 * @see #isnumber()
	 * @see #tonumber()
	 * @see #TNUMBER
	 */
	public boolean isinttype()           { return false; }
	
	/** Check if {@code this} is a {@code number} and is representable by java long
	 * without rounding or truncation
	 * @return true if this is a {@code number}
	 * meaning derives from {@link LuaNumber}
	 * or derives from {@link LuaString} and is convertible to a number,
	 * and can be represented by long,
	 * otherwise false
	 * @see #tonumber()
	 * @see #checklong()
	 * @see #optlong(long)
	 * @see #TNUMBER
	 */
	public boolean islong()              { return false; }
	
	/** Check if {@code this} is {@code #NIL}
	 * @return true if this is {@code #NIL}, otherwise false
	 * @see #NIL
	 * @see #NONE
	 * @see #checknotnil()
	 * @see #optvalue(LuaValue)
	 * @see Varargs#isnoneornil(int)
	 * @see #TNIL
	 * @see #TNONE
	 */
	public boolean isnil()               { return false; }
	
	/** Check if {@code this} is a {@code number}
	 * @return true if this is a {@code number},
	 * meaning derives from {@link LuaNumber}
	 * or derives from {@link LuaString} and is convertible to a number,
	 * otherwise false
	 * @see #tonumber()
	 * @see #checknumber()
	 * @see #optnumber(LuaNumber)
	 * @see #TNUMBER
	 */
	public boolean isnumber()            { return false; } // may convert from string
	
	/** Check if {@code this} is a {@code string}
	 * @return true if this is a {@code string},
	 * meaning derives from {@link LuaString} or {@link LuaNumber},
	 * otherwise false
	 * @see #tostring()
	 * @see #checkstring()
	 * @see #optstring(LuaString)
	 * @see #TSTRING
	 */
	public boolean isstring()            { return false; }
	
	/** Check if {@code this} is a {@code thread}
	 * @return true if this is a {@code thread}, otherwise false
	 * @see #checkthread()
	 * @see #optthread(LuaThread)
	 * @see #TTHREAD
	 */
	public boolean isthread()            { return false; }
	
	/** Check if {@code this} is a {@code table}
	 * @return true if this is a {@code table}, otherwise false
	 * @see #checktable()
	 * @see #opttable(LuaTable)
	 * @see #TTABLE
	 */
	public boolean istable()             { return false; }
	
	/** Check if {@code this} is a {@code userdata}
	 * @return true if this is a {@code userdata}, otherwise false
	 * @see #isuserdata(Class)
	 * @see #touserdata()
	 * @see #checkuserdata()
	 * @see #optuserdata(Object)
	 * @see #TUSERDATA
	 */
	public boolean isuserdata()          { return false; }
	
	/** Check if {@code this} is a {@code userdata} of type {@code c}
	 * @param c Class to test instance against
	 * @return true if this is a {@code userdata}
	 * and the instance is assignable to {@code c},
	 * otherwise false
	 * @see #isuserdata()
	 * @see #touserdata(Class)
	 * @see #checkuserdata(Class)
	 * @see #optuserdata(Class, Object)
	 * @see #TUSERDATA
	 */
	public boolean isuserdata(Class c)   { return false; }
	
	/** Convert to boolean false if {@link #NIL} or {@link #FALSE}, true if anything else
	 * @return Value cast to byte if number or string convertible to number, otherwise 0
	 * @see #optboolean(boolean)
	 * @see #checkboolean()
	 * @see #isboolean()
	 * @see #TBOOLEAN
	 */
	public boolean toboolean()           { return true; }
	
	/** Convert to byte if numeric, or 0 if not.
	 * @return Value cast to byte if number or string convertible to number, otherwise 0
	 * @see #toint()
	 * @see #todouble()
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public byte    tobyte()              { return 0; }
	
	/** Convert to char if numeric, or 0 if not.
	 * @return Value cast to char if number or string convertible to number, otherwise 0
	 * @see #toint()
	 * @see #todouble()
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public char    tochar()              { return 0; }
	
	/** Convert to double if numeric, or 0 if not.
	 * @return Value cast to double if number or string convertible to number, otherwise 0
	 * @see #toint()
	 * @see #tobyte()
	 * @see #tochar()
	 * @see #toshort()
	 * @see #tolong()
	 * @see #tofloat()
	 * @see #optdouble(double)
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public double  todouble()            { return 0; }
	
	/** Convert to float if numeric, or 0 if not.
	 * @return Value cast to float if number or string convertible to number, otherwise 0
	 * @see #toint()
	 * @see #todouble()
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public float   tofloat()             { return 0; }
	
	/** Convert to int if numeric, or 0 if not.
	 * @return Value cast to int if number or string convertible to number, otherwise 0
	 * @see #tobyte()
	 * @see #tochar()
	 * @see #toshort()
	 * @see #tolong()
	 * @see #tofloat()
	 * @see #todouble()
	 * @see #optint(int)
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public int     toint()               { return 0; }
	
	/** Convert to long if numeric, or 0 if not.
	 * @return Value cast to long if number or string convertible to number, otherwise 0
	 * @see #isint()
	 * @see #isinttype()
	 * @see #toint()
	 * @see #todouble()
	 * @see #optlong(long)
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public long    tolong()              { return 0; }
	
	/** Convert to short if numeric, or 0 if not.
	 * @return Value cast to short if number or string convertible to number, otherwise 0
	 * @see #toint()
	 * @see #todouble()
	 * @see #checknumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public short   toshort()             { return 0; }
	
	/** Convert to human readable String for any type.
	 * @return String for use by human readers based on type.
	 * @see #tostring()
	 * @see #optjstring(String)
	 * @see #checkjstring()
	 * @see #isstring()
	 * @see #TSTRING
	 */
	public String  tojstring()           { return typename() + ": " + Integer.toHexString(hashCode()); }
	
	/** Convert to userdata instance, or null.
	 * @return userdata instance if userdata, or null if not {@link LuaUserdata}
	 * @see #optuserdata(Object)
	 * @see #checkuserdata()
	 * @see #isuserdata()
	 * @see #TUSERDATA
	 */
	public Object  touserdata()          { return null; }
	
	/** Convert to userdata instance if specific type, or null.
	 * @return userdata instance if is a userdata whose instance derives from {@code c},
	 * or null if not {@link LuaUserdata}
	 * @see #optuserdata(Class,Object)
	 * @see #checkuserdata(Class)
	 * @see #isuserdata(Class)
	 * @see #TUSERDATA
	 */
	public Object  touserdata(Class c)   { return null; }

	/**
	 * Convert the value to a human readable string using {@link #tojstring()}
	 * @return String value intended to be human readible.
	 * @see #tostring()
	 * @see #tojstring()
	 * @see #optstring(LuaString)
	 * @see #checkstring()
	 * @see #toString()
	 */
	public String toString() { return tojstring(); }
	
	/** Conditionally convert to lua number without throwing errors.
	 * <p>
	 * In lua all numbers are strings, but not all strings are numbers.
	 * This function will return
	 * the {@link LuaValue} {@code this} if it is a number
	 * or a string convertible to a number,
	 * and {@link #NIL} for all other cases.
	 * <p>
	 * This allows values to be tested for their "numeric-ness" without
	 * the penalty of throwing exceptions,
	 * nor the cost of converting the type and creating storage for it.
	 * @return {@code this} if it is a {@link LuaNumber}
	 * or {@link LuaString} that can be converted to a number,
	 * otherwise {@link #NIL}
	 * @see #tostring()
	 * @see #optnumber(LuaNumber)
	 * @see #checknumber()
	 * @see #toint()
	 * @see #todouble()
	 */
	public LuaValue    tonumber()     { return NIL; }
	
	/** Conditionally convert to lua string without throwing errors.
	 * <p>
	 * In lua all numbers are strings, so this function will return
	 * the {@link LuaValue} {@code this} if it is a string or number,
	 * and {@link #NIL} for all other cases.
	 * <p>
	 * This allows values to be tested for their "string-ness" without
	 * the penalty of throwing exceptions.
	 * @return {@code this} if it is a {@link LuaString} or {@link LuaNumber},
	 * otherwise {@link #NIL}
	 * @see #tonumber()
	 * @see #tojstring()
	 * @see #optstring(LuaString)
	 * @see #checkstring()
	 * @see #toString()
	 */
	public LuaValue    tostring()     { return NIL; }

	/** Check that optional argument is a boolean and return its boolean value
	 * @param defval boolean value to return if {@code this} is nil or none
	 * @return {@code this} cast to boolean if a {@link LuaBoolean},
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not a boolean or nil or none.
	 * @see #checkboolean()
	 * @see #isboolean()
	 * @see #TBOOLEAN
	 */
	public boolean     optboolean(boolean defval)          { argerror("boolean");   return false; }

	/** Check that optional argument is a closure and return as {@link LuaClosure}
	 * <p>
	 * A {@link LuaClosure} is a {@link LuaFunction} that executes lua byteccode.
	 * @param defval {@link LuaClosure} to return if {@code this} is nil or none
	 * @return {@code this} cast to {@link LuaClosure} if a function,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not a closure or nil or none.
	 * @see #checkclosure()
	 * @see #isclosure()
	 * @see #TFUNCTION
	 */
	public LuaClosure  optclosure(LuaClosure defval)       { argerror("closure");   return null;  }

	/** Check that optional argument is a number or string convertible to number and return as double
	 * @param defval double to return if {@code this} is nil or none
	 * @return {@code this} cast to double if numeric,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not numeric or nil or none.
	 * @see #optint(int)
	 * @see #optinteger(LuaInteger)
	 * @see #checkdouble()
	 * @see #todouble()
	 * @see #tonumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public double      optdouble(double defval)            { argerror("number");    return 0;     }

	/** Check that optional argument is a function and return as {@link LuaFunction}
	 * <p>
	 * A {@link LuaFunction} may either be a Java function that implements
	 * functionality directly in Java,  or a {@link LuaClosure}
	 * which is a {@link LuaFunction} that executes lua bytecode.
	 * @param defval {@link LuaFunction} to return if {@code this} is nil or none
	 * @return {@code this} cast to {@link LuaFunction} if a function,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not a function or nil or none.
	 * @see #checkfunction()
	 * @see #isfunction()
	 * @see #TFUNCTION
	 */
	public LuaFunction optfunction(LuaFunction defval)     { argerror("function");  return null;  }

	/** Check that optional argument is a number or string convertible to number and return as int
	 * @param defval int to return if {@code this} is nil or none
	 * @return {@code this} cast to int if numeric,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not numeric or nil or none.
	 * @see #optdouble(double)
	 * @see #optlong(long)
	 * @see #optinteger(LuaInteger)
	 * @see #checkint()
	 * @see #toint()
	 * @see #tonumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public int         optint(int defval)                  { argerror("int");       return 0;     }

	/** Check that optional argument is a number or string convertible to number and return as {@link LuaInteger}
	 * @param defval {@link LuaInteger} to return if {@code this} is nil or none
	 * @return {@code this} converted and wrapped in {@link LuaInteger} if numeric,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not numeric or nil or none.
	 * @see #optdouble(double)
	 * @see #optint(int)
	 * @see #checkint()
	 * @see #toint()
	 * @see #tonumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public LuaInteger  optinteger(LuaInteger defval)       { argerror("integer");   return null;  }

	/** Check that optional argument is a number or string convertible to number and return as long
	 * @param defval long to return if {@code this} is nil or none
	 * @return {@code this} cast to long if numeric,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not numeric or nil or none.
	 * @see #optdouble(double)
	 * @see #optint(int)
	 * @see #checkint()
	 * @see #toint()
	 * @see #tonumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public long        optlong(long defval)                { argerror("long");      return 0;     }

	/** Check that optional argument is a number or string convertible to number and return as {@link LuaNumber}
	 * @param defval {@link LuaNumber} to return if {@code this} is nil or none
	 * @return {@code this} cast to {@link LuaNumber} if numeric,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} otherwise
	 * @throws LuaError if was not numeric or nil or none.
	 * @see #optdouble(double)
	 * @see #optlong(long)
	 * @see #optint(int)
	 * @see #checkint()
	 * @see #toint()
	 * @see #tonumber()
	 * @see #isnumber()
	 * @see #TNUMBER
	 */
	public LuaNumber   optnumber(LuaNumber defval)         { argerror("number");    return null;  }

	/** Check that optional argument is a string or number and return as Java String
	 * @param defval {@link LuaString} to return if {@code this} is nil or none
	 * @return {@code this} converted to String if a string or number,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} if some other type
	 * @throws LuaError if was not a string or number or nil or none.
	 * @see #tojstring()
	 * @see #optstring(LuaString)
	 * @see #checkjstring()
	 * @see #toString()
	 * @see #TSTRING
	 */
	public String      optjstring(String defval)           { argerror("String");    return null;  }

	/** Check that optional argument is a string or number and return as {@link LuaString}
	 * @param defval {@link LuaString} to return if {@code this} is nil or none
	 * @return {@code this} converted to {@link LuaString} if a string or number,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} if some other type
	 * @throws LuaError if was not a string or number or nil or none.
	 * @see #tojstring()
	 * @see #optjstring(String)
	 * @see #checkstring()
	 * @see #toString()
	 * @see #TSTRING
	 */
	public LuaString   optstring(LuaString defval)         { argerror("string");    return null;  }

	/** Check that optional argument is a table and return as {@link LuaTable}
	 * @param defval {@link LuaTable} to return if {@code this} is nil or none
	 * @return {@code this} cast to {@link LuaTable} if a table,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} if some other type
	 * @throws LuaError if was not a table or nil or none.
	 * @see #checktable()
	 * @see #istable()
	 * @see #TTABLE
	 */
	public LuaTable    opttable(LuaTable defval)           { argerror("table");     return null;  }

	/** Check that optional argument is a thread and return as {@link LuaThread}
	 * @param defval {@link LuaThread} to return if {@code this} is nil or none
	 * @return {@code this} cast to {@link LuaTable} if a thread,
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} if some other type
	 * @throws LuaError if was not a thread or nil or none.
	 * @see #checkthread()
	 * @see #isthread()
	 * @see #TTHREAD
	 */
	public LuaThread   optthread(LuaThread defval)         { argerror("thread");    return null;  }

	/** Check that optional argument is a userdata and return the Object instance
	 * @param defval Object to return if {@code this} is nil or none
	 * @return Object instance of the userdata if a {@link LuaUserdata},
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} if some other type
	 * @throws LuaError if was not a userdata or nil or none.
	 * @see #checkuserdata()
	 * @see #isuserdata()
	 * @see #optuserdata(Class, Object)
	 * @see #TUSERDATA
	 */
	public Object      optuserdata(Object defval)          { argerror("object");    return null;  }

	/** Check that optional argument is a userdata whose instance is of a type
	 * and return the Object instance
	 * @param c Class to test userdata instance against
	 * @param defval Object to return if {@code this} is nil or none
	 * @return Object instance of the userdata if a {@link LuaUserdata} and instance is assignable to {@code c},
	 * {@code defval} if nil or none,
	 * throws {@link LuaError} if some other type
	 * @throws LuaError if was not a userdata whose instance is assignable to {@code c} or nil or none.
	 * @see #checkuserdata(Class)
	 * @see #isuserdata(Class)
	 * @see #optuserdata(Object)
	 * @see #TUSERDATA
	 */
	public Object      optuserdata(Class c, Object defval) { argerror(c.getName()); return null;  }

	/** Perform argument check that this is not nil or none.
	 * @param defval {@link LuaValue} to return if {@code this} is nil or none
	 * @return {@code this} if not nil or none, else {@code defval}
	 * @see #NIL
	 * @see #NONE
	 * @see #isnil()
	 * @see Varargs#isnoneornil(int)
	 * @see #TNIL
	 * @see #TNONE
	 */
	public LuaValue    optvalue(LuaValue defval)           { return this; }

	
	/** Check that the value is a {@link LuaBoolean},
	 * or throw {@link LuaError} if not
	 * @return boolean value for {@code this} if it is a {@link LuaBoolean}
	 * @throws LuaError if not a {@link LuaBoolean}
	 * @see #optboolean(boolean)
	 * @see #TBOOLEAN
	 */
	public boolean     checkboolean()          { argerror("boolean");   return false; }
	
	/** Check that the value is a {@link LuaClosure} ,
	 * or throw {@link LuaError} if not
	 * <p>
	 * {@link LuaClosure} is a subclass of {@link LuaFunction} that interprets lua bytecode.
	 * @return {@code this} cast as {@link LuaClosure}
	 * @throws LuaError if not a {@link LuaClosure}
	 * @see #checkfunction()
	 * @see #optclosure(LuaClosure)
	 * @see #isclosure()
	 * @see #TFUNCTION
	 */
	public LuaClosure  checkclosure()          { argerror("closure");   return null;  }
	
	/** Check that the value is numeric and return the value as a double,
	 * or throw {@link LuaError} if not numeric
	 * <p>
	 * Values that are {@link LuaNumber} and values that are {@link LuaString}
	 * that can be converted to a number will be converted to double.
	 * @return value cast to a double if numeric
	 * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number
	 * @see #checkint()
	 * @see #checkinteger()
	 * @see #checklong()
	 * @see #optdouble(double)
	 * @see #TNUMBER
	 */
	public double      checkdouble()           { argerror("number");    return 0; }
	
	/** Check that the value is a function , or throw {@link LuaError} if not
	 * <p>
	 * A {@link LuaFunction} may either be a Java function that implements
	 * functionality directly in Java,  or a {@link LuaClosure}
	 * which is a {@link LuaFunction} that executes lua bytecode.
	 * @return {@code this} if it is a lua function or closure
	 * @throws LuaError if not a function
	 * @see #checkclosure()
	 */
	public LuaFunction    checkfunction()         { argerror("function");  return null; }


	/** Check that the value is a Globals instance, or throw {@link LuaError} if not
	 * <p>
	 * {@link Globals} are a special {@link LuaTable} that establish the default global environment.
	 * @return {@code this} if if an instance fof {@link Globals}
	 * @throws LuaError if not a {@link Globals} instance.
	 */
	public Globals checkglobals() { argerror("globals");  return null; }

	/** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric
	 * <p>
	 * Values that are {@link LuaNumber} will be cast to int and may lose precision.
	 * Values that are {@link LuaString} that can be converted to a number will be converted,
	 * then cast to int, so may also lose precision.
	 * @return value cast to a int if numeric
	 * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number
	 * @see #checkinteger()
	 * @see #checklong()
	 * @see #checkdouble()
	 * @see #optint(int)
	 * @see #TNUMBER
	 */
	public int         checkint()              { argerror("int");       return 0; }

	/** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric
	 * <p>
	 * Values that are {@link LuaNumber} will be cast to int and may lose precision.
	 * Values that are {@link LuaString} that can be converted to a number will be converted,
	 * then cast to int, so may also lose precision.
	 * @return value cast to a int and wrapped in {@link LuaInteger} if numeric
	 * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number
	 * @see #checkint()
	 * @see #checklong()
	 * @see #checkdouble()
	 * @see #optinteger(LuaInteger)
	 * @see #TNUMBER
	 */
	public LuaInteger  checkinteger()          { argerror("integer");   return null; }
	
	/** Check that the value is numeric, and convert and cast value to long, or throw {@link LuaError} if not numeric
	 * <p>
	 * Values that are {@link LuaNumber} will be cast to long and may lose precision.
	 * Values that are {@link LuaString} that can be converted to a number will be converted,
	 * then cast to long, so may also lose precision.
	 * @return value cast to a long if numeric
	 * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number
	 * @see #checkint()
	 * @see #checkinteger()
	 * @see #checkdouble()
	 * @see #optlong(long)
	 * @see #TNUMBER
	 */
	public long        checklong()             { argerror("long");      return 0; }
	
	/** Check that the value is numeric, and return as a LuaNumber if so, or throw {@link LuaError}
	 * <p>
	 * Values that are {@link LuaString} that can be converted to a number will be converted and returned.
	 * @return value as a {@link LuaNumber} if numeric
	 * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number
	 * @see #checkint()
	 * @see #checkinteger()
	 * @see #checkdouble()
	 * @see #checklong()
	 * @see #optnumber(LuaNumber)
	 * @see #TNUMBER
	 */
	public LuaNumber   checknumber()           { argerror("number");    return null; }
	
	/** Check that the value is numeric, and return as a LuaNumber if so, or throw {@link LuaError}
	 * <p>
	 * Values that are {@link LuaString} that can be converted to a number will be converted and returned.
	 * @param msg String message to supply if conversion fails
	 * @return value as a {@link LuaNumber} if numeric
	 * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number
	 * @see #checkint()
	 * @see #checkinteger()
	 * @see #checkdouble()
	 * @see #checklong()
	 * @see #optnumber(LuaNumber)
	 * @see #TNUMBER
	 */
	public LuaNumber   checknumber(String msg) { throw new LuaError(msg); }
	
	/** Convert this value to a Java String.
	 * <p>
	 * The string representations here will roughly match what is produced by the
	 * C lua distribution, however hash codes have no relationship,
	 * and there may be differences in number formatting.
	 * @return String representation of the value
	 * @see #checkstring()
	 * @see #optjstring(String)
	 * @see #tojstring()
	 * @see #isstring
	 * @see #TSTRING
	 */
	public String      checkjstring()          { argerror("string");    return null; }
	
	/** Check that this is a lua string, or throw {@link LuaError} if it is not.
	 * <p>
	 * In lua all numbers are strings, so this will succeed for
	 * anything that derives from {@link LuaString} or {@link LuaNumber}.
	 * Numbers will be converted to {@link LuaString}.
	 * 
	 * @return {@link LuaString} representation of the value if it is a {@link LuaString} or {@link LuaNumber}
	 * @throws LuaError if {@code this} is not a {@link LuaTable}
	 * @see #checkjstring()
	 * @see #optstring(LuaString)
	 * @see #tostring()
	 * @see #isstring()
	 * @see #TSTRING
	 */
	public LuaString   checkstring()           { argerror("string");    return null; }
	
	/** Check that this is a {@link LuaTable}, or throw {@link LuaError} if it is not
	 * @return {@code this} if it is a {@link LuaTable}
	 * @throws LuaError if {@code this} is not a {@link LuaTable}
	 * @see #istable()
	 * @see #opttable(LuaTable)
	 * @see #TTABLE
	 */
	public LuaTable    checktable()            { argerror("table");     return null; }
	
	/** Check that this is a {@link LuaThread}, or throw {@link LuaError} if it is not
	 * @return {@code this} if it is a {@link LuaThread}
	 * @throws LuaError if {@code this} is not a {@link LuaThread}
	 * @see #isthread()
	 * @see #optthread(LuaThread)
	 * @see #TTHREAD
	 */
	public LuaThread   checkthread()           { argerror("thread");    return null; }
	
	/** Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it is not
	 * @return {@code this} if it is a {@link LuaUserdata}
	 * @throws LuaError if {@code this} is not a {@link LuaUserdata}
	 * @see #isuserdata()
	 * @see #optuserdata(Object)
	 * @see #checkuserdata(Class)
	 * @see #TUSERDATA
	 */
	public Object      checkuserdata()         { argerror("userdata");  return null; }
	
	/** Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it is not
	 * @return {@code this} if it is a {@link LuaUserdata}
	 * @throws LuaError if {@code this} is not a {@link LuaUserdata}
	 * @see #isuserdata(Class)
	 * @see #optuserdata(Class, Object)
	 * @see #checkuserdata()
	 * @see #TUSERDATA
	 */
	public Object      checkuserdata(Class c)  { argerror("userdata");  return null; }
	
	/** Check that this is not the value {@link #NIL}, or throw {@link LuaError} if it is
	 * @return {@code this} if it is not {@link #NIL}
	 * @throws LuaError if {@code this} is {@link #NIL}
	 * @see #optvalue(LuaValue)
	 */
	public LuaValue    checknotnil()           { return this; }
	
	/** Return true if this is a valid key in a table index operation.
	 * @return true if valid as a table key, otherwise false
	 * @see #isnil()
	 * @see #isinttype()
	 */
	public boolean isvalidkey()         { return true; }
	
	/**
	 * Throw a {@link LuaError} with a particular message
	 * @param message String providing message details
	 * @throws LuaError in all cases
	 */
	public static LuaValue error(String message) { throw new LuaError(message); }

	/**
	 * Assert a condition is true, or throw a {@link LuaError} if not
	 * Returns no value when b is true, throws {@link #error(String)} with {@code msg} as argument
	 * and does not return if b is false.
	 * @param b condition to test
	 * @param msg String message to produce on failure
	 * @throws LuaError if b is not true
	 */
	public static void assert_(boolean b,String msg) { if(!b) throw new LuaError(msg); }
	
	/**
	 * Throw a {@link LuaError} indicating an invalid argument was supplied to a function
	 * @param expected String naming the type that was expected
	 * @throws LuaError in all cases
	 */
	protected LuaValue argerror(String expected) { throw new LuaError("bad argument: "+expected+" expected, got "+typename()); }
	
	/**
	 * Throw a {@link LuaError} indicating an invalid argument was supplied to a function
	 * @param iarg index of the argument that was invalid, first index is 1
	 * @param msg String providing information about the invalid argument
	 * @throws LuaError in all cases
	 */
	public static LuaValue argerror(int iarg,String msg) { throw new LuaError("bad argument #"+iarg+": "+msg); }
	
	/**
	 * Throw a {@link LuaError} indicating an invalid type was supplied to a function
	 * @param expected String naming the type that was expected
	 * @throws LuaError in all cases
	 */
	protected LuaValue typerror(String expected) { throw new LuaError(expected+" expected, got "+typename()); }
	
	/**
	 * Throw a {@link LuaError} indicating an operation is not implemented
	 * @throws LuaError in all cases
	 */
	protected LuaValue unimplemented(String fun) { throw new LuaError("'"+fun+"' not implemented for "+typename()); }
	
	/**
	 * Throw a {@link LuaError} indicating an illegal operation occurred,
	 * typically involved in managing weak references
	 * @throws LuaError in all cases
	 */
	protected LuaValue illegal(String op,String typename) { throw new LuaError("illegal operation '"+op+"' for "+typename); }
	
	/**
	 * Throw a {@link LuaError} based on the len operator,
	 * typically due to an invalid operand type
	 * @throws LuaError in all cases
	 */
	protected LuaValue lenerror() { throw new LuaError("attempt to get length of "+typename()); }
	
	/**
	 * Throw a {@link LuaError} based on an arithmetic error such as add, or pow,
	 * typically due to an invalid operand type
	 * @throws LuaError in all cases
	 */
	protected LuaValue aritherror() { throw new LuaError("attempt to perform arithmetic on "+typename()); }
	
	/**
	 * Throw a {@link LuaError} based on an arithmetic error such as add, or pow,
	 * typically due to an invalid operand type
	 * @param fun String description of the function that was attempted
	 * @throws LuaError in all cases
	 */
	protected LuaValue aritherror(String fun) { throw new LuaError("attempt to perform arithmetic '"+fun+"' on "+typename()); }
	
	/**
	 * Throw a {@link LuaError} based on a comparison error such as greater-than or less-than,
	 * typically due to an invalid operand type
	 * @param rhs String description of what was on the right-hand-side of the comparison that resulted in the error.
	 * @throws LuaError in all cases
	 */
	protected LuaValue compareerror(String rhs) { throw new LuaError("attempt to compare "+typename()+" with "+rhs); }
	
	/**
	 * Throw a {@link LuaError} based on a comparison error such as greater-than or less-than,
	 * typically due to an invalid operand type
	 * @param rhs Right-hand-side of the comparison that resulted in the error.
	 * @throws LuaError in all cases
	 */
	protected LuaValue compareerror(LuaValue rhs) { throw new LuaError("attempt to compare "+typename()+" with "+rhs.typename()); }
	
	/** Get a value in a table including metatag processing using {@link #INDEX}.
	 * @param key the key to look up, must not be {@link #NIL} or null
	 * @return {@link LuaValue} for that key, or {@link #NIL} if not found and no metatag
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #INDEX} metatag,
	 * or key is {@link #NIL}
	 * @see #get(int)
	 * @see #get(String)
	 * @see #rawget(LuaValue)
	 */
	public LuaValue get( LuaValue key ) { return gettable(this,key); }
	
	/** Get a value in a table including metatag processing using {@link #INDEX}.
	 * @param key the key to look up
	 * @return {@link LuaValue} for that key, or {@link #NIL} if not found
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #INDEX} metatag
	 * @see #get(LuaValue)
	 * @see #rawget(int)
	 */
	public LuaValue get( int key ) { return get(LuaInteger.valueOf(key)); }

	/** Get a value in a table including metatag processing using {@link #INDEX}.
	 * @param key the key to look up, must not be null
	 * @return {@link LuaValue} for that key, or {@link #NIL} if not found
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #INDEX} metatag
	 * @see #get(LuaValue)
	 * @see #rawget(String)
	 */
	public LuaValue get( String key ) { return get(valueOf(key)); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use, must not be {@link #NIL} or null
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table,
	 * or key is {@link #NIL},
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( LuaValue key, LuaValue value ) { settable(this, key, value); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( int key, LuaValue value ) { set(LuaInteger.valueOf(key), value ); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use
	 * @param value the value to use, must not be null
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( int key, String value ) { set(key, valueOf(value) ); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use, must not be {@link #NIL} or null
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( String key, LuaValue value ) { set(valueOf(key), value ); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use, must not be null
	 * @param value the value to use
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( String key, double value ) { set(valueOf(key), valueOf(value) ); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use, must not be null
	 * @param value the value to use
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( String key, int value ) { set(valueOf(key), valueOf(value) ); }
	
	/** Set a value in a table without metatag processing using {@link #NEWINDEX}.
	 * @param key the key to use, must not be null
	 * @param value the value to use, must not be null
	 * @throws LuaError if {@code this} is not a table,
	 * or there is no {@link #NEWINDEX} metatag
	 */
	public void set( String key, String value ) { set(valueOf(key), valueOf(value) ); }

	/** Get a value in a table without metatag processing.
	 * @param key the key to look up, must not be {@link #NIL} or null
	 * @return {@link LuaValue} for that key, or {@link #NIL} if not found
	 * @throws LuaError if {@code this} is not a table, or key is {@link #NIL}
	 */
	public LuaValue rawget( LuaValue key ) { return unimplemented("rawget"); }

	/** Get a value in a table without metatag processing.
	 * @param key the key to look up
	 * @return {@link LuaValue} for that key, or {@link #NIL} if not found
	 * @throws LuaError if {@code this} is not a table
	 */
	public LuaValue rawget( int key ) { return rawget(valueOf(key)); }

	/** Get a value in a table without metatag processing.
	 * @param key the key to look up, must not be null
	 * @return {@link LuaValue} for that key, or {@link #NIL} if not found
	 * @throws LuaError if {@code this} is not a table
	 */
	public LuaValue rawget( String key ) { return rawget(valueOf(key)); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use, must not be {@link #NIL} or null
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table, or key is {@link #NIL}
	 */
	public void rawset( LuaValue key, LuaValue value ) { unimplemented("rawset"); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table
	 */
	public void rawset( int key, LuaValue value ) { rawset(valueOf(key),value); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table
	 */
	public void rawset( int key, String value ) { rawset(key,valueOf(value)); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use, must not be null
	 * @param value the value to use, can be {@link #NIL}, must not be null
	 * @throws LuaError if {@code this} is not a table
	 */
	public void rawset( String key, LuaValue value ) { rawset(valueOf(key),value); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use, must not be null
	 * @param value the value to use
	 * @throws LuaError if {@code this} is not a table
	 */
	public void rawset( String key, double value ) { rawset(valueOf(key),valueOf(value)); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use, must not be null
	 * @param value the value to use
	 * @throws LuaError if {@code this} is not a table
	 */
	public void rawset( String key, int value ) { rawset(valueOf(key),valueOf(value)); }
	
	/** Set a value in a table without metatag processing.
	 * @param key the key to use, must not be null
	 * @param value the value to use, must not be null
	 * @throws LuaError if {@code this} is not a table
	 */
	public void rawset( String key, String value ) { rawset(valueOf(key),valueOf(value)); }

	/** Set list values in a table without invoking metatag processing
	 * <p>
	 * Primarily used internally in response to a SETLIST bytecode.
	 * @param key0 the first key to set in the table
	 * @param values the list of values to set
	 * @throws LuaError if this is not a table.
	 */
	public void rawsetlist( int key0, Varargs values ) { for ( int i=0, n=values.narg(); i<n; i++ ) rawset(key0+i,values.arg(i+1)); }
	
	/** Preallocate the array part of a table to be a certain size,
	 * <p>
	 * Primarily used internally in response to a SETLIST bytecode.
	 * @param i the number of array slots to preallocate in the table.
	 * @throws LuaError if this is not a table.
	 */
	public void presize( int i) { typerror("table"); }
	
	/** Find the next key,value pair if {@code this} is a table,
	 * return {@link #NIL} if there are no more, or throw a {@link LuaError} if not a table.
	 * <p>
	 * To iterate over all key-value pairs in a table you can use
	 * <pre> {@code
	 * LuaValue k = LuaValue.NIL;
	 * while ( true ) {
	 *    Varargs n = table.next(k);
	 *    if ( (k = n.arg1()).isnil() )
	 *       break;
	 *    LuaValue v = n.arg(2)
	 *    process( k, v )
	 * }}</pre>
	 * @param index {@link LuaInteger} value identifying a key to start from,
	 * or {@link #NIL} to start at the beginning
	 * @return {@link Varargs} containing {key,value} for the next entry,
	 * or {@link #NIL} if there are no more.
	 * @throws LuaError if {@code this} is not a table, or the supplied key is invalid.
	 * @see LuaTable
	 * @see #inext(LuaValue)
	 * @see #valueOf(int)
	 * @see Varargs#arg1()
	 * @see Varargs#arg(int)
	 * @see #isnil()
	 */
	public Varargs next(LuaValue index) { return typerror("table"); }
	
	/** Find the next integer-key,value pair if {@code this} is a table,
	 * return {@link #NIL} if there are no more, or throw a {@link LuaError} if not a table.
	 * <p>
	 * To iterate over integer keys in a table you can use
	 * <pre> {@code
	 *   LuaValue k = LuaValue.NIL;
	 *   while ( true ) {
	 *      Varargs n = table.inext(k);
	 *      if ( (k = n.arg1()).isnil() )
	 *         break;
	 *      LuaValue v = n.arg(2)
	 *      process( k, v )
	 *   }
	 * } </pre>
	 * @param index {@link LuaInteger} value identifying a key to start from,
	 * or {@link #NIL} to start at the beginning
	 * @return {@link Varargs} containing {@code (key,value)} for the next entry,
	 * or {@link #NONE} if there are no more.
	 * @throws LuaError if {@code this} is not a table, or the supplied key is invalid.
	 * @see LuaTable
	 * @see #next(LuaValue)
	 * @see #valueOf(int)
	 * @see Varargs#arg1()
	 * @see Varargs#arg(int)
	 * @see #isnil()
	 */
	public Varargs inext(LuaValue index) { return typerror("table"); }
	
	/**
	 * Load a library instance by calling it with and empty string as the modname,
	 * and this Globals as the environment. This is normally used to iniitalize the
	 * library instance and which may install itself into these globals.
	 * @param library The callable {@link LuaValue} to load into {@code this}
	 * @return {@link LuaValue} returned by the initialization call.
	 */
	public LuaValue load(LuaValue library) { return library.call(EMPTYSTRING, this); }

	// varargs references
	public LuaValue arg(int index) { return index==1? this: NIL; }
	public int narg() { return 1; };
	public LuaValue arg1() { return this; }
	
	/**
	 * Get the metatable for this {@link LuaValue}
	 * <p>
	 * For {@link LuaTable} and {@link LuaUserdata} instances,
	 * the metatable returned is this instance metatable.
	 * For all other types, the class metatable value will be returned.
	 * @return metatable, or null if it there is none
	 * @see LuaBoolean#s_metatable
	 * @see LuaNumber#s_metatable
	 * @see LuaNil#s_metatable
	 * @see LuaFunction#s_metatable
	 * @see LuaThread#s_metatable
	 */
	public LuaValue getmetatable() { return null; }
	
	/**
	 * Set the metatable for this {@link LuaValue}
	 * <p>
	 * For {@link LuaTable} and {@link LuaUserdata} instances, the metatable is per instance.
	 * For all other types, there is one metatable per type that can be set directly from java
	 * @param metatable {@link LuaValue} instance to serve as the metatable, or null to reset it.
	 * @return {@code this} to allow chaining of Java function calls
	 * @see LuaBoolean#s_metatable
	 * @see LuaNumber#s_metatable
	 * @see LuaNil#s_metatable
	 * @see LuaFunction#s_metatable
	 * @see LuaThread#s_metatable
	 */
	public LuaValue setmetatable(LuaValue metatable) { return argerror("table"); }
			
	/** Call {@code this} with 0 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a method call, use {@link #method(LuaValue)} instead.
	 * 
	 * @return First return value {@code (this())}, or {@link #NIL} if there were none.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call(LuaValue)
	 * @see #call(LuaValue,LuaValue)
	 * @see #call(LuaValue, LuaValue, LuaValue)
	 * @see #invoke()
	 * @see #method(String)
	 * @see #method(LuaValue)
	 */
	public LuaValue call() { return callmt().call(this); }

	/** Call {@code this} with 1 argument, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a method call, use {@link #method(LuaValue)} instead.
	 * 
	 * @param arg First argument to supply to the called function
	 * @return First return value {@code (this(arg))}, or {@link #NIL} if there were none.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #call(LuaValue,LuaValue)
	 * @see #call(LuaValue, LuaValue, LuaValue)
	 * @see #invoke(Varargs)
	 * @see #method(String,LuaValue)
	 * @see #method(LuaValue,LuaValue)
	 */
	public LuaValue call(LuaValue arg) { return callmt().call(this,arg); }

	/** Convenience function which calls a luavalue with a single, string argument.
	 * @param arg String argument to the function.  This will be converted to a LuaString.
	 * @return return value of the invocation.
	 * @see #call(LuaValue)
	 */
	public LuaValue call(String arg) { return call(valueOf(arg)); }
	
	/** Call {@code this} with 2 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a method call, use {@link #method(LuaValue)} instead.
	 * 
	 * @param arg1 First argument to supply to the called function
	 * @param arg2 Second argument to supply to the called function
	 * @return First return value {@code (this(arg1,arg2))}, or {@link #NIL} if there were none.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #call(LuaValue)
	 * @see #call(LuaValue, LuaValue, LuaValue)
	 * @see #invoke(LuaValue, Varargs)
	 * @see #method(String,LuaValue,LuaValue)
	 * @see #method(LuaValue,LuaValue,LuaValue)
	 */
	public LuaValue call(LuaValue arg1, LuaValue arg2) { return callmt().call(this,arg1,arg2); }

	/** Call {@code this} with 3 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a method call, use {@link #method(LuaValue)} instead.
	 * 
	 * @param arg1 First argument to supply to the called function
	 * @param arg2 Second argument to supply to the called function
	 * @param arg3 Second argument to supply to the called function
	 * @return First return value {@code (this(arg1,arg2,arg3))}, or {@link #NIL} if there were none.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #call(LuaValue)
	 * @see #call(LuaValue, LuaValue)
	 * @see #invoke(LuaValue, LuaValue, Varargs)
	 * @see #invokemethod(String,Varargs)
	 * @see #invokemethod(LuaValue,Varargs)
	 */
	public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { return callmt().invoke(new LuaValue[]{this,arg1,arg2,arg3}).arg1(); }
	
	/** Call named method on {@code this} with 0 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument.
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a plain call, use {@link #call()} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @return All values returned from {@code this:name()} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke()
	 * @see #method(LuaValue)
	 * @see #method(String,LuaValue)
	 * @see #method(String,LuaValue,LuaValue)
	 */
	public LuaValue method(String name) { return this.get(name).call(this); }

	/** Call named method on {@code this} with 0 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a plain call, use {@link #call()} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @return All values returned from {@code this:name()} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke()
	 * @see #method(String)
	 * @see #method(LuaValue,LuaValue)
	 * @see #method(LuaValue,LuaValue,LuaValue)
	 */
	public LuaValue method(LuaValue name) { return this.get(name).call(this); }
	
	/** Call named method on {@code this} with 1 argument, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a plain call, use {@link #call(LuaValue)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param arg Argument to supply to the method
	 * @return All values returned from {@code this:name(arg)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call(LuaValue)
	 * @see #invoke(Varargs)
	 * @see #method(String)
	 * @see #method(LuaValue)
	 * @see #method(String,LuaValue,LuaValue)
	 */
	public LuaValue method(String name, LuaValue arg) { return this.get(name).call(this,arg); }
	
	/** Call named method on {@code this} with 1 argument, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a plain call, use {@link #call(LuaValue)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param arg Argument to supply to the method
	 * @return All values returned from {@code this:name(arg)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call(LuaValue)
	 * @see #invoke(Varargs)
	 * @see #method(String,LuaValue)
	 * @see #method(LuaValue)
	 * @see #method(LuaValue,LuaValue,LuaValue)
	 */
	public LuaValue method(LuaValue name, LuaValue arg) { return this.get(name).call(this,arg); }

	/** Call named method on {@code this} with 2 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a plain call, use {@link #call(LuaValue,LuaValue)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param arg1 First argument to supply to the method
	 * @param arg2 Second argument to supply to the method
	 * @return All values returned from {@code this:name(arg1,arg2)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call(LuaValue,LuaValue)
	 * @see #invoke(LuaValue,Varargs)
	 * @see #method(String,LuaValue)
	 * @see #method(LuaValue,LuaValue,LuaValue)
	 */
	public LuaValue method(String name, LuaValue arg1, LuaValue arg2) { return this.get(name).call(this,arg1,arg2); }

	/** Call named method on {@code this} with 2 arguments, including metatag processing,
	 * and return only the first return value.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return only its first return value, dropping any others.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * If the return value is a {@link Varargs}, only the 1st value will be returned.
	 * To get multiple values, use {@link #invoke()} instead.
	 * <p>
	 * To call {@code this} as a plain call, use {@link #call(LuaValue,LuaValue)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param arg1 First argument to supply to the method
	 * @param arg2 Second argument to supply to the method
	 * @return All values returned from {@code this:name(arg1,arg2)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call(LuaValue,LuaValue)
	 * @see #invoke(LuaValue,Varargs)
	 * @see #method(LuaValue,LuaValue)
	 * @see #method(String,LuaValue,LuaValue)
	 */
	public LuaValue method(LuaValue name, LuaValue arg1, LuaValue arg2) { return this.get(name).call(this,arg1,arg2); }
	
	/** Call {@code this} with 0 arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it, and return all values.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a method call, use {@link #invokemethod(LuaValue)} instead.
	 * 
	 * @return All return values as a {@link Varargs} instance.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke(Varargs)
	 * @see #invokemethod(String)
	 * @see #invokemethod(LuaValue)
	 */
	public Varargs invoke() { return invoke(NONE); }

	/** Call {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it, and return all values.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a method call, use {@link #invokemethod(LuaValue)} instead.
	 * 
	 * @param args Varargs containing the arguments to supply to the called function
	 * @return All return values as a {@link Varargs} instance.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #varargsOf(LuaValue[])
	 * @see #call(LuaValue)
	 * @see #invoke()
	 * @see #invoke(LuaValue,Varargs)
	 * @see #invokemethod(String,Varargs)
	 * @see #invokemethod(LuaValue,Varargs)
	 */
	public Varargs invoke(Varargs args) { return callmt().invoke(this,args); }

	/** Call {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it, and return all values.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead.
	 * 
	 * @param arg The first argument to supply to the called function
	 * @param varargs Varargs containing the remaining arguments to supply to the called function
	 * @return All return values as a {@link Varargs} instance.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #varargsOf(LuaValue[])
	 * @see #call(LuaValue,LuaValue)
	 * @see #invoke(LuaValue,Varargs)
	 * @see #invokemethod(String,Varargs)
	 * @see #invokemethod(LuaValue,Varargs)
	 */
	public Varargs invoke(LuaValue arg,Varargs varargs) { return invoke(varargsOf(arg,varargs)); }

	/** Call {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it, and return all values.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead.
	 * 
	 * @param arg1 The first argument to supply to the called function
	 * @param arg2 The second argument to supply to the called function
	 * @param varargs Varargs containing the remaining arguments to supply to the called function
	 * @return All return values as a {@link Varargs} instance.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #varargsOf(LuaValue[])
	 * @see #call(LuaValue,LuaValue,LuaValue)
	 * @see #invoke(LuaValue,LuaValue,Varargs)
	 * @see #invokemethod(String,Varargs)
	 * @see #invokemethod(LuaValue,Varargs)
	 */
	public Varargs invoke(LuaValue arg1,LuaValue arg2,Varargs varargs) { return invoke(varargsOf(arg1,arg2,varargs)); }

	/** Call {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it, and return all values.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead.
	 * 
	 * @param args Array of arguments to supply to the called function
	 * @return All return values as a {@link Varargs} instance.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #varargsOf(LuaValue[])
	 * @see #call(LuaValue,LuaValue,LuaValue)
	 * @see #invoke(LuaValue,LuaValue,Varargs)
	 * @see #invokemethod(String,LuaValue[])
	 * @see #invokemethod(LuaValue,LuaValue[])
	 */
	public Varargs invoke(LuaValue[] args) { return invoke(varargsOf(args)); }

	/** Call {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * If {@code this} is a {@link LuaFunction}, call it, and return all values.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead.
	 * 
	 * @param args Array of arguments to supply to the called function
	 * @param varargs Varargs containing additional arguments to supply to the called function
	 * @return All return values as a {@link Varargs} instance.
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #varargsOf(LuaValue[])
	 * @see #call(LuaValue,LuaValue,LuaValue)
	 * @see #invoke(LuaValue,LuaValue,Varargs)
	 * @see #invokemethod(String,LuaValue[])
	 * @see #invokemethod(LuaValue,LuaValue[])
	 * @see #invokemethod(String,Varargs)
	 * @see #invokemethod(LuaValue,Varargs)
	 */
	public Varargs invoke(LuaValue[] args,Varargs varargs) { return invoke(varargsOf(args,varargs)); }
	
	/** Call named method on {@code this} with 0 arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return all return values as a {@link Varargs} instance.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a plain call, use {@link #invoke()} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @return All values returned from {@code this:name()} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke()
	 * @see #method(String)
	 * @see #invokemethod(LuaValue)
	 * @see #invokemethod(String, LuaValue[])
	 * @see #invokemethod(String, Varargs)
	 * @see #invokemethod(LuaValue, LuaValue[])
	 * @see #invokemethod(LuaValue, Varargs)
	 */
	public Varargs invokemethod(String name) { return get(name).invoke(this); }
	
	/** Call named method on {@code this} with 0 arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return all return values as a {@link Varargs} instance.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a plain call, use {@link #invoke()} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @return All values returned from {@code this:name()} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke()
	 * @see #method(LuaValue)
	 * @see #invokemethod(String)
	 * @see #invokemethod(String, LuaValue[])
	 * @see #invokemethod(String, Varargs)
	 * @see #invokemethod(LuaValue, LuaValue[])
	 * @see #invokemethod(LuaValue, Varargs)
	 */
	public Varargs invokemethod(LuaValue name) { return get(name).invoke(this); }
	
	/** Call named method on {@code this} with 1 argument, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return all return values as a {@link Varargs} instance.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param args {@link Varargs} containing arguments to supply to the called function after {@code this}
	 * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke(Varargs)
	 * @see #method(String)
	 * @see #invokemethod(String)
	 * @see #invokemethod(LuaValue)
	 * @see #invokemethod(String, LuaValue[])
	 * @see #invokemethod(LuaValue, LuaValue[])
	 * @see #invokemethod(LuaValue, Varargs)
	 */
	public Varargs invokemethod(String name, Varargs args) { return get(name).invoke(varargsOf(this,args)); }
	
	/** Call named method on {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return all return values as a {@link Varargs} instance.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param args {@link Varargs} containing arguments to supply to the called function after {@code this}
	 * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke(Varargs)
	 * @see #method(String)
	 * @see #invokemethod(String)
	 * @see #invokemethod(LuaValue)
	 * @see #invokemethod(String, LuaValue[])
	 * @see #invokemethod(String, Varargs)
	 * @see #invokemethod(LuaValue, LuaValue[])
	 */
	public Varargs invokemethod(LuaValue name, Varargs args) { return get(name).invoke(varargsOf(this,args)); }
	
	/** Call named method on {@code this} with 1 argument, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return all return values as a {@link Varargs} instance.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param args Array of {@link LuaValue} containing arguments to supply to the called function after {@code this}
	 * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke(Varargs)
	 * @see #method(String)
	 * @see #invokemethod(String)
	 * @see #invokemethod(LuaValue)
	 * @see #invokemethod(String, Varargs)
	 * @see #invokemethod(LuaValue, LuaValue[])
	 * @see #invokemethod(LuaValue, Varargs)
	 * @see LuaValue#varargsOf(LuaValue[])
	 */
	public Varargs invokemethod(String name, LuaValue[] args) { return get(name).invoke(varargsOf(this,varargsOf(args))); }
	
	/** Call named method on {@code this} with variable arguments, including metatag processing,
	 * and retain all return values in a {@link Varargs}.
	 * <p>
	 * Look up {@code this[name]} and if it is a {@link LuaFunction},
	 * call it inserting {@code this} as an additional first argument,
	 * and return all return values as a {@link Varargs} instance.
	 * Otherwise, look for the {@link #CALL} metatag and call that.
	 * <p>
	 * To get a particular return value, us {@link Varargs#arg(int)}
	 * <p>
	 * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead.
	 * 
	 * @param name Name of the method to look up for invocation
	 * @param args Array of {@link LuaValue} containing arguments to supply to the called function after {@code this}
	 * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance
	 * @throws LuaError if not a function and {@link #CALL} is not defined,
	 * or the invoked function throws a {@link LuaError}
	 * or the invoked closure throw a lua {@code error}
	 * @see #call()
	 * @see #invoke(Varargs)
	 * @see #method(String)
	 * @see #invokemethod(String)
	 * @see #invokemethod(LuaValue)
	 * @see #invokemethod(String, LuaValue[])
	 * @see #invokemethod(String, Varargs)
	 * @see #invokemethod(LuaValue, Varargs)
	 * @see LuaValue#varargsOf(LuaValue[])
	 */
	public Varargs invokemethod(LuaValue name, LuaValue[] args) { return get(name).invoke(varargsOf(this,varargsOf(args))); }
	
	/**
	 * Get the metatag value for the {@link #CALL} metatag, if it exists.
	 * @return {@link LuaValue} value if metatag is defined
	 * @throws LuaError if {@link #CALL} metatag is not defined.
	 */
	protected LuaValue callmt() {
		return checkmetatag(CALL, "attempt to call ");
	}
	
	/** Unary not: return inverse boolean value {@code (~this)} as defined by lua not operator
	 * @return {@link #TRUE} if {@link #NIL} or {@link #FALSE}, otherwise {@link #FALSE}
	 */
	public LuaValue not()  { return FALSE;  }
	
	/** Unary minus: return negative value {@code (-this)} as defined by lua unary minus operator
	 * @return boolean inverse as {@link LuaBoolean} if boolean or nil,
	 * numeric inverse as {@link LuaNumber} if numeric,
	 * or metatag processing result if {@link #UNM} metatag is defined
	 * @throws LuaError if  {@code this} is not a table or string, and has no {@link #UNM} metatag
	 */
	public LuaValue neg()  { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this);  }

	/** Unary bitwise not: return bitwise inverse value {@code (~this)}.
	 * @return numeric inverse as {@link LuaNumber} if integer-coercible,
	 * or metatag processing result if {@link #BNOT} metatag is defined
	 * @throws LuaError if {@code this} cannot be represented as an integer
	 */
	public LuaValue bnot() { return checkmetatag(BNOT, "attempt to perform bitwise operation on ").call(this); }
	
	/** Length operator: return lua length of object {@code (#this)} including metatag processing as java int
	 * @return length as defined by the lua # operator
	 * or metatag processing result
	 * @throws LuaError if  {@code this} is not a table or string, and has no {@link #LEN} metatag
	 */
	public LuaValue len()  { return checkmetatag(LEN, "attempt to get length of ").call(this);  }

	/** Length operator: return lua length of object {@code (#this)} including metatag processing as java int
	 * @return length as defined by the lua # operator
	 * or metatag processing result converted to java int using {@link #toint()}
	 * @throws LuaError if  {@code this} is not a table or string, and has no {@link #LEN} metatag
	 */
	public int length()    { return len().toint(); }
	
	/** Get raw length of table or string without metatag processing.
	 * @return the length of the table or string.
	 * @throws LuaError if {@code this} is not a table or string.
	 */
	public int rawlen() { typerror("table or string"); return 0; }
	
	// object equality, used for key comparison
	public boolean equals(Object obj)         { return this == obj; }
	
	/** Equals: Perform equality comparison with another value
	 * including metatag processing using {@link #EQ}.
	 * @param val The value to compare with.
	 * @return  {@link #TRUE} if values are comparable and {@code (this == rhs)},
	 * {@link #FALSE} if comparable but not equal,
	 * {@link LuaValue} if metatag processing occurs.
	 * @see #eq_b(LuaValue)
	 * @see #raweq(LuaValue)
	 * @see #neq(LuaValue)
	 * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue)
	 * @see #EQ
	 */
	public LuaValue   eq( LuaValue val )      { return eq_b(val)? TRUE: FALSE; }
	
	/** Equals: Perform equality comparison with another value
	 * including metatag processing using {@link #EQ},
	 * and return java boolean
	 * @param val The value to compare with.
	 * @return  true if values are comparable and {@code (this == rhs)},
	 * false if comparable but not equal,
	 * result converted to java boolean if metatag processing occurs.
	 * @see #eq(LuaValue)
	 * @see #raweq(LuaValue)
	 * @see #neq_b(LuaValue)
	 * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue)
	 * @see #EQ
	 */
	public boolean  eq_b( LuaValue val )      { return this == val; }

	/** Notquals: Perform inequality comparison with another value
	 * including metatag processing using {@link #EQ}.
	 * @param val The value to compare with.
	 * @return  {@link #TRUE} if values are comparable and {@code (this != rhs)},
	 * {@link #FALSE} if comparable but equal,
	 * inverse of {@link LuaValue} converted to {@link LuaBoolean} if metatag processing occurs.
	 * @see #eq(LuaValue)
	 * @see #raweq(LuaValue)
	 * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue)
	 * @see #EQ
	 */
	public LuaValue  neq( LuaValue val )      { return  eq_b(val)? FALSE: TRUE;  }

	/** Notquals: Perform inequality comparison with another value
	 * including metatag processing using {@link #EQ}.
	 * @param val The value to compare with.
	 * @return  true if values are comparable and {@code (this != rhs)},
	 * false if comparable but equal,
	 * inverse of result converted to boolean if metatag processing occurs.
	 * @see #eq_b(LuaValue)
	 * @see #raweq(LuaValue)
	 * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue)
	 * @see #EQ
	 */
	public boolean neq_b( LuaValue val )      { return !eq_b(val); }

	/** Equals: Perform direct equality comparison with another value
	 * without metatag processing.
	 * @param val The value to compare with.
	 * @return  true if {@code (this == rhs)}, false otherwise
	 * @see #eq(LuaValue)
	 * @see #raweq(LuaUserdata)
	 * @see #raweq(LuaString)
	 * @see #raweq(double)
	 * @see #raweq(int)
	 * @see #EQ
	 */
	public boolean raweq( LuaValue val )      { return this == val; }
	
	/** Equals: Perform direct equality comparison with a {@link LuaUserdata} value
	 * without metatag processing.
	 * @param val The {@link LuaUserdata} to compare with.
	 * @return  true if {@code this} is userdata
	 * and their metatables are the same using ==
	 * and their instances are equal using {@link #equals(Object)},
	 * otherwise false
	 * @see #eq(LuaValue)
	 * @see #raweq(LuaValue)
	 */
	public boolean raweq( LuaUserdata val )   { return false; }

	/** Equals: Perform direct equality comparison with a {@link LuaString} value
	 * without metatag processing.
	 * @param val The {@link LuaString} to compare with.
	 * @return  true if {@code this} is a {@link LuaString}
	 * and their byte sequences match,
	 * otherwise false
	 */
	public boolean raweq( LuaString val )     { return false; }

	/** Equals: Perform direct equality comparison with a double value
	 * without metatag processing.
	 * @param val The double value to compare with.
	 * @return  true if {@code this} is a {@link LuaNumber}
	 * whose value equals val,
	 * otherwise false
	 */
	public boolean raweq( double val )        { return false; }

	/** Equals: Perform direct equality comparison with a int value
	 * without metatag processing.
	 * @param val The double value to compare with.
	 * @return  true if {@code this} is a {@link LuaNumber}
	 * whose value equals val,
	 * otherwise false
	 */
	public boolean raweq( int val )           { return false; }

	/** Equals: Perform direct equality comparison with a long value
	 * without metatag processing.
	 * @param val The long value to compare with.
	 * @return  true if {@code this} is a {@link LuaNumber}
	 * whose value equals val,
	 * otherwise false
	 */
	public boolean raweq( long val )          { return false; }

	/** Perform equality testing metatag processing
	 * @param lhs left-hand-side of equality expression
	 * @param lhsmt metatag value for left-hand-side
	 * @param rhs right-hand-side of equality expression
	 * @param rhsmt metatag value for right-hand-side
	 * @return true if metatag processing result is not {@link #NIL} or {@link #FALSE}
	 * @throws LuaError if metatag was not defined for either operand
	 * @see #equals(Object)
	 * @see #eq(LuaValue)
	 * @see #raweq(LuaValue)
	 * @see #EQ
	 */
	public static final boolean eqmtcall(LuaValue lhs, LuaValue lhsmt, LuaValue rhs, LuaValue rhsmt) {
		LuaValue h = lhsmt.rawget(EQ);
		return h.isnil() || h!=rhsmt.rawget(EQ)? false: h.call(lhs,rhs).toboolean();
	}
	
	/** Add: Perform numeric add operation with another value
	 * including metatag processing.
	 * <p>
	 * Each operand must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the add with
	 * @return  value of {@code (this + rhs)} if both are numeric,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either operand is not a number or string convertible to number,
	 * and neither has the {@link #ADD} metatag defined
	 * @see #arithmt(LuaValue, LuaValue)
	 */
	public LuaValue   add( LuaValue rhs )        { return arithmt(ADD,rhs); }
	
	/** Add: Perform numeric add operation with another value
	 * of double type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the add with
	 * @return  value of {@code (this + rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #add(LuaValue)
	 */
	public LuaValue   add(double rhs)         { return arithmtwith(ADD,rhs); }
	
	/** Add: Perform numeric add operation with another value
	 * of int type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the add with
	 * @return  value of {@code (this + rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #add(LuaValue)
	 */
	public LuaValue   add(int rhs)            { return add((double)rhs); }
	
	/** Subtract: Perform numeric subtract operation with another value
	 * of unknown type,
	 * including metatag processing.
	 * <p>
	 * Each operand must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the subtract with
	 * @return  value of {@code (this - rhs)} if both are numeric,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either operand is not a number or string convertible to number,
	 * and neither has the {@link #SUB} metatag defined
	 * @see #arithmt(LuaValue, LuaValue)
	 */
	public LuaValue   sub( LuaValue rhs )        { return arithmt(SUB,rhs); }
	
	/** Subtract: Perform numeric subtract operation with another value
	 * of double type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the subtract with
	 * @return  value of {@code (this - rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #sub(LuaValue)
	 */
	public LuaValue   sub( double rhs )        { return aritherror("sub"); }
	
	/** Subtract: Perform numeric subtract operation with another value
	 * of int type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the subtract with
	 * @return  value of {@code (this - rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #sub(LuaValue)
	 */
	public LuaValue   sub( int rhs )        { return aritherror("sub"); }
	
	/** Reverse-subtract: Perform numeric subtract operation from an int value
	 * with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param lhs The left-hand-side value from which to perform the subtraction
	 * @return  value of {@code (lhs - this)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #sub(LuaValue)
	 * @see #sub(double)
	 * @see #sub(int)
	 */
	public LuaValue   subFrom(double lhs)     { return arithmtwith(SUB,lhs); }
	
	/** Reverse-subtract: Perform numeric subtract operation from a double value
	 * without metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * <p>
	 * For metatag processing {@link #sub(LuaValue)} must be used
	 * 
	 * @param lhs The left-hand-side value from which to perform the subtraction
	 * @return  value of {@code (lhs - this)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #sub(LuaValue)
	 * @see #sub(double)
	 * @see #sub(int)
	 */
	public LuaValue   subFrom(int lhs)        { return subFrom((double)lhs); }
	
	/** Multiply: Perform numeric multiply operation with another value
	 * of unknown type,
	 * including metatag processing.
	 * <p>
	 * Each operand must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the multiply with
	 * @return  value of {@code (this * rhs)} if both are numeric,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either operand is not a number or string convertible to number,
	 * and neither has the {@link #MUL} metatag defined
	 * @see #arithmt(LuaValue, LuaValue)
	 */
	public LuaValue   mul( LuaValue rhs )        { return arithmt(MUL,rhs); }
	
	/** Multiply: Perform numeric multiply operation with another value
	 * of double type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the multiply with
	 * @return  value of {@code (this * rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #mul(LuaValue)
	 */
	public LuaValue   mul(double rhs)         { return arithmtwith(MUL,rhs); }
	
	/** Multiply: Perform numeric multiply operation with another value
	 * of int type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the multiply with
	 * @return  value of {@code (this * rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #mul(LuaValue)
	 */
	public LuaValue   mul(int rhs)            { return mul((double)rhs); }
	
	/** Raise to power: Raise this value to a power
	 * including metatag processing.
	 * <p>
	 * Each operand must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The power to raise this value to
	 * @return  value of {@code (this ^ rhs)} if both are numeric,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either operand is not a number or string convertible to number,
	 * and neither has the {@link #POW} metatag defined
	 * @see #arithmt(LuaValue, LuaValue)
	 */
	public LuaValue   pow( LuaValue rhs )        { return arithmt(POW,rhs); }
	
	/** Raise to power: Raise this value to a power
	 * of double type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The power to raise this value to
	 * @return  value of {@code (this ^ rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #pow(LuaValue)
	 */
	public LuaValue   pow( double rhs )        { return aritherror("pow"); }
	
	/** Raise to power: Raise this value to a power
	 * of int type with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The power to raise this value to
	 * @return  value of {@code (this ^ rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #pow(LuaValue)
	 */
	public LuaValue   pow( int rhs )        { return aritherror("pow"); }
	
	/** Reverse-raise to power: Raise another value of double type to this power
	 * with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param lhs The left-hand-side value which will be raised to this power
	 * @return  value of {@code (lhs ^ this)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #pow(LuaValue)
	 * @see #pow(double)
	 * @see #pow(int)
	 */
	public LuaValue   powWith(double lhs)     { return arithmtwith(POW,lhs); }
	
	/** Reverse-raise to power: Raise another value of double type to this power
	 * with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param lhs The left-hand-side value which will be raised to this power
	 * @return  value of {@code (lhs ^ this)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #pow(LuaValue)
	 * @see #pow(double)
	 * @see #pow(int)
	 */
	public LuaValue   powWith(int lhs)        { return powWith((double)lhs); }
	
	/** Divide: Perform numeric divide operation by another value
	 * of unknown type,
	 * including metatag processing.
	 * <p>
	 * Each operand must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the divulo with
	 * @return  value of {@code (this / rhs)} if both are numeric,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either operand is not a number or string convertible to number,
	 * and neither has the {@link #DIV} metatag defined
	 * @see #arithmt(LuaValue, LuaValue)
	 */
	public LuaValue   div( LuaValue rhs )        { return arithmt(DIV,rhs); }

	public LuaValue   idiv( LuaValue rhs )       { return arithmt(IDIV,rhs); }

	public LuaValue   band( LuaValue rhs )       { return arithmt(BAND,rhs); }

	public LuaValue   bor( LuaValue rhs )        { return arithmt(BOR,rhs); }

	public LuaValue   bxor( LuaValue rhs )       { return arithmt(BXOR,rhs); }

	public LuaValue   shl( LuaValue rhs )        { return arithmt(SHL,rhs); }

	public LuaValue   shr( LuaValue rhs )        { return arithmt(SHR,rhs); }
	
	/** Divide: Perform numeric divide operation by another value
	 * of double type without metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * <p>
	 * For metatag processing {@link #div(LuaValue)} must be used
	 * 
	 * @param rhs The right-hand-side value to perform the divulo with
	 * @return  value of {@code (this / rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #div(LuaValue)
	 */
	public LuaValue   div( double rhs )        { return aritherror("div"); }

	public LuaValue   idiv( double rhs )       { return aritherror("idiv"); }

	public LuaValue   band( double rhs )       { return aritherror("band"); }

	public LuaValue   bor( double rhs )        { return aritherror("bor"); }

	public LuaValue   bxor( double rhs )       { return aritherror("bxor"); }

	public LuaValue   shl( double rhs )        { return aritherror("shl"); }

	public LuaValue   shr( double rhs )        { return aritherror("shr"); }
	
	/** Divide: Perform numeric divide operation by another value
	 * of int type without metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * <p>
	 * For metatag processing {@link #div(LuaValue)} must be used
	 * 
	 * @param rhs The right-hand-side value to perform the divulo with
	 * @return  value of {@code (this / rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #div(LuaValue)
	 */
	public LuaValue   div( int rhs )        { return aritherror("div"); }

	public LuaValue   idiv( int rhs )       { return aritherror("idiv"); }

	public LuaValue   band( int rhs )       { return aritherror("band"); }

	public LuaValue   bor( int rhs )        { return aritherror("bor"); }

	public LuaValue   bxor( int rhs )       { return aritherror("bxor"); }

	public LuaValue   shl( int rhs )        { return aritherror("shl"); }

	public LuaValue   shr( int rhs )        { return aritherror("shr"); }
	
	/** Reverse-divide: Perform numeric divide operation into another value
	 * with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param lhs The left-hand-side value which will be divided by this
	 * @return  value of {@code (lhs / this)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #div(LuaValue)
	 * @see #div(double)
	 * @see #div(int)
	 */
	public LuaValue   divInto(double lhs)     { return arithmtwith(DIV,lhs); }

	public LuaValue   idivInto(double lhs)    { return arithmtwith(IDIV,lhs); }

	public LuaValue   bandInto(double lhs)    { return arithmtwith(BAND,lhs); }

	public LuaValue   borInto(double lhs)     { return arithmtwith(BOR,lhs); }

	public LuaValue   bxorInto(double lhs)    { return arithmtwith(BXOR,lhs); }

	public LuaValue   shlInto(double lhs)     { return arithmtwith(SHL,lhs); }

	public LuaValue   shrInto(double lhs)     { return arithmtwith(SHR,lhs); }
	
	/** Modulo: Perform numeric modulo operation with another value
	 * of unknown type,
	 * including metatag processing.
	 * <p>
	 * Each operand must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param rhs The right-hand-side value to perform the modulo with
	 * @return  value of {@code (this % rhs)} if both are numeric,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either operand is not a number or string convertible to number,
	 * and neither has the {@link #MOD} metatag defined
	 * @see #arithmt(LuaValue, LuaValue)
	 */
	public LuaValue   mod( LuaValue rhs )        { return arithmt(MOD,rhs); }
	
	/** Modulo: Perform numeric modulo operation with another value
	 * of double type without metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * <p>
	 * For metatag processing {@link #mod(LuaValue)} must be used
	 * 
	 * @param rhs The right-hand-side value to perform the modulo with
	 * @return  value of {@code (this % rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #mod(LuaValue)
	 */
	public LuaValue   mod( double rhs )        { return aritherror("mod"); }
	
	/** Modulo: Perform numeric modulo operation with another value
	 * of int type without metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * <p>
	 * For metatag processing {@link #mod(LuaValue)} must be used
	 * 
	 * @param rhs The right-hand-side value to perform the modulo with
	 * @return  value of {@code (this % rhs)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #mod(LuaValue)
	 */
	public LuaValue   mod( int rhs )        { return aritherror("mod"); }
	
	/** Reverse-modulo: Perform numeric modulo operation from another value
	 * with metatag processing
	 * <p>
	 * {@code this} must derive from {@link LuaNumber}
	 * or derive from {@link LuaString} and be convertible to a number
	 * 
	 * @param lhs The left-hand-side value which will be modulo'ed by this
	 * @return  value of {@code (lhs % this)} if this is numeric
	 * @throws LuaError if {@code this} is not a number or string convertible to number
	 * @see #mod(LuaValue)
	 * @see #mod(double)
	 * @see #mod(int)
	 */
	public LuaValue   modFrom(double lhs)     { return arithmtwith(MOD,lhs); }
	
	/** Perform metatag processing for arithmetic operations.
	 * <p>
	 * Finds the supplied metatag value for {@code this} or {@code op2} and invokes it,
	 * or throws {@link LuaError} if neither is defined.
	 * @param tag The metatag to look up
	 * @param op2 The other operand value to perform the operation with
	 * @return {@link LuaValue} resulting from metatag processing
	 * @throws LuaError if metatag was not defined for either operand
	 * @see #add(LuaValue)
	 * @see #sub(LuaValue)
	 * @see #mul(LuaValue)
	 * @see #pow(LuaValue)
	 * @see #div(LuaValue)
	 * @see #mod(LuaValue)
	 * @see #ADD
	 * @see #SUB
	 * @see #MUL
	 * @see #POW
	 * @see #DIV
	 * @see #MOD
	 */
	protected LuaValue arithmt(LuaValue tag, LuaValue op2) {
		LuaValue h = this.metatag(tag);
		if ( h.isnil() ) {
			h = op2.metatag(tag);
			if ( h.isnil() )
				error( "attempt to perform arithmetic "+tag+" on "+typename()+" and "+op2.typename() );
		}
		return h.call( this, op2 );
	}
	
	/** Perform metatag processing for arithmetic operations when the left-hand-side is a number.
	 * <p>
	 * Finds the supplied metatag value for {@code this} and invokes it,
	 * or throws {@link LuaError} if neither is defined.
	 * @param tag The metatag to look up
	 * @param op1 The value of the left-hand-side to perform the operation with
	 * @return {@link LuaValue} resulting from metatag processing
	 * @throws LuaError if metatag was not defined for either operand
	 * @see #add(LuaValue)
	 * @see #sub(LuaValue)
	 * @see #mul(LuaValue)
	 * @see #pow(LuaValue)
	 * @see #div(LuaValue)
	 * @see #mod(LuaValue)
	 * @see #ADD
	 * @see #SUB
	 * @see #MUL
	 * @see #POW
	 * @see #DIV
	 * @see #MOD
	 */
	protected LuaValue arithmtwith(LuaValue tag, double op1) {
		LuaValue h = metatag(tag);
		if ( h.isnil() )
			error( "attempt to perform arithmetic "+tag+" on number and "+typename() );
		return h.call( LuaValue.valueOf(op1), this );
	}
	
	/** Less than: Perform numeric or string comparison with another value
	 * of unknown type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq_b(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   lt( LuaValue rhs )         { return comparemt(LT,rhs); }

	/** Less than: Perform numeric comparison with another value
	 * of double type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq_b(double)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   lt( double rhs )         { return compareerror("number"); }

	/** Less than: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq_b(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   lt( int rhs )         { return compareerror("number"); }

	/** Less than: Perform numeric or string comparison with another value
	 * of unknown type, including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this < rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean lt_b( LuaValue rhs )     { return comparemt(LT,rhs).toboolean(); }

	/** Less than: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this < rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean lt_b( int rhs )         { compareerror("number"); return false; }

	/** Less than: Perform numeric or string comparison with another value
	 * of unknown type, including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this < rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean lt_b( double rhs )      { compareerror("number"); return false; }

	/** Less than or equals: Perform numeric or string comparison with another value
	 * of unknown type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq_b(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   lteq( LuaValue rhs )       { return comparemt(LE,rhs); }

	/** Less than or equals: Perform numeric comparison with another value
	 * of double type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq_b(double)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   lteq( double rhs )       { return compareerror("number"); }

	/** Less than or equals: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq_b(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   lteq( int rhs )       { return compareerror("number"); }

	/** Less than or equals: Perform numeric or string comparison with another value
	 * of unknown type, including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this <= rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean lteq_b( LuaValue rhs )     { return comparemt(LE,rhs).toboolean(); }

	/** Less than or equals: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this <= rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean lteq_b( int rhs )       { compareerror("number"); return false; }

	/** Less than or equals: Perform numeric comparison with another value
	 * of double type,
	 * including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this <= rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq(double)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean lteq_b( double rhs )    { compareerror("number"); return false; }

	/** Greater than: Perform numeric or string comparison with another value
	 * of unknown type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq_b(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   gt( LuaValue rhs )         { return rhs.comparemt(LE,this); }

	/** Greater than: Perform numeric comparison with another value
	 * of double type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq_b(double)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   gt( double rhs )         { return compareerror("number"); }

	/** Greater than: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq_b(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   gt( int rhs )         { return compareerror("number"); }

	/** Greater than: Perform numeric or string comparison with another value
	 * of unknown type, including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this > rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean gt_b( LuaValue rhs )       { return rhs.comparemt(LE,this).toboolean(); }

	/** Greater than: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this > rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if this is not a number
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean gt_b( int rhs )         { compareerror("number"); return false; }

	/** Greater than: Perform numeric or string comparison with another value
	 * of unknown type, including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this > rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LE} metatag is defined.
	 * @see #gteq(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean gt_b( double rhs )      { compareerror("number"); return false; }

	/** Greater than or equals: Perform numeric or string comparison with another value
	 * of unknown type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq_b(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   gteq( LuaValue rhs )       { return rhs.comparemt(LT,this); }

	/** Greater than or equals: Perform numeric comparison with another value
	 * of double type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq_b(double)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   gteq( double rhs )         { return compareerror("number"); }

	/** Greater than or equals: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing, and returning {@link LuaValue}.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not,
	 * or {@link LuaValue} if metatag processing occurs
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq_b(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public LuaValue   gteq( int rhs )         { return valueOf(todouble() >= rhs); }

	/** Greater than or equals: Perform numeric or string comparison with another value
	 * of unknown type, including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, both operands must derive from {@link LuaString}
	 * or both must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this >= rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if either both operands are not a strings or both are not numbers
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq(LuaValue)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean gteq_b( LuaValue rhs )     { return rhs.comparemt(LT,this).toboolean(); }

	/** Greater than or equals: Perform numeric comparison with another value
	 * of int type,
	 * including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this >= rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq(int)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean gteq_b( int rhs )       { compareerror("number"); return false; }

	/** Greater than or equals: Perform numeric comparison with another value
	 * of double type,
	 * including metatag processing,
	 * and returning java boolean.
	 * <p>
	 * To be comparable, this must derive from {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  true if {@code (this >= rhs)}, false if not,
	 * and boolean interpreation of result if metatag processing occurs.
	 * @throws LuaError if this is not a number
	 * and no {@link #LT} metatag is defined.
	 * @see #gteq(double)
	 * @see #comparemt(LuaValue, LuaValue)
	 */
	public boolean gteq_b( double rhs )    { compareerror("number"); return false; }
	
	/** Perform metatag processing for comparison operations.
	 * <p>
	 * Finds the supplied metatag value and invokes it,
	 * or throws {@link LuaError} if none applies.
	 * @param tag The metatag to look up
	 * @param op1 The operand with which to to perform the operation
	 * @return {@link LuaValue} resulting from metatag processing
	 * @throws LuaError if metatag was not defined for either operand,
	 * or if the operands are not the same type,
	 * or the metatag values for the two operands are different.
	 * @see #gt(LuaValue)
	 * @see #gteq(LuaValue)
	 * @see #lt(LuaValue)
	 * @see #lteq(LuaValue)
	 */
	public LuaValue comparemt( LuaValue tag, LuaValue op1 ) {
		LuaValue h;
		if (!(h = metatag(tag)).isnil() || !(h = op1.metatag(tag)).isnil())
			return h.call(this, op1);
		if (LuaValue.LE.raweq(tag) && (!(h = metatag(LT)).isnil() || !(h = op1.metatag(LT)).isnil()))
			return h.call(op1, this).not();
		return error("attempt to compare "+tag+" on "+typename()+" and "+op1.typename());
	}
	
	/** Perform string comparison with another value
	 * of any type
	 * using string comparison based on byte values.
	 * <p>
	 * Only strings can be compared, meaning
	 * each operand must derive from {@link LuaString}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  int < 0 for {@code (this < rhs)}, int > 0 for {@code (this > rhs)}, or 0 when same string.
	 * @throws LuaError if either operand is not a string
	 */
	public int strcmp( LuaValue rhs )         { error("attempt to compare "+typename()); return 0; }

	/** Perform string comparison with another value
	 * known to be a {@link LuaString}
	 * using string comparison based on byte values.
	 * <p>
	 * Only strings can be compared, meaning
	 * each operand must derive from {@link LuaString}.
	 * 
	 * @param rhs The right-hand-side value to perform the comparison with
	 * @return  int < 0 for {@code (this < rhs)}, int > 0 for {@code (this > rhs)}, or 0 when same string.
	 * @throws LuaError if this is not a string
	 */
	public int strcmp( LuaString rhs )      { error("attempt to compare "+typename()); return 0; }

	/** Concatenate another value onto this value and return the result
	 * using rules of lua string concatenation including metatag processing.
	 * <p>
	 * Only strings and numbers as represented can be concatenated, meaning
	 * each operand must derive from {@link LuaString} or {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side value to perform the operation with
	 * @return  {@link LuaValue} resulting from concatenation of {@code (this .. rhs)}
	 * @throws LuaError if either operand is not of an appropriate type,
	 * such as nil or a table
	 */
	public LuaValue concat(LuaValue rhs)      { return this.concatmt(rhs); }

	/** Reverse-concatenation: concatenate this value onto another value
	 * whose type is unknwon
	 * and return the result using rules of lua string concatenation including
	 * metatag processing.
	 * <p>
	 * Only strings and numbers as represented can be concatenated, meaning
	 * each operand must derive from {@link LuaString} or {@link LuaNumber}.
	 * 
	 * @param lhs The left-hand-side value onto which this will be concatenated
	 * @return  {@link LuaValue} resulting from concatenation of {@code (lhs .. this)}
	 * @throws LuaError if either operand is not of an appropriate type,
	 * such as nil or a table
	 * @see #concat(LuaValue)
	 */
	public LuaValue concatTo(LuaValue lhs)    { return lhs.concatmt(this); }

	/** Reverse-concatenation: concatenate this value onto another value
	 * known to be a {@link  LuaNumber}
	 * and return the result using rules of lua string concatenation including
	 * metatag processing.
	 * <p>
	 * Only strings and numbers as represented can be concatenated, meaning
	 * each operand must derive from {@link LuaString} or {@link LuaNumber}.
	 * 
	 * @param lhs The left-hand-side value onto which this will be concatenated
	 * @return  {@link LuaValue} resulting from concatenation of {@code (lhs .. this)}
	 * @throws LuaError if either operand is not of an appropriate type,
	 * such as nil or a table
	 * @see #concat(LuaValue)
	 */
	public LuaValue concatTo(LuaNumber lhs)   { return lhs.concatmt(this); }
	
	/** Reverse-concatenation: concatenate this value onto another value
	 * known to be a {@link  LuaString}
	 * and return the result using rules of lua string concatenation including
	 * metatag processing.
	 * <p>
	 * Only strings and numbers as represented can be concatenated, meaning
	 * each operand must derive from {@link LuaString} or {@link LuaNumber}.
	 * 
	 * @param lhs The left-hand-side value onto which this will be concatenated
	 * @return  {@link LuaValue} resulting from concatenation of {@code (lhs .. this)}
	 * @throws LuaError if either operand is not of an appropriate type,
	 * such as nil or a table
	 * @see #concat(LuaValue)
	 */
	public LuaValue concatTo(LuaString lhs)   { return lhs.concatmt(this); }

	/** Convert the value to a {@link Buffer} for more efficient concatenation of
	 * multiple strings.
	 * @return Buffer instance containing the string or number
	 */
	public Buffer   buffer()                  { return new Buffer(this); }
	
	/** Concatenate a {@link Buffer} onto this value and return the result
	 * using rules of lua string concatenation including metatag processing.
	 * <p>
	 * Only strings and numbers as represented can be concatenated, meaning
	 * each operand must derive from {@link LuaString} or {@link LuaNumber}.
	 * 
	 * @param rhs The right-hand-side {@link Buffer} to perform the operation with
	 * @return LuaString resulting from concatenation of {@code (this .. rhs)}
	 * @throws LuaError if either operand is not of an appropriate type,
	 * such as nil or a table
	 */
	public Buffer   concat(Buffer rhs)        { return rhs.concatTo(this); }
	
	/** Perform metatag processing for concatenation operations.
	 * <p>
	 * Finds the {@link #CONCAT} metatag value and invokes it,
	 * or throws {@link LuaError} if it doesn't exist.
	 * @param rhs The right-hand-side value to perform the operation with
	 * @return {@link LuaValue} resulting from metatag processing for {@link #CONCAT} metatag.
	 * @throws LuaError if metatag was not defined for either operand
	 */
	public LuaValue concatmt(LuaValue rhs) {
		LuaValue h=metatag(CONCAT);
		if ( h.isnil() && (h=rhs.metatag(CONCAT)).isnil())
			error("attempt to concatenate "+typename()+" and "+rhs.typename());
		return h.call(this,rhs);
	}
	
	/** Perform boolean {@code and} with another operand, based on lua rules for boolean evaluation.
	 * This returns either {@code this} or {@code rhs} depending on the boolean value for {@code this}.
	 * 
	 * @param rhs The right-hand-side value to perform the operation with
	 * @return {@code this} if {@code this.toboolean()} is false, {@code rhs} otherwise.
	 */
	public LuaValue   and( LuaValue rhs )      { return this.toboolean()? rhs: this; }
	
	/** Perform boolean {@code or} with another operand, based on lua rules for boolean evaluation.
	 * This returns either {@code this} or {@code rhs} depending on the boolean value for {@code this}.
	 * 
	 * @param rhs The right-hand-side value to perform the operation with
	 * @return {@code this} if {@code this.toboolean()} is true, {@code rhs} otherwise.
	 */
	public LuaValue   or( LuaValue rhs )       { return this.toboolean()? this: rhs; }
	
	/** Perform end-condition test in for-loop processing.
	 * <p>
	 * Used in lua-bytecode to Java-bytecode conversion.
	 * 
	 * @param limit the numerical limit to complete the for loop
	 * @param step the numberical step size to use.
	 * @return true if limit has not been reached, false otherwise.
	 */
	public boolean testfor_b(LuaValue limit, LuaValue step) { return step.gt_b(0)? lteq_b(limit): gteq_b(limit); }
	
	/**
	 * Convert this value to a string if it is a {@link LuaString} or {@link LuaNumber},
	 * or throw a {@link LuaError} if it is not
	 * @return {@link LuaString} corresponding to the value if a string or number
	 * @throws LuaError if not a string or number
	 */
	public LuaString strvalue()     { typerror("string or number"); return null; }

	/** Return this value as a strong reference, or null if it was weak and is no longer referenced.
	 * @return {@link LuaValue} referred to, or null if it was weak and is no longer referenced.
	 * @see WeakTable
	 */
	public LuaValue  strongvalue()  { return this; }

	/** Convert java boolean to a {@link LuaValue}.
	 * 
	 * @param b boolean value to convert
	 * @return {@link #TRUE} if not  or {@link #FALSE} if false
	 */
	public static LuaBoolean  valueOf(boolean b)    { return b? LuaValue.TRUE: FALSE; };

	/** Convert java int to a {@link LuaValue}.
	 * 
	 * @param i int value to convert
	 * @return {@link LuaInteger} instance, possibly pooled, whose value is i
	 */
	public static LuaInteger  valueOf(int i)        { return LuaInteger.valueOf(i); }

	/** Convert java long to a {@link LuaValue}.
	 *
	 * @param l long value to convert
	 * @return {@link LuaInteger} instance, possibly pooled, whose value is l
	 */
	public static LuaInteger  valueOf(long l)       { return LuaInteger.valueOf(l); }
	
	/** Convert java double to a {@link LuaValue}.
	 * This may return a {@link LuaInteger} or {@link LuaDouble} depending
	 * on the value supplied.
	 * 
	 * @param d double value to convert
	 * @return {@link LuaNumber} instance, possibly pooled, whose value is d
	 */
	public static LuaNumber   valueOf(double d)     { return LuaDouble.valueOf(d); };
	
	/** Convert java string to a {@link LuaValue}.
	 * 
	 * @param s String value to convert
	 * @return {@link LuaString} instance, possibly pooled, whose value is s
	 */
	public static LuaString valueOf(String s)     { return LuaString.valueOf(s); }

	/** Convert bytes in an array to a {@link LuaValue}.
	 * 
	 * @param bytes byte array to convert
	 * @return {@link LuaString} instance, possibly pooled, whose bytes are those in the supplied array
	 */
	public static LuaString valueOf(byte[] bytes) { return LuaString.valueOf(bytes); }
	
	/** Convert bytes in an array to a {@link LuaValue}.
	 * 
	 * @param bytes byte array to convert
	 * @param off offset into the byte array, starting at 0
	 * @param len number of bytes to include in the {@link LuaString}
	 * @return {@link LuaString} instance, possibly pooled, whose bytes are those in the supplied array
	 */
	public static LuaString valueOf(byte[] bytes, int off, int len) {
		return LuaString.valueOf(bytes,off,len);
	}
	
	/** Construct an empty {@link LuaTable}.
	 * @return new {@link LuaTable} instance with no values and no metatable.
	 */
	public static LuaTable tableOf() { return new LuaTable(); }

	/** Construct a {@link LuaTable} initialized with supplied array values.
	 * @param varargs {@link Varargs} containing the values to use in initialization
	 * @param firstarg the index of the first argument to use from the varargs, 1 being the first.
	 * @return new {@link LuaTable} instance with sequential elements coming from the varargs.
	 */
	public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs,firstarg); }
	
	/** Construct an empty {@link LuaTable} preallocated to hold array and hashed elements
	 * @param narray Number of array elements to preallocate
	 * @param nhash Number of hash elements to preallocate
	 * @return new {@link LuaTable} instance with no values and no metatable, but preallocated for array and hashed elements.
	 */
	public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); }
	
	/** Construct a {@link LuaTable} initialized with supplied array values.
	 * @param unnamedValues array of {@link LuaValue} containing the values to use in initialization
	 * @return new {@link LuaTable} instance with sequential elements coming from the array.
	 */
	public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null,unnamedValues,null); }
	
	/** Construct a {@link LuaTable} initialized with supplied array values.
	 * @param unnamedValues array of {@link LuaValue} containing the first values to use in initialization
	 * @param lastarg {@link Varargs} containing additional values to use in initialization
	 * to be put after the last unnamedValues element
	 * @return new {@link LuaTable} instance with sequential elements coming from the array and varargs.
	 */
	public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); }

	/** Construct a {@link LuaTable} initialized with supplied named values.
	 * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization
	 * in order {@code {key-a, value-a, key-b, value-b, ...} }
	 * @return new {@link LuaTable} instance with non-sequential keys coming from the supplied array.
	 */
	public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues,null,null); }

	/** Construct a {@link LuaTable} initialized with supplied named values and sequential elements.
	 * The named values will be assigned first, and the sequential elements will be assigned later,
	 * possibly overwriting named values at the same slot if there are conflicts.
	 * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization
	 * in order {@code {key-a, value-a, key-b, value-b, ...} }
	 * @param unnamedValues array of {@link LuaValue} containing the sequenctial elements to use in initialization
	 * in order {@code {value-1, value-2, ...} }, or null if there are none
	 * @return new {@link LuaTable} instance with named and sequential values supplied.
	 */
	public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues) {return new LuaTable(namedValues,unnamedValues,null); }

	/** Construct a {@link LuaTable} initialized with supplied named values and sequential elements in an array part and as varargs.
	 * The named values will be assigned first, and the sequential elements will be assigned later,
	 * possibly overwriting named values at the same slot if there are conflicts.
	 * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization
	 * in order {@code {key-a, value-a, key-b, value-b, ...} }
	 * @param unnamedValues array of {@link LuaValue} containing the first sequenctial elements to use in initialization
	 * in order {@code {value-1, value-2, ...} }, or null if there are none
	 * @param lastarg {@link Varargs} containing additional values to use in the sequential part of the initialization,
	 * to be put after the last unnamedValues element
	 * @return new {@link LuaTable} instance with named and sequential values supplied.
	 */
	public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues, Varargs lastarg) {return new LuaTable(namedValues,unnamedValues,lastarg); }
	
	/** Construct a LuaUserdata for an object.
	 * 
	 * @param o The java instance to be wrapped as userdata
	 * @return {@link LuaUserdata} value wrapping the java instance.
	 */
	public static LuaUserdata userdataOf(Object o) { return new LuaUserdata(o); }
	
	/** Construct a LuaUserdata for an object with a user supplied metatable.
	 * 
	 * @param o The java instance to be wrapped as userdata
	 * @param metatable The metatble to associate with the userdata instance.
	 * @return {@link LuaUserdata} value wrapping the java instance.
	 */
	public static LuaUserdata userdataOf(Object o,LuaValue metatable) { return new LuaUserdata(o,metatable); }

	/** Constant limiting metatag loop processing */
	private static final int      MAXTAGLOOP = 100;
	
	/**
	 * Return value for field reference including metatag processing, or {@link LuaValue#NIL} if it doesn't exist.
	 * @param t {@link LuaValue} on which field is being referenced, typically a table or something with the metatag {@link LuaValue#INDEX} defined
	 * @param key {@link LuaValue} naming the field to reference
	 * @return {@link LuaValue} for the {@code key} if it exists, or {@link LuaValue#NIL}
	 * @throws LuaError if there is a loop in metatag processing
	 */
	/** get value from metatable operations, or NIL if not defined by metatables */
	protected static LuaValue gettable(LuaValue t, LuaValue key) {
		LuaValue tm;
		int loop = 0;
		do {
			if (t.istable()) {
				LuaValue res = t.rawget(key);
				if ((!res.isnil()) || (tm = t.metatag(INDEX)).isnil())
					return res;
			} else if ((tm = t.metatag(INDEX)).isnil())
				t.indexerror(key.tojstring());
			if (tm.isfunction())
				return tm.call(t, key);
			t = tm;
		}
		while ( ++loop < MAXTAGLOOP );
		error("loop in gettable");
		return NIL;
	}
	
	/**
	 * Perform field assignment including metatag processing.
	 * @param t {@link LuaValue} on which value is being set, typically a table or something with the metatag {@link LuaValue#NEWINDEX} defined
	 * @param key {@link LuaValue} naming the field to assign
	 * @param value {@link LuaValue} the new value to assign to {@code key}
	 * @throws LuaError if there is a loop in metatag processing
	 * @return true if assignment or metatag processing succeeded, false otherwise
	 */
	protected static boolean settable(LuaValue t, LuaValue key, LuaValue value) {
		LuaValue tm;
		int loop = 0;
		do {
			if (t.istable()) {
				if ((!t.rawget(key).isnil()) || (tm = t.metatag(NEWINDEX)).isnil()) {
					t.rawset(key, value);
					return true;
				}
			} else if ((tm = t.metatag(NEWINDEX)).isnil())
				throw new LuaError("table expected for set index ('" + key + "') value, got " + t.typename());
			if (tm.isfunction()) {
				tm.call(t, key, value);
				return true;
			}
			t = tm;
		}
		while ( ++loop < MAXTAGLOOP );
		error("loop in settable");
		return false;
	}
	
    /**
     * Get particular metatag, or return {@link LuaValue#NIL} if it doesn't exist
     * @param tag Metatag name to look up, typically a string such as
     * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX}
     * @return {@link LuaValue} for tag {@code reason}, or  {@link LuaValue#NIL}
     */
    public LuaValue metatag(LuaValue tag) {
    	LuaValue mt = getmetatable();
    	if ( mt == null )
    		return NIL;
    	return mt.rawget(tag);
    }

    /**
     * Get particular metatag, or throw {@link LuaError} if it doesn't exist
     * @param tag Metatag name to look up, typically a string such as
     * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX}
     * @param reason Description of error when tag lookup fails.
     * @return {@link LuaValue} that can be called
     * @throws LuaError when the lookup fails.
     */
	protected LuaValue checkmetatag(LuaValue tag, String reason) {
		LuaValue h = this.metatag(tag);
		if ( h.isnil() )
			throw new LuaError(reason + "a " + typename() + " value");
		return h;
	}

	/** Construct a Metatable instance from the given LuaValue */
	protected static Metatable metatableOf(LuaValue mt) {
		if ( mt != null && mt.istable() ) {
			LuaValue mode = mt.rawget(MODE);
			if ( mode.isstring() ) {
				String m = mode.tojstring();
				boolean weakkeys = m.indexOf('k') >= 0;
				boolean weakvalues = m.indexOf('v') >= 0;
				if ( weakkeys || weakvalues ) {
					return new WeakTable(weakkeys, weakvalues, mt);
				}
			}
			return (LuaTable)mt;
		} else if ( mt != null ) {
			return new NonTableMetatable( mt );
		} else {
			return null;
		}
	}

	/** Throw {@link LuaError} indicating index was attempted on illegal type
	 * @throws LuaError when called.
	 */
    private void indexerror(String key) {
		error( "attempt to index ? (a "+typename()+" value) with key '" + key + "'" );
	}
 	
	/** Construct a {@link Varargs} around an array of {@link LuaValue}s.
	 * 
	 * @param v The array of {@link LuaValue}s
	 * @return {@link Varargs} wrapping the supplied values.
	 * @see LuaValue#varargsOf(LuaValue, Varargs)
	 * @see LuaValue#varargsOf(LuaValue[], int, int)
	 */
	public static Varargs varargsOf(final LuaValue[] v) {
		switch ( v.length ) {
		case 0: return NONE;
		case 1: return v[0];
		case 2: return new PairVarargs(v[0],v[1]);
		default: return new ArrayVarargs(v,NONE);
		}
	}
	
	/** Construct a {@link Varargs} around an array of {@link LuaValue}s.
	 * 
	 * @param v The array of {@link LuaValue}s
	 * @param r {@link Varargs} contain values to include at the end
	 * @return {@link Varargs} wrapping the supplied values.
	 * @see LuaValue#varargsOf(LuaValue[])
	 * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
	 */
	public static Varargs varargsOf(final LuaValue[] v,Varargs r) {
		switch ( v.length ) {
		case 0: return r;
		case 1: return r.narg()>0?
					(Varargs) new PairVarargs(v[0],r):
					(Varargs) v[0];
		case 2: return r.narg()>0?
					(Varargs) new ArrayVarargs(v,r):
					(Varargs) new PairVarargs(v[0],v[1]);
		default: return new ArrayVarargs(v,r);
		}
	}

	/** Construct a {@link Varargs} around an array of {@link LuaValue}s.
	 * 
	 * @param v The array of {@link LuaValue}s
	 * @param offset number of initial values to skip in the array
	 * @param length number of values to include from the array
	 * @return {@link Varargs} wrapping the supplied values.
	 * @see LuaValue#varargsOf(LuaValue[])
	 * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
	 */
	public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length) {
		switch ( length ) {
		case 0: return NONE;
		case 1: return v[offset];
		case 2: return new PairVarargs(v[offset+0],v[offset+1]);
		default: return new ArrayPartVarargs(v, offset, length, NONE);
		}
	}

	/** Construct a {@link Varargs} around an array of {@link LuaValue}s.
	 * 
	 * Caller must ensure that array contents are not mutated after this call
	 * or undefined behavior will result.
	 * 
	 * @param v The array of {@link LuaValue}s
	 * @param offset number of initial values to skip in the array
	 * @param length number of values to include from the array
	 * @param more {@link Varargs} contain values to include at the end
	 * @return {@link Varargs} wrapping the supplied values.
	 * @see LuaValue#varargsOf(LuaValue[], Varargs)
	 * @see LuaValue#varargsOf(LuaValue[], int, int)
	 */
	public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length, Varargs more) {
		switch ( length ) {
		case 0: return more;
		case 1: return more.narg()>0?
					(Varargs) new PairVarargs(v[offset],more):
					(Varargs) v[offset];
		case 2: return more.narg()>0?
					(Varargs) new ArrayPartVarargs(v,offset,length,more):
					(Varargs) new PairVarargs(v[offset],v[offset+1]);
		default: return new ArrayPartVarargs(v,offset,length,more);
		}
	}

	/** Construct a {@link Varargs} around a set of 2 or more {@link LuaValue}s.
	 * <p>
	 * This can be used to wrap exactly 2 values, or a list consisting of 1 initial value
	 * followed by another variable list of remaining values.
	 * 
	 * @param v First {@link LuaValue} in the {@link Varargs}
	 * @param r {@link LuaValue} supplying the 2rd value,
	 * or {@link Varargs}s supplying all values beyond the first
	 * @return {@link Varargs} wrapping the supplied values.
	 */
	public static Varargs varargsOf(LuaValue v, Varargs r) {
		switch ( r.narg() ) {
		case 0: return v;
		default: return new PairVarargs(v,r);
		}
	}
	
	/** Construct a {@link Varargs} around a set of 3 or more {@link LuaValue}s.
	 * <p>
	 * This can be used to wrap exactly 3 values, or a list consisting of 2 initial values
	 * followed by another variable list of remaining values.
	 * 
	 * @param v1 First {@link LuaValue} in the {@link Varargs}
	 * @param v2 Second {@link LuaValue} in the {@link Varargs}
	 * @param v3 {@link LuaValue} supplying the 3rd value,
	 * or {@link Varargs}s supplying all values beyond the second
	 * @return {@link Varargs} wrapping the supplied values.
	 */
	public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) {
		switch ( v3.narg() ) {
		case 0: return new PairVarargs(v1,v2);
		default: return new ArrayPartVarargs(new LuaValue[]{v1,v2}, 0, 2, v3);
		}
	}
	
	/** Construct a {@link TailcallVarargs} around a function and arguments.
	 * <p>
	 * The tail call is not yet called or processing until the client invokes
	 * {@link TailcallVarargs#eval()} which performs the tail call processing.
	 * <p>
	 * This method is typically not used directly by client code.
	 * Instead use one of the function invocation methods.
	 * 
	 * @param func {@link LuaValue} to be called as a tail call
	 * @param args {@link Varargs} containing the arguments to the call
	 * @return {@link TailcallVarargs} to be used in tailcall oprocessing.
	 * @see LuaValue#call()
	 * @see LuaValue#invoke()
	 * @see LuaValue#method(LuaValue)
	 * @see LuaValue#invokemethod(LuaValue)
	 */
	public static Varargs tailcallOf(LuaValue func, Varargs args) {
		return new TailcallVarargs(func, args);
	}
	
	/**
	 * Callback used during tail call processing to invoke the function once.
	 * <p>
	 * This may return a {@link TailcallVarargs} to be evaluated by the client.
	 * <p>
	 * This should not be called directly, instead use one of the call invocation functions.
	 * 
	 * @param args the arguments to the call invocation.
	 * @return Varargs the return values, possible a TailcallVarargs.
	 * @see LuaValue#call()
	 * @see LuaValue#invoke()
	 * @see LuaValue#method(LuaValue)
	 * @see LuaValue#invokemethod(LuaValue)
	 */
	public Varargs onInvoke(Varargs args) {
		return invoke(args);
	}

	/** Hook for implementations such as LuaJC to load the environment of the main chunk
	 * into the first upvalue location.  If the function has no upvalues or is not a main chunk,
	 * calling this will be no effect.
	 * @param env  The environment to load into the first upvalue, if there is one.
	 */
	public void initupvalue1(LuaValue env) {}

	/** Varargs implemenation with no values.
	 * <p>
	 * This is an internal class not intended to be used directly.
	 * Instead use the predefined constant {@link LuaValue#NONE}
	 * 
	 * @see LuaValue#NONE
	 */
	private static final class None extends LuaNil {
		static None _NONE = new None();
		public LuaValue arg(int i) { return NIL; }
		public int narg() { return 0; }
		public LuaValue arg1() { return NIL; }
		public String tojstring() { return "none"; }
		public Varargs subargs(final int start) { return start > 0? this: argerror(1, "start must be > 0"); }
		void copyto(LuaValue[] dest, int offset, int length) { for(;length>0; length--) dest[offset++] = NIL; }
	}
	
	/**
	 * 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) {
		if (start == 1)
			return this;
		if (start > 1)
			return NONE;
		return argerror(1, "start must be > 0");
	}

}
