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

org.luaj.vm2.LuaValue Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/*******************************************************************************
* 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; 
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy