org.luaj.vm2.LuaValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of luaj-jse Show documentation
Show all versions of luaj-jse Show documentation
Luaj 2.0 for the jse platform
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
abstract
public class LuaValue extends Varargs {
public static final int TINT = (-2);
public static final int TNONE = (-1);
public static final int TNIL = 0;
public static final int TBOOLEAN = 1;
public static final int TLIGHTUSERDATA = 2;
public static final int TNUMBER = 3;
public static final int TSTRING = 4;
public static final int TTABLE = 5;
public static final int TFUNCTION = 6;
public static final int TUSERDATA = 7;
public static final int TTHREAD = 8;
public static final int TVALUE = 9;
public static final String[] TYPE_NAMES = {
"nil",
"boolean",
"lightuserdata",
"number",
"string",
"table",
"function",
"userdata",
"thread",
"value",
};
public static final LuaValue NIL = new LuaNil();
public static final LuaBoolean TRUE = new LuaBoolean(true);
public static final LuaBoolean FALSE = new LuaBoolean(false);
public static final LuaValue NONE = new None();
public static final LuaNumber ZERO = LuaInteger.valueOf(0);
public static final LuaNumber ONE = LuaInteger.valueOf(1);
public static final LuaNumber MINUSONE = LuaInteger.valueOf(-1);
public static final LuaValue[] NOVALS = {};
public static final LuaString INDEX = valueOf("__index");
public static final LuaString NEWINDEX = valueOf("__newindex");
public static final LuaString CALL = valueOf("__call");
public static final LuaString MODE = valueOf("__mode");
public static final LuaString METATABLE = valueOf("__metatable");
public static final LuaString ADD = valueOf("__add");
public static final LuaString SUB = valueOf("__sub");
public static final LuaString DIV = valueOf("__div");
public static final LuaString MUL = valueOf("__mul");
public static final LuaString POW = valueOf("__pow");
public static final LuaString MOD = valueOf("__mod");
public static final LuaString UNM = valueOf("__unm");
public static final LuaString LEN = valueOf("__len");
public static final LuaString EQ = valueOf("__eq");
public static final LuaString LT = valueOf("__lt");
public static final LuaString LE = valueOf("__le");
public static final LuaString TOSTRING = valueOf("__tostring");
public static final LuaString CONCAT = valueOf("__concat");
public static final LuaString EMPTYSTRING = valueOf("");
private static int MAXSTACK = 250;
public static final LuaValue[] NILS = new LuaValue[MAXSTACK];
static {
for ( int i=0; i= rhs); }
public boolean gteq_b( LuaValue rhs ) { return rhs.comparemt(LT,this).toboolean(); }
public boolean gteq_b( int rhs ) { compareerror("number"); return false; }
public boolean gteq_b( double rhs ) { compareerror("number"); return false; }
public LuaValue comparemt( LuaValue tag, LuaValue op1 ) {
if ( type() == op1.type() ) {
LuaValue h = metatag(tag);
if ( !h.isnil() && h == op1.metatag(tag) )
return h.call(this, op1);
}
return error("attempt to compare "+tag+" on "+typename()+" and "+op1.typename());
}
// string comparison
public int strcmp( LuaValue rhs ) { error("attempt to compare "+typename()); return 0; }
public int strcmp( LuaString rhs ) { error("attempt to compare "+typename()); return 0; }
// concatenation
public LuaValue concat(LuaValue rhs) { return this.concatmt(rhs); }
public LuaValue concatTo(LuaValue lhs) { return lhs.concatmt(this); }
public LuaValue concatTo(LuaNumber lhs) { return lhs.concatmt(this); }
public LuaValue concatTo(LuaString lhs) { return lhs.concatmt(this); }
public Buffer buffer() { return new Buffer(this); }
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
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);
}
// boolean operators
public LuaValue and( LuaValue rhs ) { return this.toboolean()? rhs: this; }
public LuaValue or( LuaValue rhs ) { return this.toboolean()? this: rhs; }
// for loop helpers
/** used in for loop only */
public boolean testfor_b(LuaValue limit, LuaValue step) { return step.gt_b(0)? lteq_b(limit): gteq_b(limit); }
// lua number/string conversion
public LuaString strvalue() { typerror("strValue"); return null; }
public LuaValue strongkey() { return strongvalue(); }
public LuaValue strongvalue() { return this; }
public boolean isweaknil() { return false; }
// conversion from java values
public static LuaBoolean valueOf(boolean b) { return b? LuaValue.TRUE: FALSE; };
public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); }
public static LuaNumber valueOf(double d) { return LuaDouble.valueOf(d); };
public static LuaString valueOf(String s) { return LuaString.valueOf(s); }
public static LuaString valueOf(byte[] bytes) { return LuaString.valueOf(bytes); }
public static LuaString valueOf(byte[] bytes, int off, int len) {
return LuaString.valueOf(bytes,off,len);
}
// table initializers
public static LuaTable tableOf() { return new LuaTable(); }
public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs,firstarg); }
public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); }
public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null,unnamedValues,null); }
public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); }
public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues,null,null); }
public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues) {return new LuaTable(namedValues,unnamedValues,null); }
public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues, Varargs lastarg) {return new LuaTable(namedValues,unnamedValues,lastarg); }
// userdata intializers
public static LuaUserdata userdataOf(Object o) { return new LuaUserdata(o); }
public static LuaUserdata userdataOf(Object o,LuaValue metatable) { return new LuaUserdata(o,metatable); }
private static final int MAXTAGLOOP = 100;
// metatable 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();
if (tm.isfunction())
return tm.call(t, key);
t = tm;
}
while ( ++loop < MAXTAGLOOP );
error("loop in gettable");
return NIL;
}
/** returns true if value was set via metatable processing, false otherwise */
protected static boolean settable(LuaValue t, LuaValue key, LuaValue val) {
LuaValue tm;
int loop = 0;
do {
if (t.istable()) {
if ((!t.rawget(key).isnil()) || (tm = t.metatag(NEWINDEX)).isnil()) {
t.rawset(key, val);
return true;
}
} else if ((tm = t.metatag(NEWINDEX)).isnil())
t.typerror("index");
if (tm.isfunction()) {
tm.call(t, key, val);
return true;
}
t = tm;
}
while ( ++loop < MAXTAGLOOP );
error("loop in settable");
return false;
}
public LuaValue metatag(LuaValue tag) {
LuaValue mt = getmetatable();
if ( mt == null )
return NIL;
return mt.rawget(tag);
}
protected LuaValue checkmetatag(LuaValue tag, String reason) {
LuaValue h = this.metatag(tag);
if ( h.isnil() )
throw new LuaError(reason+typename());
return h;
}
private void indexerror() {
error( "attempt to index ? (a "+typename()+" value)" );
}
// common varargs constructors
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);
}
}
public static Varargs varargsOf(final LuaValue[] v,Varargs r) {
switch ( v.length ) {
case 0: return r;
case 1: return new PairVarargs(v[0],r);
default: return new ArrayVarargs(v,r);
}
}
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);
}
}
public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length,Varargs more) {
switch ( length ) {
case 0: return more;
case 1: return new PairVarargs(v[offset],more);
default: return new ArrayPartVarargs(v,offset,length,more);
}
}
public static Varargs varargsOf(LuaValue v, Varargs r) {
switch ( r.narg() ) {
case 0: return v;
default: return new PairVarargs(v,r);
}
}
public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) {
switch ( v3.narg() ) {
case 0: return new PairVarargs(v1,v2);
default: return new ArrayVarargs(new LuaValue[] {v1,v2},v3);
}
}
// tail call support
public static Varargs tailcallOf(LuaValue func, Varargs args) {
return new TailcallVarargs(func, args);
}
// called by TailcallVarargs to invoke the function once.
// may return TailcallVarargs to be evaluated by the caller.
public Varargs onInvoke(Varargs args) {
return invoke(args);
}
// empty varargs
private static final class None extends LuaNil {
public LuaValue arg(int i) { return NIL; }
public int narg() { return 0; }
public LuaValue arg1() { return NIL; }
public String tojstring() { return "none"; }
}
// varargs from array
static final class ArrayVarargs extends Varargs {
private final LuaValue[] v;
private final Varargs r;
ArrayVarargs(LuaValue[] v, Varargs r) {
this.v = v;
this.r = r ;
}
public LuaValue arg(int i) {
return i >=1 && i<=v.length? v[i - 1]: r.arg(i-v.length);
}
public int narg() {
return v.length+r.narg();
}
public LuaValue arg1() { return v.length>0? v[0]: r.arg1(); }
}
// varargs from array part
static final class ArrayPartVarargs extends Varargs {
private final int offset;
private final LuaValue[] v;
private final int length;
private final Varargs more;
ArrayPartVarargs(LuaValue[] v, int offset, int length) {
this.v = v;
this.offset = offset;
this.length = length;
this.more = NONE;
}
public ArrayPartVarargs(LuaValue[] v, int offset, int length, Varargs more) {
this.v = v;
this.offset = offset;
this.length = length;
this.more = more;
}
public LuaValue arg(int i) {
return i>=1&&i<=length? v[i+offset-1]: more.arg(i-length);
}
public int narg() {
return length + more.narg();
}
public LuaValue arg1() {
return length>0? v[offset]: more.arg1();
}
}
// varargs from two values
static final class PairVarargs extends Varargs {
private final LuaValue v1;
private final Varargs v2;
PairVarargs(LuaValue v1, Varargs v2) {
this.v1 = v1;
this.v2 = v2;
}
public LuaValue arg(int i) {
return i==1? v1: v2.arg(i-1);
}
public int narg() {
return 1+v2.narg();
}
public LuaValue arg1() {
return v1;
}
}
}