Remove obsolete v 1.0 source files (still available in 1.0 branch).

This commit is contained in:
James Roseborough
2009-10-27 06:20:40 +00:00
parent 3863ff8e46
commit d1debdf2ec
123 changed files with 3 additions and 21813 deletions

View File

@@ -105,7 +105,9 @@
<mkdir dir="build/luaj-${version}/src"/> <mkdir dir="build/luaj-${version}/src"/>
<mkdir dir="build/luaj-${version}/lib"/> <mkdir dir="build/luaj-${version}/lib"/>
<copy todir="build/luaj-${version}/src"> <copy todir="build/luaj-${version}/src">
<fileset dir="src"/> <fileset dir="src">
<exclude name="src/test/**"/>
</fileset>
</copy> </copy>
<copy todir="build/luaj-${version}/test"> <copy todir="build/luaj-${version}/test">
<fileset dir="test"/> <fileset dir="test"/>

View File

@@ -1,269 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.compiler;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.luaj.vm.LNumber;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LString;
import org.luaj.vm.LValue;
import org.luaj.vm.LocVars;
import org.luaj.vm.Lua;
public class DumpState {
/** mark for precompiled code (`<esc>Lua') */
public static final String LUA_SIGNATURE = "\033Lua";
/** for header of binary files -- this is Lua 5.1 */
public static final int LUAC_VERSION = 0x51;
/** for header of binary files -- this is the official format */
public static final int LUAC_FORMAT = 0;
/** size of header of binary files */
public static final int LUAC_HEADERSIZE = 12;
/** expected lua header bytes */
private static final byte[] LUAC_HEADER_SIGNATURE = { '\033', 'L', 'u', 'a' };
/** set true to allow integer compilation */
public static boolean ALLOW_INTEGER_CASTING = false;
/** format corresponding to non-number-patched lua, all numbers are floats or doubles */
public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
/** format corresponding to non-number-patched lua, all numbers are ints */
public static final int NUMBER_FORMAT_INTS_ONLY = 1;
/** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
/** default number format */
public static final int NUMBER_FORMAT_DEFAULT = NUMBER_FORMAT_FLOATS_OR_DOUBLES;
// header fields
private boolean IS_LITTLE_ENDIAN = false;
private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT;
private int SIZEOF_LUA_NUMBER = 8;
private static final int SIZEOF_INT = 4;
private static final int SIZEOF_SIZET = 4;
private static final int SIZEOF_INSTRUCTION = 4;
DataOutputStream writer;
boolean strip;
int status;
public DumpState(OutputStream w, boolean strip) {
this.writer = new DataOutputStream( w );
this.strip = strip;
this.status = 0;
}
void dumpBlock(final byte[] b, int size) throws IOException {
writer.write(b, 0, size);
}
void dumpChar(int b) throws IOException {
writer.write( b );
}
void dumpInt(int x) throws IOException {
if ( IS_LITTLE_ENDIAN ) {
writer.writeByte(x&0xff);
writer.writeByte((x>>8)&0xff);
writer.writeByte((x>>16)&0xff);
writer.writeByte((x>>24)&0xff);
} else {
writer.writeInt(x);
}
}
void dumpString(LString s) throws IOException {
final int len = s.length();
dumpInt( len+1 );
s.write( writer, 0, len );
writer.write( 0 );
}
void dumpDouble(double d) throws IOException {
long l = Double.doubleToLongBits(d);
if ( IS_LITTLE_ENDIAN ) {
dumpInt( (int) l );
dumpInt( (int) (l>>32) );
} else {
writer.writeLong(l);
}
}
void dumpCode( final LPrototype f ) throws IOException {
final int[] code = f.code;
int n = code.length;
dumpInt( n );
for ( int i=0; i<n; i++ )
dumpInt( code[i] );
}
void dumpConstants(final LPrototype f) throws IOException {
final LValue[] k = f.k;
int i, n = k.length;
dumpInt(n);
for (i = 0; i < n; i++) {
final LValue o = k[i];
switch ( o.luaGetType() ) {
case Lua.LUA_TNIL:
writer.write(Lua.LUA_TNIL);
break;
case Lua.LUA_TBOOLEAN:
writer.write(Lua.LUA_TBOOLEAN);
dumpChar(o.toJavaBoolean() ? 1 : 0);
break;
case Lua.LUA_TNUMBER:
switch (NUMBER_FORMAT) {
case NUMBER_FORMAT_FLOATS_OR_DOUBLES:
writer.write(Lua.LUA_TNUMBER);
dumpDouble(o.toJavaDouble());
break;
case NUMBER_FORMAT_INTS_ONLY:
if ( ! ALLOW_INTEGER_CASTING && ! o.isInteger() )
throw new java.lang.IllegalArgumentException("not an integer: "+o);
writer.write(Lua.LUA_TNUMBER);
dumpInt(o.toJavaInt());
break;
case NUMBER_FORMAT_NUM_PATCH_INT32:
if ( o.isInteger() ) {
writer.write(Lua.LUA_TINT);
dumpInt(o.toJavaInt());
} else {
writer.write(Lua.LUA_TNUMBER);
dumpDouble(o.toJavaDouble());
}
break;
default:
throw new IllegalArgumentException("number format not supported: "+NUMBER_FORMAT);
}
break;
case Lua.LUA_TSTRING:
writer.write(Lua.LUA_TSTRING);
dumpString(o.luaAsString());
break;
default:
throw new IllegalArgumentException("bad type for " + o);
}
}
n = f.p.length;
dumpInt(n);
for (i = 0; i < n; i++)
dumpFunction(f.p[i], f.source);
}
void dumpDebug(final LPrototype f) throws IOException {
int i, n;
n = (strip) ? 0 : f.lineinfo.length;
dumpInt(n);
for (i = 0; i < n; i++)
dumpInt(f.lineinfo[i]);
n = (strip) ? 0 : f.locvars.length;
dumpInt(n);
for (i = 0; i < n; i++) {
LocVars lvi = f.locvars[i];
dumpString(lvi.varname);
dumpInt(lvi.startpc);
dumpInt(lvi.endpc);
}
n = (strip) ? 0 : f.upvalues.length;
dumpInt(n);
for (i = 0; i < n; i++)
dumpString(f.upvalues[i]);
}
void dumpFunction(final LPrototype f, final LString string) throws IOException {
if ( f.source == null || f.source.equals(string) || strip )
dumpInt(0);
else
dumpString(f.source);
dumpInt(f.linedefined);
dumpInt(f.lastlinedefined);
dumpChar(f.nups);
dumpChar(f.numparams);
dumpChar(f.is_vararg);
dumpChar(f.maxstacksize);
dumpCode(f);
dumpConstants(f);
dumpDebug(f);
}
void dumpHeader() throws IOException {
writer.write( LUAC_HEADER_SIGNATURE );
writer.write( LUAC_VERSION );
writer.write( LUAC_FORMAT );
writer.write( IS_LITTLE_ENDIAN? 1: 0 );
writer.write( SIZEOF_INT );
writer.write( SIZEOF_SIZET );
writer.write( SIZEOF_INSTRUCTION );
writer.write( SIZEOF_LUA_NUMBER );
writer.write( NUMBER_FORMAT );
}
/*
** dump Lua function as precompiled chunk
*/
public static int dump( LPrototype f, OutputStream w, boolean strip ) throws IOException {
DumpState D = new DumpState(w,strip);
D.dumpHeader();
D.dumpFunction(f,null);
return D.status;
}
/**
*
* @param f the function to dump
* @param w the output stream to dump to
* @param stripDebug true to strip debugging info, false otherwise
* @param numberFormat one of NUMBER_FORMAT_FLOATS_OR_DOUBLES, NUMBER_FORMAT_INTS_ONLY, NUMBER_FORMAT_NUM_PATCH_INT32
* @param littleendian true to use little endian for numbers, false for big endian
* @return 0 if dump succeeds
* @throws IOException
* @throws IllegalArgumentException if the number format it not supported
*/
public static int dump(LPrototype f, OutputStream w, boolean stripDebug, int numberFormat, boolean littleendian) throws IOException {
switch ( numberFormat ) {
case NUMBER_FORMAT_FLOATS_OR_DOUBLES:
case NUMBER_FORMAT_INTS_ONLY:
case NUMBER_FORMAT_NUM_PATCH_INT32:
break;
default:
throw new IllegalArgumentException("number format not supported: "+numberFormat);
}
DumpState D = new DumpState(w,stripDebug);
D.IS_LITTLE_ENDIAN = littleendian;
D.NUMBER_FORMAT = numberFormat;
D.SIZEOF_LUA_NUMBER = (numberFormat==NUMBER_FORMAT_INTS_ONLY? 4: 8);
D.dumpHeader();
D.dumpFunction(f,null);
return D.status;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.compiler;
class InstructionPtr {
final int[] code;
final int idx;
InstructionPtr(int[] code, int idx ) {
this.code = code;
this.idx = idx;
}
int get() {
return code[idx];
}
void set(int value) {
code[idx] = value;
}
}

View File

@@ -1,31 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.compiler;
public class IntPtr {
int i;
IntPtr() {
}
IntPtr(int value) {
this.i = value;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,223 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.compiler;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LString;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.LocVars;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LoadState.LuaCompiler;
/**
* Compiler for Lua
*/
public class LuaC extends Lua implements LuaCompiler {
/** Install the compiler so that LoadState will first
* try to use it when handed bytes that are
* not already a compiled lua chunk.
*/
public static void install() {
LoadState.compiler = new LuaC();
}
protected static void _assert(boolean b) {
if (!b)
throw new LuaErrorException("compiler assert failed");
}
public static final int MAXSTACK = 250;
static final int LUAI_MAXUPVALUES = 60;
static final int LUAI_MAXVARS = 200;
static final int NO_REG = MAXARG_A;
/* OpMode - basic instruction format */
static final int
iABC = 0,
iABx = 1,
iAsBx = 2;
/* OpArgMask */
static final int
OpArgN = 0, /* argument is not used */
OpArgU = 1, /* argument is used */
OpArgR = 2, /* argument is a register or a jump offset */
OpArgK = 3; /* argument is a constant or register/constant */
static void SET_OPCODE(InstructionPtr i,int o) {
i.set( ( i.get() & (MASK_NOT_OP)) | ((o << POS_OP) & MASK_OP) );
}
static void SETARG_A(InstructionPtr i,int u) {
i.set( ( i.get() & (MASK_NOT_A)) | ((u << POS_A) & MASK_A) );
}
static void SETARG_B(InstructionPtr i,int u) {
i.set( ( i.get() & (MASK_NOT_B)) | ((u << POS_B) & MASK_B) );
}
static void SETARG_C(InstructionPtr i,int u) {
i.set( ( i.get() & (MASK_NOT_C)) | ((u << POS_C) & MASK_C) );
}
static void SETARG_Bx(InstructionPtr i,int u) {
i.set( ( i.get() & (MASK_NOT_Bx)) | ((u << POS_Bx) & MASK_Bx) );
}
static void SETARG_sBx(InstructionPtr i,int u) {
SETARG_Bx( i, u + MAXARG_sBx );
}
static int CREATE_ABC(int o, int a, int b, int c) {
return ((o << POS_OP) & MASK_OP) |
((a << POS_A) & MASK_A) |
((b << POS_B) & MASK_B) |
((c << POS_C) & MASK_C) ;
}
static int CREATE_ABx(int o, int a, int bc) {
return ((o << POS_OP) & MASK_OP) |
((a << POS_A) & MASK_A) |
((bc << POS_Bx) & MASK_Bx) ;
}
// vector reallocation
static LValue[] realloc(LValue[] v, int n) {
LValue[] a = new LValue[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
static LPrototype[] realloc(LPrototype[] v, int n) {
LPrototype[] a = new LPrototype[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
static LString[] realloc(LString[] v, int n) {
LString[] a = new LString[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
static LocVars[] realloc(LocVars[] v, int n) {
LocVars[] a = new LocVars[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
static int[] realloc(int[] v, int n) {
int[] a = new int[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
static byte[] realloc(byte[] v, int n) {
byte[] a = new byte[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
public int nCcalls;
Hashtable strings = new Hashtable();
/** Utility method to invoke the compiler for an input stream
*/
public static LPrototype compile(InputStream is, String string) throws IOException {
return new LuaC().compile(is.read(), is, string);
}
/** Compile source bytes into a LPrototype.
*
* Try to compile the file, and return the Prototype on success,
* or throw LuaErrorException on syntax error or I/O Exception
*
* @param firstByte the first byte from the InputStream.
* This can be read by the client and tested to see if it is already a binary chunk.
* @param stream InputStream to read from.
* @param name Name of the chunk
* @return null if the first byte indicates it is a binary chunk,
* a LPrototype instance if it can be compiled,
* or an exception is thrown if there is an error.
* @throws IOException if an I/O exception occurs
* @throws LuaErrorException if there is a syntax error.
*/
public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException {
LuaC compiler = new LuaC();
return compiler.luaY_parser(firstByte, stream, name);
}
/** Parse the input */
private LPrototype luaY_parser(int firstByte, InputStream z, String name) {
LexState lexstate = new LexState(this, z);
FuncState funcstate = new FuncState();
// lexstate.buff = buff;
lexstate.setinput( this, firstByte, z, new LString(name) );
lexstate.open_func(funcstate);
/* main func. is always vararg */
funcstate.f.is_vararg = LuaC.VARARG_ISVARARG;
funcstate.f.source = new LString("@"+name);
lexstate.next(); /* read first token */
lexstate.chunk();
lexstate.check(LexState.TK_EOS);
lexstate.close_func();
LuaC._assert (funcstate.prev == null);
LuaC._assert (funcstate.f.nups == 0);
LuaC._assert (lexstate.fs == null);
return funcstate.f;
}
public LString newlstr(char[] chars, int offset, int len) {
return newTString( LString.valueOf( new String(chars,offset,len) ) );
}
public LString newTString(LString s) {
LString t = (LString) strings.get(s);
if ( t == null ) {
t = LString.newStringCopy(s);
strings.put( t, t );
}
return t;
}
public String pushfstring(String string) {
return string;
}
}

View File

@@ -1,504 +0,0 @@
/**
*
*/
package org.luaj.lib;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import org.luaj.vm.CallInfo;
import org.luaj.vm.LClosure;
import org.luaj.vm.LFunction;
import org.luaj.vm.LNil;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class BaseLib extends LFunction {
public static InputStream STDIN = null;
public static PrintStream STDOUT = System.out;
private static final String[] NAMES = {
"base",
"print",
"pairs",
"getmetatable",
"setmetatable",
"type",
"pcall",
"ipairs",
"error",
"assert",
"loadfile",
"tonumber",
"rawequal",
"rawget",
"rawset",
"getfenv",
"setfenv",
"select",
"collectgarbage",
"dofile",
"loadstring",
"load",
"tostring",
"unpack",
"xpcall",
"next",
"_inext", // not public
};
private static final int INSTALL = 0;
private static final int PRINT = 1;
private static final int PAIRS = 2;
private static final int GETMETATABLE = 3;
private static final int SETMETATABLE = 4;
private static final int TYPE = 5;
private static final int PCALL = 6;
private static final int IPAIRS = 7;
private static final int ERROR = 8;
private static final int ASSERT = 9;
private static final int LOADFILE = 10;
private static final int TONUMBER = 11;
private static final int RAWEQUAL = 12;
private static final int RAWGET = 13;
private static final int RAWSET = 14;
private static final int GETFENV = 15;
private static final int SETFENV = 16;
private static final int SELECT = 17;
private static final int COLLECTGARBAGE = 18;
private static final int DOFILE = 19;
private static final int LOADSTRING = 20;
private static final int LOAD = 21;
private static final int TOSTRING = 22;
private static final int UNPACK = 23;
private static final int XPCALL = 24;
private static final int NEXT = 25;
private static final int INEXT = 26;
private static LFunction next;
private static LFunction inext;
public static void install(LTable globals) {
for ( int i=1, n=NAMES.length; i<n; i++ )
globals.put( NAMES[i], new BaseLib(i) );
next = new BaseLib(NEXT);
inext = new BaseLib(INEXT);
globals.put("_G", globals);
globals.put("_VERSION", new LString(Lua._VERSION));
}
private int id;
private BaseLib( int id ) {
this.id = id;
}
public String toString() {
return NAMES[id]+"()";
}
private static void setResult( LuaState vm, LValue value ) {
vm.resettop();
vm.pushlvalue( value );
}
private static void setErrorResult( LuaState vm, String message ) {
vm.resettop();
vm.pushnil();
vm.pushstring( message );
}
public int invoke(LuaState vm) {
switch ( id ) {
case PRINT: {
int n = vm.gettop();
vm.getglobal("tostring");
for ( int i=1; i<=n; i++ ) {
vm.pushvalue(-1);
vm.pushvalue(i);
vm.call(1, 1);
if ( vm.type(-1) != Lua.LUA_TSTRING )
vm.error( "'tostring' must return a string to 'print'" );
if ( i > 1 )
STDOUT.print( "\t" );
STDOUT.print( vm.tostring(-1) );
vm.poplvalue();
}
STDOUT.println();
return 0;
}
case IPAIRS: {
LTable t = vm.checktable(1);
vm.pushfunction( inext );
vm.pushlvalue( t );
vm.pushinteger( 0 );
return 3;
}
case PAIRS: {
LTable t = vm.checktable(1);
vm.pushfunction( next );
vm.pushlvalue( t );
vm.pushnil();
return 3;
}
case INEXT: {
int i = vm.checkint(2) + 1;
LTable t = vm.checktable(1);
LValue v = t.get(i);
if ( !v.isNil() ) {
vm.pushinteger(i);
vm.pushlvalue(v);
return 2;
}
return 0;
}
case NEXT: {
LTable t = vm.checktable(1);
LValue k = vm.topointer(2);
vm.resettop();
t.next(vm,k,false);
return -1;
}
case GETMETATABLE: {
vm.checkany(1);
if ( ! vm.getmetatable(1) ) {
vm.pushnil();
return 1;
} else {
vm.getfield(-1,LValue.TM_METATABLE);
if ( vm.isnil(-1) )
vm.pop(1);
}
return 1;
}
case SETMETATABLE: {
LTable t = vm.checktable(1);
LValue v = vm.checkany(2);
vm.argcheck(v.isTable() || v.isNil(), 2, "table or nil expected");
t = t.luaSetMetatable(v);
vm.pushlvalue(t);
return 1;
}
case TYPE: {
LValue v = vm.checkany(1);
vm.pushlstring( v.luaGetTypeName() );
return 1;
}
case PCALL: {
vm.checkany(1);
int n = vm.gettop();
int s = vm.pcall( n-1, Lua.LUA_MULTRET );
if ( s == 0 ) { // success, results are on stack
vm.pushboolean( true );
vm.insert( 1 );
return -1;
} else { // error, error message is on the stack
vm.pushboolean( false );
vm.insert( -2 );
return 2;
}
}
case XPCALL: {
LValue errfun = vm.checkany(2);
vm.settop(1);
int s = vm.xpcall( 0, Lua.LUA_MULTRET, errfun );
if ( s == 0 ) { // success, results are on stack
vm.pushboolean( true );
vm.insert( 1 );
return -1;
} else { // error, error message is on the stack
vm.pushboolean( false );
vm.insert( 1 );
return 2;
}
}
case ERROR: {
vm.error(vm.optstring(1,null), vm.optint(2,-1));
return 0;
}
case ASSERT: {
if ( ! vm.toboolean(1) )
vm.error( vm.optstring(2,"assertion failed!") );
return -1;
}
case LOADFILE:
loadfile(vm, vm.optstring(1,null));
return -1;
case TONUMBER: {
int base = vm.optint(2, 10);
if (base == 10) { /* standard conversion */
vm.checkany(1);
LValue v = vm.tolnumber(1);
vm.pushlvalue(v);
return 1;
} else {
if ( base < 2 || base > 36 )
vm.argerror(2, "base out of range");
LString s = vm.checklstring(1);
vm.pushlvalue( s.luaToNumber(base) );
return 1;
}
}
case RAWEQUAL: {
LValue a = vm.checkany(1);
LValue b = vm.checkany(2);
vm.pushboolean(a == b);
return 1;
}
case RAWGET: {
LTable t = vm.checktable(1);
LValue k = vm.checkany(2);
vm.pushlvalue( t.get( k ) );
return 1;
}
case RAWSET: {
LTable t = vm.checktable(1);
LValue k = vm.checkany(2);
LValue v = vm.checkany(3);
t.put( k, v );
vm.pushlvalue(t);
return 1;
}
case GETFENV: {
LValue f = getfunc(vm, true);
vm.pushlvalue(f.luaGetEnv(vm._G));
return 1;
}
case SETFENV: {
LTable t = vm.checktable(2);
if ( vm.isnumber(1) && vm.tointeger(1) == 0 ) {
vm._G = t;
} else {
LValue f = getfunc(vm, false);
if ( (!(f instanceof LClosure)) || ! f.luaSetEnv(t) )
vm.error( "'setfenv' cannot change environment of given object" );
vm.pushlvalue(f);
return 1;
}
}
case SELECT: {
vm.checkany(1);
int n = vm.gettop();
if ( vm.isnumber(1) ) {
int index = vm.tolnumber(1).toJavaInt();
if ( index < 0 )
index += n;
if ( index <= 0 )
vm.argerror( 1, "index out of range" );
if ( index >= n )
return 0;
else {
return n-index;
}
} else if ( vm.checkstring(1).equals( "#" ) ) {
vm.pushnumber( n - 1 );
return 1;
} else {
vm.typerror(1,"expected number or '#'");
return 0;
}
}
case COLLECTGARBAGE: {
String s = vm.optstring(1, "collect");
int result = 0;
if ( "collect".equals(s) )
System.gc();
else if ( "count".equals(s) ) {
Runtime rt = Runtime.getRuntime();
long used = rt.totalMemory() - rt.freeMemory();
result = (int) (used >> 10);
} else {
vm.argerror(2,"gc op");
}
vm.pushnumber(result);
return 1;
}
case DOFILE:
dofile(vm);
return -1;
case LOADSTRING:
loadstring(vm, vm.checklstring(1), vm.optstring(2,"(string)"));
return -1;
case LOAD:
load(vm);
return -1;
case TOSTRING: {
LValue v = vm.checkany(1);
vm.pushlvalue( v.luaAsString() );
return 1;
}
case UNPACK: {
LTable list = vm.checktable(1);
int n = vm.gettop();
int i = vm.optint(2,1);
int j;
if ( n >= 3 ) {
j = vm.checkint(3);
} else {
j = list.luaLength();
}
vm.resettop();
vm.checkstack(j+1-i);
for ( int k=i; k<=j; k++ )
vm.pushlvalue(list.get(k));
return -1;
}
default:
LuaState.vmerror( "bad base id" );
return 0;
}
}
private static LValue getfunc (LuaState vm, boolean opt) {
if ( vm.isfunction(1) )
return vm.tofunction(1);
else {
int level = opt? vm.optint(1, 1): vm.checkint(1);
vm.argcheck(level >= 0, 1, "level must be non-negative");
vm.argcheck(level-1 <= vm.cc, 1, "invalid level");
CallInfo ci = vm.getStackFrame(level-1);
if ( ci == null || ci.closure == null )
return LNil.NIL;
return ci.closure;
}
}
public static void redirectOutput( OutputStream newStdOut ) {
STDOUT = new PrintStream( newStdOut );
}
public static void restoreStandardOutput() {
STDOUT = System.out;
}
// closes the input stream, provided its not null or System.in
private static void closeSafely(InputStream is) {
try {
if ( is != null && is != STDIN )
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// closes the output stream, provided its not null or STDOUT
private static void closeSafely(OutputStream os) {
try {
if ( os != null && os != STDOUT )
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// return true if loaded, false if error put onto the stack
/** Load a chunk from an input stream, leaving it on the stack if successful,
* then close the input stream if it is not STDIN
*
* @param vm LuaState to load into
* @param is input stream to load from
* @return true if loaded and only item on stack, false if nil+error put onto stack
*/
static boolean loadis(LuaState vm, InputStream is, String chunkname ) {
try {
vm.resettop();
if ( 0 != vm.load(is, chunkname) ) {
setErrorResult( vm, "cannot load "+chunkname+": "+vm.topointer(-1) );
return false;
} else {
return true;
}
} finally {
closeSafely( is );
}
}
/** Load a file into a chunk given a filename, leaving it on the stack if successful
*
* @param vm LuaState to load into
* @param fileName file to load, or null to use STDIN
* @return true if loaded and only item on stack, false if nil+error put onto stack
*/
private static boolean loadfile( LuaState vm, String fileName ) {
InputStream is;
String script;
if ( fileName != null ) {
script = fileName;
is = Platform.getInstance().openFile(fileName);
if ( is == null ) {
setErrorResult( vm, "cannot open "+fileName+": No such file or directory" );
return false;
}
} else {
is = STDIN != null? STDIN: new ByteArrayInputStream(new byte[0]);
script = "-";
}
// use vm to load the script
return loadis( vm, is, script );
}
// if load succeeds, return 0 for success, 1 for error (as per lua spec)
private void dofile( LuaState vm ) {
String filename = vm.optstring(1,null);
if ( loadfile( vm, filename ) ) {
vm.call(0, 0);
} else {
vm.error( vm.tostring(-1) );
}
}
// return true if loaded, false if error put onto stack
private boolean loadstring(LuaState vm, LString string, String chunkname) {
return loadis( vm, string.toInputStream(), chunkname );
}
// return true if loaded, false if error put onto stack
private boolean load(LuaState vm) {
LFunction chunkPartLoader = vm.checkfunction(2);
String chunkname = vm.optstring(3,"=(load)");
// load all the parts
LClosure c = (LClosure) chunkPartLoader;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
while ( true ) {
setResult(vm,c);
if ( 0 != vm.pcall(0, 1) ) {
setErrorResult(vm, vm.tostring(2));
return false;
}
LValue v = vm.topointer(2);
if ( v.isNil() )
break;
LString s = v.luaAsString();
s.write(baos, 0, s.length());
}
// load the chunk
return loadis( vm, new ByteArrayInputStream( baos.toByteArray() ), chunkname );
} catch (IOException ioe) {
setErrorResult(vm, ioe.getMessage());
return false;
} finally {
closeSafely( baos );
}
}
}

View File

@@ -1,141 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib;
import org.luaj.vm.LFunction;
import org.luaj.vm.LTable;
import org.luaj.vm.LThread;
import org.luaj.vm.LuaState;
public class CoroutineLib extends LFunction {
private static final String[] NAMES = {
"install",
"create",
"resume",
"running",
"status",
"wrap",
"yield",
"wrapped"
};
private static final int INSTALL = 0;
private static final int CREATE = 1;
private static final int RESUME = 2;
private static final int RUNNING = 3;
private static final int STATUS = 4;
private static final int WRAP = 5;
private static final int YIELD = 6;
private static final int WRAPPED = 7;
public static void install( LTable globals ) {
LTable lib = new LTable(0,6);
for ( int i=1; i<=YIELD; i++ )
lib.put(NAMES[i], new CoroutineLib(i));
globals.put("coroutine",lib);
PackageLib.setIsLoaded("coroutine", lib);
}
private final int id;
private final LThread thread;
public CoroutineLib() {
this.id = 0;
this.thread = null;
}
private CoroutineLib( int id ) {
this.id = id;
this.thread = null;
}
public String toString() {
return NAMES[id]+"()";
}
private CoroutineLib( int id, LThread thread ) {
this.id = id;
this.thread = thread;
}
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL: {
install(vm._G);
return 0;
}
case CREATE: {
LFunction c = vm.checkfunction(1);
vm.pushlvalue( new LThread( c, c.luaGetEnv(vm._G) ) );
return 1;
}
case RESUME: {
LThread t = vm.checkthread(1);
t.resumeFrom( vm, vm.gettop()-1 );
return -1;
}
case RUNNING: {
LThread r = LThread.getRunning();
if ( r != null ) {
vm.pushlvalue( r );
} else {
vm.pushnil();
}
return 1;
}
case STATUS: {
vm.pushstring( vm.checkthread(1).getStatus() );
return 1;
}
case WRAP: {
LFunction c = vm.checkfunction(1);
vm.pushlvalue( new CoroutineLib(WRAPPED,new LThread(c, c.luaGetEnv(vm._G))) );
return 1;
}
case YIELD: {
LThread r = LThread.getRunning();
if ( r == null ) {
vm.error("main thread can't yield");
return 0;
}
r.yield();
return -1;
}
case WRAPPED: {
LThread t = this.thread;
t.resumeFrom( vm, vm.gettop() );
if ( vm.toboolean(1) ) {
vm.remove(1);
return -1;
} else {
vm.error( vm.tostring(2) );
return 0;
}
}
default: {
LuaState.vmerror( "bad coroutine id" );
return 0;
}
}
}
}

View File

@@ -1,824 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 LuaJ. 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.lib;
import org.luaj.vm.CallInfo;
import org.luaj.vm.LBoolean;
import org.luaj.vm.LClosure;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
import org.luaj.vm.UpVal;
public class DebugLib extends LFunction {
private static final String[] NAMES = {
"debuglib",
"debug",
"getfenv",
"gethook",
"getinfo",
"getlocal",
"getmetatable",
"getregistry",
"getupvalue",
"setfenv",
"sethook",
"setlocal",
"setmetatable",
"setupvalue",
"traceback",
};
private static final int INSTALL = 0;
private static final int DEBUG = 1;
private static final int GETFENV = 2;
private static final int GETHOOK = 3;
private static final int GETINFO = 4;
private static final int GETLOCAL = 5;
private static final int GETMETATABLE = 6;
private static final int GETREGISTRY = 7;
private static final int GETUPVALUE = 8;
private static final int SETFENV = 9;
private static final int SETHOOK = 10;
private static final int SETLOCAL = 11;
private static final int SETMETATABLE = 12;
private static final int SETUPVALUE = 13;
private static final int TRACEBACK = 14;
/* maximum stack for a Lua function */
private static final int MAXSTACK = 250;
private static final LString LUA = new LString("Lua");
private static final LString JAVA = new LString("Java");
private static final LString JAVASRC = new LString("[Java]");
private static final LString QMARK = new LString("?");
private static final LString GLOBAL = new LString("global");
private static final LString LOCAL = new LString("local");
private static final LString METHOD = new LString("method");
private static final LString UPVALUE = new LString("upvalue");
private static final LString FIELD = new LString("field");
private static final LString NOSTRING = new LString("");
public static void install( LuaState vm ) {
LTable debug = new LTable();
for (int i = 1; i < NAMES.length; i++)
debug.put(NAMES[i], new DebugLib(i));
vm._G.put("debug", debug);
PackageLib.setIsLoaded("debug", debug);
}
private final int id;
public DebugLib() {
this.id = INSTALL;
}
private DebugLib( int id ) {
this.id = id;
}
public String toString() {
return NAMES[id]+"()";
}
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL:
install(vm);
return 0;
case DEBUG:
return debug(vm);
case GETFENV:
return getfenv(vm);
case GETHOOK:
return gethook(vm);
case GETINFO:
return getinfo(vm);
case GETLOCAL:
return getlocal(vm);
case GETMETATABLE:
return getmetatable(vm);
case GETREGISTRY:
return getregistry(vm);
case GETUPVALUE:
return getupvalue(vm);
case SETFENV:
return setfenv(vm);
case SETHOOK:
return sethook(vm);
case SETLOCAL:
return setlocal(vm);
case SETMETATABLE:
return setmetatable(vm);
case SETUPVALUE:
return setupvalue(vm);
case TRACEBACK:
return traceback(vm);
default:
LuaState.vmerror( "bad package id" );
return 0;
}
}
// j2se subclass may wish to override and provide actual console here.
// j2me platform has not System.in to provide console.
protected int debug(LuaState vm) {
return 0;
}
protected int gethook(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
LValue hook = threadVm.gethook();
int mask = threadVm.gethookmask();
int count = threadVm.gethookcount();
vm.pushlvalue(hook!=null? hook: LNil.NIL);
vm.pushstring(""
+((mask&LuaState.LUA_MASKCALL)!=0? "c": "")
+((mask&LuaState.LUA_MASKRET) !=0? "r": "")
+((mask&LuaState.LUA_MASKLINE)!=0? "l": ""));
vm.pushinteger(count);
return 3;
}
protected LuaState optthreadvm(LuaState vm, int index) {
if ( ! vm.isthread(index) )
return vm;
LuaState threadVm = vm.checkthread(index).vm;
vm.remove(index);
return threadVm;
}
protected int sethook(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
LFunction func = vm.isnoneornil(1)? null: vm.checkfunction(1);
String str = vm.optstring(2,"");
int count = vm.optint(3,0);
int mask = 0;
for ( int i=0; i<str.length(); i++ )
switch ( str.charAt(i) ) {
case 'c': mask |= LuaState.LUA_MASKCALL; break;
case 'l': mask |= LuaState.LUA_MASKLINE; break;
case 'r': mask |= LuaState.LUA_MASKRET; break;
}
threadVm.sethook(func, mask, count);
return 0;
}
protected int getfenv(LuaState vm) {
LValue object = vm.topointer(1);
LValue env = object.luaGetEnv(null);
vm.pushlvalue(env!=null? env: LNil.NIL);
return 1;
}
protected int setfenv(LuaState vm) {
LValue object = vm.topointer(1);
LTable table = vm.checktable(2);
object.luaSetEnv(table);
vm.settop(1);
return 1;
}
protected int getinfo(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
String what = vm.optstring(2, "nSluf");
// find the stack info
StackInfo si;
if ( vm.isnumber(1) ) {
int level = vm.tointeger(1);
si = getstackinfo(threadVm, level, 1)[0];
if ( si == null ) {
return 0;
}
} else {
LFunction func = vm.checkfunction(1);
si = findstackinfo(threadVm, func);
}
// look up info
LTable info = new LTable();
vm.pushlvalue(info);
LClosure c = si.closure();
for (int i = 0, n = what.length(); i < n; i++) {
switch (what.charAt(i)) {
case 'S': {
if ( c != null ) {
LPrototype p = c.p;
info.put("what", LUA);
info.put("source", p.source);
info.put("short_src", new LString(p.sourceshort()));
info.put("linedefined", p.linedefined);
info.put("lastlinedefined", p.lastlinedefined);
} else {
info.put("what", JAVA);
info.put("source", (si.func!=null? new LString("[Java] "+si.func.toString()): JAVASRC));
info.put("short_src", (si.func!=null? new LString(si.func.toString()): JAVASRC));
info.put("linedefined", -1);
info.put("lastlinedefined", -1);
}
break;
}
case 'l': {
int line = si.currentline();
info.put( "currentline", line );
break;
}
case 'u': {
info.put("nups", (c!=null? c.p.nups: 0));
break;
}
case 'n': {
LString[] kind = si.getfunckind();
info.put("name", kind!=null? kind[0]: QMARK);
info.put("namewhat", kind!=null? kind[1]: NOSTRING);
break;
}
case 'f': {
info.put( "func", si.func );
break;
}
case 'L': {
LTable lines = new LTable();
info.put("activelines", lines);
if ( si.luainfo != null ) {
int line = si.luainfo.currentline();
if ( line >= 0 )
lines.put(1, LInteger.valueOf(line));
}
break;
}
}
}
return 1;
}
protected int getlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
int level = vm.checkint(1);
int local = vm.checkint(2);
StackInfo si = getstackinfo(threadVm, level, 1)[0];
CallInfo ci = (si!=null? si.luainfo: null);
LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.currentpc()): null);
if ( name != null ) {
LValue value = threadVm.stack[ci.base+(local-1)];
vm.pushlvalue( name );
vm.pushlvalue( value );
return 2;
} else {
vm.pushnil();
return 1;
}
}
protected int setlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
int level = vm.checkint(1);
int local = vm.checkint(2);
LValue value = vm.topointer(3);
StackInfo si = getstackinfo(threadVm, level, 1)[0];
CallInfo ci = (si!=null? si.luainfo: null);
LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.currentpc()): null);
if ( name != null ) {
threadVm.stack[ci.base+(local-1)] = value;
vm.pushlvalue( name );
} else {
vm.pushnil();
}
return 1;
}
protected int getmetatable(LuaState vm) {
LValue object = vm.topointer(1);
LValue mt = object.luaGetMetatable();
if ( mt != null )
vm.pushlvalue( object.luaGetMetatable() );
else
vm.pushnil();
return 1;
}
protected int setmetatable(LuaState vm) {
LValue object = vm.topointer(1);
try {
if ( ! vm.isnoneornil(2) )
object.luaSetMetatable(vm.checktable(3));
else
object.luaSetMetatable(null);
vm.pushboolean(true);
return 1;
} catch ( LuaErrorException e ) {
vm.pushboolean(false);
vm.pushstring(e.toString());
return 2;
}
}
protected int getregistry(LuaState vm) {
vm.pushlvalue( new LTable() );
return 1;
}
private static LString findupvalue(LClosure c, int up) {
if ( c.upVals != null && up > 0 && up <= c.upVals.length ) {
if ( c.p.upvalues != null && up <= c.p.upvalues.length )
return c.p.upvalues[up-1];
else
return new LString( "."+up+"" );
}
return null;
}
protected int getupvalue(LuaState vm) {
LFunction func = vm.checkfunction(1);
int up = vm.checkint(2);
vm.resettop();
if ( func.isClosure() ) {
LClosure c = (LClosure) func;
LString name = findupvalue(c, up);
if ( name != null ) {
vm.pushlstring(name);
vm.pushlvalue(c.upVals[up-1].getValue());
return 2;
}
}
vm.pushnil();
return 1;
}
protected int setupvalue(LuaState vm) {
LFunction func = vm.checkfunction(1);
int up = vm.checkint(2);
LValue value = vm.topointer(3);
vm.resettop();
if ( func instanceof LClosure ) {
LClosure c = (LClosure) func;
LString name = findupvalue(c, up);
if ( name != null ) {
c.upVals[up-1].setValue(value);
vm.pushlstring(name);
return 1;
}
}
vm.pushnil();
return 1;
}
protected int traceback(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
String message = "stack traceback:\n";
int level = vm.optint(2,1);
if ( ! vm.isnoneornil(1) )
message = vm.checkstring(1)+"\n";
String tb = DebugLib.traceback(threadVm, level);
vm.pushstring(message+tb);
return 1;
}
// =================== public utilities ====================
/**
* @param callinfo the CallInfo to inspect
* @param up the 1-based index of the local
* @return { name, value } or null if not found.
*/
public static LValue[] getlocal(LuaState vm, CallInfo ci, int local) {
LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.currentpc()): null);
if ( name != null ) {
LValue value = vm.stack[ci.base+(local-1)];
return new LValue[] { name, value };
} else {
return null;
}
}
/**
* @param c the LClosure to inspect
* @param up the 1-based index of the upvalue
* @return { name, value, isclosed } or null if not found.
*/
public static LValue[] getupvalue(LClosure c, int up) {
LString name = findupvalue(c, up);
if ( name != null ) {
UpVal u = c.upVals[up-1];
LValue value = u.getValue();
boolean isclosed = u.isClosed();
return new LValue[] { name, value, LBoolean.valueOf(isclosed) };
}
return null;
}
/**
* Get a traceback as a string for an arbitrary LuaState
*/
public static String traceback(LuaState vm, int level) {
StackInfo[] s = getstackinfo(vm, level, 10);
StringBuffer sb = new StringBuffer();
for ( int i=0; i<s.length; i++ ) {
StackInfo si = s[i];
if ( si != null ) {
sb.append( "\n\t" );
sb.append( si.sourceline() );
sb.append( ": in " );
sb.append( si.tracename() );
}
}
return sb.toString();
}
// =======================================================
private static void lua_assert(boolean x) {
if (!x) throw new RuntimeException("lua_assert failed");
}
private static class StackInfo {
private LuaState vm;
private CallInfo caller; // or null if first item on stack
private int stackpos; // offset into stack
private CallInfo luainfo; // or null if a java function
private LValue func; // or null if a lua call
public StackInfo(LuaState vm, CallInfo caller, int stackpos, CallInfo luainfo, LFunction func) {
this.vm = vm;
this.caller = caller;
this.stackpos = stackpos;
this.luainfo = luainfo;
this.func = func!=null? func: luainfo!=null? luainfo.closure: null;
}
public LClosure closure() {
return luainfo!=null? luainfo.closure:
func!=null&&func.isClosure()? (LClosure)func:
null;
}
public String sourceline() {
if ( luainfo != null ) {
String s = luainfo.closure.p.source.toJavaString();
int line = currentline();
return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line;
} else {
return "[Java]";
}
}
public LString[] getfunckind() {
return (caller!=null && stackpos>=0? getobjname(vm, caller, stackpos): null);
}
public int currentline() {
return luainfo!=null? luainfo.currentline(): -1;
}
public String tracename() {
if ( caller == null )
return "main chunk";
if ( func != null )
return func.toString();
LString[] kind = getfunckind();
if ( kind == null )
return "function ?";
return "function "+kind[0].toJavaString();
}
}
/**
* @param level first level to report
* @return array StackInfo with countlevels items, some may be null!
*/
private static StackInfo[] getstackinfo(LuaState vm, int level, int countlevels) {
StackInfo[] si = new StackInfo[countlevels];
int i = 0;
LClosure prevclosure = null;
for (int j=vm.cc; j>=0; --j) {
CallInfo ci = vm.calls[j];
LFunction f = ci.currentfunc(vm);
// java, or tailcall?
if ( f != null && (! f.isClosure() || f!=prevclosure) ) {
if ( (level--) <= 0 ) {
si[i++] = new StackInfo( vm, ci, ci.currentfunca(vm), null, f);
if ( i >= countlevels )
return si;
}
}
// add the lua closure
if ( (level--) <= 0 ) {
if (j>0 && vm.calls[j-1].currentfunc(vm) == ci.closure) {
CallInfo caller = vm.calls[j-1];
int callera = caller.currentfunca(vm);
si[i++] = new StackInfo( vm, caller, callera, ci, ci.closure);
} else {
si[i++] = new StackInfo( vm, null, -1, ci, ci.closure);
}
if ( i >= countlevels )
return si;
}
prevclosure = ci.closure;
}
return si;
}
// look up a function in the stack, if it exists
private static StackInfo findstackinfo(LuaState vm, LFunction func) {
for (int j=vm.cc; j>=0; --j) {
CallInfo ci = vm.calls[j];
int instr = ci.closure.p.code[ci.currentpc()];
if ( Lua.GET_OPCODE(instr) == Lua.OP_CALL ) {
int a = Lua.GETARG_A(instr);
if ( func == vm.stack[ci.base + a] )
return new StackInfo(vm, ci, a, null, func);
if ( func == ci.closure )
return new StackInfo(vm, (j>0? vm.calls[j-1]: null), 0, ci, null);
}
}
return new StackInfo(vm, null, -1, null, func);
}
// return LString[] { name, namewhat } if found, null if not
private static LString[] getobjname(LuaState L, CallInfo ci, int stackpos) {
LString name;
if (ci.isLua()) { /* a Lua function? */
LPrototype p = ci.closure.p;
int pc = (ci.pc > 0 ? ci.pc - 1 : 0); // currentpc(L, ci);
int i;// Instruction i;
name = p.getlocalname(stackpos + 1, pc);
if (name != null) /* is a local? */
return new LString[] { name, LOCAL };
i = symbexec(p, pc, stackpos); /* try symbolic execution */
lua_assert(pc != -1);
switch (Lua.GET_OPCODE(i)) {
case Lua.OP_GETGLOBAL: {
int g = Lua.GETARG_Bx(i); /* global index */
// lua_assert(p.k[g].isString());
return new LString[] { p.k[g].luaAsString(), GLOBAL };
}
case Lua.OP_MOVE: {
int a = Lua.GETARG_A(i);
int b = Lua.GETARG_B(i); /* move from `b' to `a' */
if (b < a)
return getobjname(L, ci, b); /* get name for `b' */
break;
}
case Lua.OP_GETTABLE: {
int k = Lua.GETARG_C(i); /* key index */
name = kname(p, k);
return new LString[] { name, FIELD };
}
case Lua.OP_GETUPVAL: {
int u = Lua.GETARG_B(i); /* upvalue index */
name = u < p.upvalues.length ? p.upvalues[u] : QMARK;
return new LString[] { name, UPVALUE };
}
case Lua.OP_SELF: {
int k = Lua.GETARG_C(i); /* key index */
name = kname(p, k);
return new LString[] { name, METHOD };
}
default:
break;
}
}
return null; /* no useful name found */
}
private static LString kname(LPrototype p, int c) {
if (Lua.ISK(c) && p.k[Lua.INDEXK(c)].isString())
return p.k[Lua.INDEXK(c)].luaAsString();
else
return QMARK;
}
private static boolean checkreg(LPrototype pt,int reg) {
return (reg < pt.maxstacksize);
}
private static boolean precheck(LPrototype pt) {
if (!(pt.maxstacksize <= MAXSTACK)) return false;
lua_assert(pt.numparams + (pt.is_vararg & Lua.VARARG_HASARG) <= pt.maxstacksize);
lua_assert((pt.is_vararg & Lua.VARARG_NEEDSARG) == 0
|| (pt.is_vararg & Lua.VARARG_HASARG) != 0);
if (!(pt.upvalues.length <= pt.nups)) return false;
if (!(pt.lineinfo.length == pt.code.length || pt.lineinfo.length == 0)) return false;
if (!(Lua.GET_OPCODE(pt.code[pt.code.length - 1]) == Lua.OP_RETURN)) return false;
return true;
}
private static boolean checkopenop(LPrototype pt,int pc) {
int i = pt.code[(pc)+1];
switch (Lua.GET_OPCODE(i)) {
case Lua.OP_CALL:
case Lua.OP_TAILCALL:
case Lua.OP_RETURN:
case Lua.OP_SETLIST: {
if (!(Lua.GETARG_B(i) == 0)) return false;
return true;
}
default:
return false; /* invalid instruction after an open call */
}
}
//static int checkArgMode (LPrototype pt, int r, enum OpArgMask mode) {
private static boolean checkArgMode (LPrototype pt, int r, int mode) {
switch (mode) {
case Lua.OpArgN: if (!(r == 0)) return false; break;
case Lua.OpArgU: break;
case Lua.OpArgR: checkreg(pt, r); break;
case Lua.OpArgK:
if (!(Lua.ISK(r) ? Lua.INDEXK(r) < pt.k.length : r < pt.maxstacksize)) return false;
break;
}
return true;
}
// return last instruction, or 0 if error
private static int symbexec(LPrototype pt, int lastpc, int reg) {
int pc;
int last; /* stores position of last instruction that changed `reg' */
last = pt.code.length - 1; /*
* points to final return (a `neutral'
* instruction)
*/
if (!(precheck(pt))) return 0;
for (pc = 0; pc < lastpc; pc++) {
int i = pt.code[pc];
int op = Lua.GET_OPCODE(i);
int a = Lua.GETARG_A(i);
int b = 0;
int c = 0;
if (!(op < Lua.NUM_OPCODES)) return 0;
if (!checkreg(pt, a)) return 0;
switch (Lua.getOpMode(op)) {
case Lua.iABC: {
b = Lua.GETARG_B(i);
c = Lua.GETARG_C(i);
if (!(checkArgMode(pt, b, Lua.getBMode(op)))) return 0;
if (!(checkArgMode(pt, c, Lua.getCMode(op)))) return 0;
break;
}
case Lua.iABx: {
b = Lua.GETARG_Bx(i);
if (Lua.getBMode(op) == Lua.OpArgK)
if (!(b < pt.k.length)) return 0;
break;
}
case Lua.iAsBx: {
b = Lua.GETARG_sBx(i);
if (Lua.getBMode(op) == Lua.OpArgR) {
int dest = pc + 1 + b;
if (!(0 <= dest && dest < pt.code.length)) return 0;
if (dest > 0) {
/* cannot jump to a setlist count */
int d = pt.code[dest - 1];
if ((Lua.GET_OPCODE(d) == Lua.OP_SETLIST && Lua.GETARG_C(d) == 0)) return 0;
}
}
break;
}
}
if (Lua.testAMode(op)) {
if (a == reg)
last = pc; /* change register `a' */
}
if (Lua.testTMode(op)) {
if (!(pc + 2 < pt.code.length)) return 0; /* check skip */
if (!(Lua.GET_OPCODE(pt.code[pc + 1]) == Lua.OP_JMP)) return 0;
}
switch (op) {
case Lua.OP_LOADBOOL: {
if (!(c == 0 || pc + 2 < pt.code.length)) return 0; /* check its jump */
break;
}
case Lua.OP_LOADNIL: {
if (a <= reg && reg <= b)
last = pc; /* set registers from `a' to `b' */
break;
}
case Lua.OP_GETUPVAL:
case Lua.OP_SETUPVAL: {
if (!(b < pt.nups)) return 0;
break;
}
case Lua.OP_GETGLOBAL:
case Lua.OP_SETGLOBAL: {
if (!(pt.k[b].isString())) return 0;
break;
}
case Lua.OP_SELF: {
if (!checkreg(pt, a + 1)) return 0;
if (reg == a + 1)
last = pc;
break;
}
case Lua.OP_CONCAT: {
if (!(b < c)) return 0; /* at least two operands */
break;
}
case Lua.OP_TFORLOOP: {
if (!(c >= 1)) return 0; /* at least one result (control variable) */
if (!checkreg(pt, a + 2 + c)) return 0; /* space for results */
if (reg >= a + 2)
last = pc; /* affect all regs above its base */
break;
}
case Lua.OP_FORLOOP:
case Lua.OP_FORPREP:
if (!checkreg(pt, a + 3)) return 0;
/* go through */
case Lua.OP_JMP: {
int dest = pc + 1 + b;
/* not full check and jump is forward and do not skip `lastpc'? */
if (reg != Lua.NO_REG && pc < dest && dest <= lastpc)
pc += b; /* do the jump */
break;
}
case Lua.OP_CALL:
case Lua.OP_TAILCALL: {
if (b != 0) {
if (!checkreg(pt, a + b - 1)) return 0;
}
c--; /* c = num. returns */
if (c == Lua.LUA_MULTRET) {
if (!(checkopenop(pt, pc))) return 0;
} else if (c != 0)
if (!checkreg(pt, a + c - 1)) return 0;
if (reg >= a)
last = pc; /* affect all registers above base */
break;
}
case Lua.OP_RETURN: {
b--; /* b = num. returns */
if (b > 0)
if (!checkreg(pt, a + b - 1)) return 0;
break;
}
case Lua.OP_SETLIST: {
if (b > 0)
if (!checkreg(pt, a + b)) return 0;
if (c == 0)
pc++;
break;
}
case Lua.OP_CLOSURE: {
int nup, j;
if (!(b < pt.p.length)) return 0;
nup = pt.p[b].nups;
if (!(pc + nup < pt.code.length)) return 0;
for (j = 1; j <= nup; j++) {
int op1 = Lua.GET_OPCODE(pt.code[pc + j]);
if (!(op1 == Lua.OP_GETUPVAL || op1 == Lua.OP_MOVE)) return 0;
}
if (reg != Lua.NO_REG) /* tracing? */
pc += nup; /* do not 'execute' these pseudo-instructions */
break;
}
case Lua.OP_VARARG: {
if (!((pt.is_vararg & Lua.VARARG_ISVARARG) != 0
&& (pt.is_vararg & Lua.VARARG_NEEDSARG) == 0)) return 0;
b--;
if (b == Lua.LUA_MULTRET)
if (!(checkopenop(pt, pc))) return 0;
if (!checkreg(pt, a + b - 1)) return 0;
break;
}
default:
break;
}
}
return pt.code[last];
}
}

View File

@@ -1,513 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.lib;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import org.luaj.vm.LFunction;
import org.luaj.vm.LNil;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
abstract
public class IoLib extends LFunction {
protected interface File {
public void write( LString string ) throws IOException;
public void flush() throws IOException;
public boolean isstdfile();
public void close() throws IOException;
public boolean isclosed();
// returns new position
public int seek(String option, int bytecount) throws IOException;
public void setvbuf(String mode, int size);
// get length remaining to read
public int remaining() throws IOException;
// peek ahead one character
public int peek() throws IOException, EOFException;
// return char if read, -1 if eof, throw IOException on other exception
public int read() throws IOException, EOFException;
// return number of bytes read if positive, false if eof, throw IOException on other exception
public int read(byte[] bytes, int offset, int length) throws IOException;
}
/**
* Create a function stub with a specific index (factory method)
*/
abstract protected IoLib newInstance( int index );
/**
* Wrap the standard input.
* @return File
* @throws IOException
*/
abstract protected File wrapStdin() throws IOException;
/**
* Wrap the standard output.
* @return File
* @throws IOException
*/
abstract protected File wrapStdout() throws IOException;
/**
* Open a file in a particular mode.
* @param filename
* @param mode
* @return File object if successful
* @throws IOException if could not be opened
*/
abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException;
/**
* Open a temporary file.
* @return File object if successful
* @throws IOException if could not be opened
*/
abstract protected File tmpFile() throws IOException;
/**
* Start a new process and return a file for input or output
* @param prog the program to execute
* @param mode "r" to read, "w" to write
* @return File to read to or write from
* @throws IOException if an i/o exception occurs
*/
abstract protected File openProgram(String prog, String mode) throws IOException;
public static final String[] NAMES = {
"io",
"__index",
"close",
"flush",
"input",
"lines",
"open",
"output",
"popen",
"read",
"tmpfile",
"type",
"write",
"close",
"flush",
"lines",
"read",
"seek",
"setvbuf",
"write",
};
private static final int INSTALL = 0;
private static final int IO_INDEX = 1;
private static final int IO_CLOSE = 2;
private static final int IO_FLUSH = 3;
private static final int IO_INPUT = 4;
private static final int IO_LINES = 5;
private static final int IO_OPEN = 6;
private static final int IO_OUTPUT = 7;
private static final int IO_POPEN = 8;
private static final int IO_READ = 9;
private static final int IO_TMPFILE = 10;
private static final int IO_TYPE = 11;
private static final int IO_WRITE = 12;
private static final int FILE_CLOSE = 13;
private static final int FILE_FLUSH = 14;
private static final int FILE_LINES = 15;
private static final int FILE_READ = 16;
private static final int FILE_SEEK = 17;
private static final int FILE_SETVBUF = 18;
private static final int FILE_WRITE = 19;
private static File INPUT = null;
private static File OUTPUT = null;
private static File ERROR = null;
private static LTable FILE_MT;
protected void initialize( LTable globals ) {
LTable io = new LTable();
for ( int i=IO_INDEX; i<=IO_WRITE; i++ )
io.put(NAMES[i], newInstance(i));
io.luaSetMetatable(io);
FILE_MT = new LTable();
for ( int i=FILE_CLOSE; i<=FILE_WRITE; i++ )
FILE_MT.put(NAMES[i], newInstance(i));
FILE_MT.put("__index", FILE_MT);
INPUT = null;
OUTPUT = null;
ERROR = null;
globals.put( "io", io );
PackageLib.setIsLoaded("io", io);
}
private final int id;
protected IoLib() {
id = 0;
}
protected IoLib( int id ) {
this.id = id;
}
public LString luaAsString() {
return new LString(toJavaString());
}
public String toJavaString() {
return "io."+toString();
}
public String toString() {
return NAMES[id]+"()";
}
private File input(LuaState vm) {
return INPUT!=null? INPUT: (INPUT=ioopenfile(vm,"-","r"));
}
private File output(LuaState vm) {
return OUTPUT!=null? OUTPUT: (OUTPUT=ioopenfile(vm,"-","w"));
}
private File error(LuaState vm) {
return ERROR!=null? ERROR: (ERROR=ioopenfile(vm,"-","w"));
}
public LValue __index(LuaState vm, LValue table, LValue key) {
String k = key.toJavaString();
if ( "stdout".equals(k) )
return touserdata(output(vm));
else if ( "stdin".equals(k) )
return touserdata(input(vm));
else if ( "stderr".equals(k) )
return touserdata(error(vm));
else
return LNil.NIL;
}
public int invoke( LuaState vm ) {
File f;
int n;
try {
switch ( id ) {
/* Load the table library dynamically */
case INSTALL:
initialize(vm._G);
return 0;
case IO_CLOSE:
f = vm.isnoneornil(1)?
output(vm):
checkfile(vm,1);
checkopen(vm, f);
ioclose(vm,f);
break;
case IO_FLUSH:
checkopen(vm,output(vm));
OUTPUT.flush();
vm.pushboolean(true);
return 1;
case IO_INPUT:
INPUT = vm.isnoneornil(1)?
input(vm):
vm.isstring(1)?
ioopenfile(vm,vm.checkstring(1),"r"):
checkfile(vm,1);
setresult(vm, INPUT);
break;
case IO_LINES:
INPUT = vm.isnoneornil(1)?
input(vm):
ioopenfile(vm,vm.checkstring(1),"r");
checkopen(vm, INPUT);
vm.pushlvalue(lines(vm,INPUT));
return 1;
case IO_OPEN:
setresult(vm, rawopenfile(vm.checkstring(1), vm.optstring(2,"r")));
break;
case IO_OUTPUT:
OUTPUT = vm.isnoneornil(1)?
output(vm):
vm.isstring(1)?
ioopenfile(vm,vm.checkstring(1),"w"):
checkfile(vm,1);
setresult(vm, OUTPUT);
break;
case IO_POPEN:
setresult(vm, openProgram(vm.checkstring(1),vm.optstring(2, "r")));
break;
case IO_READ:
checkopen(vm, INPUT);
ioread( vm, INPUT );
break;
case IO_TMPFILE:
setresult(vm, tmpFile());
break;
case IO_TYPE:
f = optfile(vm,1);
if ( f != null )
vm.pushstring(f.isclosed()? "closed file": "file");
else
vm.pushnil();
return 1;
case IO_WRITE:
checkopen(vm, output(vm));
iowrite( vm, OUTPUT );
break;
case FILE_CLOSE:
f = checkfile(vm,1);
ioclose(vm, f);
break;
case FILE_FLUSH:
f = checkfile(vm,1);
f.flush();
vm.pushboolean(true);
return 1;
case FILE_LINES:
f = checkfile(vm,1);
vm.pushlvalue(lines(vm,f));
return 1;
case FILE_READ:
f = checkfile(vm,1);
vm.remove(1);
ioread(vm, f);
break;
case FILE_SEEK:
f = checkfile(vm,1);
vm.remove(1);
n = f.seek(vm.optstring(1,"cur"),vm.optint(2, 0));
vm.pushinteger(n);
return 1;
case FILE_SETVBUF:
f = checkfile(vm,1);
vm.remove(1);
f.setvbuf(vm.checkstring(1),vm.optint(2, 1024));
vm.pushboolean(true);
return 1;
case FILE_WRITE:
f = checkfile(vm,1);
vm.remove(1);
iowrite( vm, f );
break;
default:
LuaState.vmerror( "bad io id" );
}
} catch ( IOException ioe ) {
seterrorresult(vm,ioe);
}
return -1;
}
private static void ioclose(LuaState vm, File f) throws IOException {
if ( f.isstdfile() )
seterrorresult(vm,"cannot close standard file");
else {
f.close();
setsuccessresult(vm);
}
}
private static void setsuccessresult(LuaState vm) {
vm.resettop();
vm.pushboolean(true);
}
private static void seterrorresult(LuaState vm, IOException ioe) {
String s = ioe.getMessage();
seterrorresult(vm, "io error: "+(s!=null? s: ioe.toString()));
}
private static void seterrorresult(LuaState vm, String errortext) {
vm.resettop();
vm.pushnil();
vm.pushstring(errortext);
}
private LValue lines(LuaState vm, final File f) {
return new LFunction() {
public boolean luaStackCall(LuaState vm) {
vm.resettop();
try {
vm.pushlvalue(freadline(f));
} catch (IOException e) {
seterrorresult(vm,e);
}
return false;
}
};
}
private static void iowrite(LuaState vm, File f) throws IOException {
for ( int i=1, n=vm.gettop(); i<=n; i++ )
f.write( vm.checklstring(i) );
vm.resettop();
vm.pushboolean(true);
}
private static void ioread(LuaState vm, File f) throws IOException {
int i,n=vm.gettop();
for ( i=1; i<=n; i++ ) {
if ( vm.isnumber(i) ) {
vm.pushlvalue(freadbytes(f,vm.tointeger(i)));
} else {
String format = vm.checkstring(i);
if ( "*n".equals(format) )
vm.pushnumber(freadnumber(f));
else if ( "*a".equals(format) )
vm.pushlvalue(freadall(f));
else if ( "*l".equals(format) )
vm.pushlvalue(freadline(f));
else
vm.typerror( i, "(invalid format)" );
}
}
for ( i=1; i<=n; i++ )
vm.remove(1);
}
private static File checkfile(LuaState vm, int index) {
File f = (File) vm.checkudata(index, File.class);
checkopen( vm, f );
return f;
}
private File optfile(LuaState vm, int index) {
Object u = vm.touserdata(index);
return (u instanceof File? (File) u: null);
}
private static File checkopen(LuaState vm, File file) {
if ( file.isclosed() )
vm.error("attempt to use a closed file");
return file;
}
private static void setresult(LuaState vm, File file) {
vm.settop(0);
vm.pushlvalue(touserdata(file));
}
private static LUserData touserdata(File file) {
return new LUserData(file, FILE_MT);
}
private File ioopenfile(LuaState vm, String filename, String mode) {
try {
return rawopenfile(filename, mode);
} catch ( Exception e ) {
vm.error("io error: "+e.getMessage());
return null;
}
}
private File rawopenfile(String filename, String mode) throws IOException {
boolean isstdfile = "-".equals(filename);
boolean isreadmode = mode.startsWith("r");
if ( isstdfile ) {
return isreadmode?
wrapStdin():
wrapStdout();
}
boolean isappend = mode.startsWith("a");
boolean isupdate = mode.indexOf("+") > 0;
boolean isbinary = mode.endsWith("b");
return openFile( filename, isreadmode, isappend, isupdate, isbinary );
}
// ------------- file reading utilitied ------------------
public static LValue freadbytes(File f, int count) throws IOException {
byte[] b = new byte[count];
int r;
if ( ( r = f.read(b,0,b.length) ) < 0 )
return LNil.NIL;
return new LString(b, 0, r);
}
public static LValue freaduntil(File f,int delim) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
try {
while ( true ) {
c = f.read();
if ( c < 0 || c == delim )
break;
baos.write(c);
}
} catch ( EOFException e ) {
c = -1;
}
return ( c < 0 && baos.size() == 0 )?
(LValue) LNil.NIL:
(LValue) new LString(baos.toByteArray());
}
public static LValue freadline(File f) throws IOException {
return freaduntil(f,'\n');
}
public static LValue freadall(File f) throws IOException {
int n = f.remaining();
if ( n >= 0 ) {
return freadbytes(f, n);
} else {
return freaduntil(f,-1);
}
}
public static Double freadnumber(File f) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
freadchars(f," \t\r\n",null);
freadchars(f,"-+",baos);
//freadchars(f,"0",baos);
//freadchars(f,"xX",baos);
freadchars(f,"0123456789",baos);
freadchars(f,".",baos);
freadchars(f,"0123456789",baos);
//freadchars(f,"eEfFgG",baos);
// freadchars(f,"+-",baos);
//freadchars(f,"0123456789",baos);
String s = baos.toString();
return s.length()>0? Double.valueOf(s): null;
}
private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException {
int c;
while ( true ) {
c = f.peek();
if ( chars.indexOf(c) < 0 ) {
return;
}
f.read();
if ( baos != null )
baos.write( c );
}
}
}

View File

@@ -1,78 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib;
import org.luaj.vm.LString;
public class LBuffer {
private byte[] bytes;
private int length;
public LBuffer( int initialCapacity ) {
bytes = new byte[ initialCapacity ];
length = 0;
}
public void append( byte b ) {
ensureCapacity( length + 1 );
bytes[ length++ ] = b;
}
public void append( LString str ) {
final int alen = str.length();
ensureCapacity( length + alen );
str.copyInto( 0, bytes, length, alen );
length += alen;
}
public void append( String str ) {
final int alen = LString.lengthAsUtf8( str );
ensureCapacity( length + alen );
LString.encodeToUtf8( str, bytes, length );
length += alen;
}
public void setLength( int length ) {
ensureCapacity( length );
this.length = length;
}
public LString toLuaString() {
return new LString( realloc( bytes, length ) );
}
public void ensureCapacity( int minSize ) {
if ( minSize > bytes.length )
realloc( minSize );
}
private void realloc( int minSize ) {
bytes = realloc( bytes, Math.max( bytes.length * 2, minSize ) );
}
private static byte[] realloc( byte[] b, int newSize ) {
byte[] newBytes = new byte[ newSize ];
System.arraycopy( b, 0, newBytes, 0, Math.min( b.length, newSize ) );
return newBytes;
}
}

View File

@@ -1,227 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib;
import java.util.Random;
import org.luaj.vm.LDouble;
import org.luaj.vm.LFunction;
import org.luaj.vm.LTable;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class MathLib extends LFunction {
public static final String[] NAMES = {
"math",
// irregular functions
"max",
"min",
"modf",
"ceil",
"floor",
"frexp",
"ldexp",
"random",
"randomseed",
// 2 argument, return double
"atan2",
"fmod",
"pow",
// single argument, return double
"abs",
"acos",
"asin",
"atan",
"cos",
"cosh",
"deg",
"exp",
"log",
"log10",
"rad",
"sin",
"sinh",
"sqrt",
"tan",
"tanh",
};
private static final int INSTALL = 0;
// irregular functions
public static final int MAX = 1;
public static final int MIN = 2;
public static final int MODF = 3;
public static final int CEIL = 4;
public static final int FLOOR = 5;
public static final int FREXP = 6;
public static final int LDEXP = 7;
public static final int RANDOM = 8;
public static final int RSEED = 9;
public static final int LAST_IRREGULAR = RSEED;
// 2 argument, return double
public static final int ATAN2 = 10;
public static final int FMOD = 11;
public static final int POW = 12;
public static final int LAST_DOUBLE_ARG = POW;
/* Math operations - single argument, one function */
public static final int ABS = 13;
public static final int ACOS = 14;
public static final int ASIN = 15;
public static final int ATAN = 16;
public static final int COS = 17;
public static final int COSH = 18;
public static final int DEG = 19;
public static final int EXP = 20;
public static final int LOG = 21;
public static final int LOG10 = 22;
public static final int RAD = 23;
public static final int SIN = 24;
public static final int SINH = 25;
public static final int SQRT = 26;
public static final int TAN = 27;
public static final int TANH = 28;
private static Platform platform;
public static void install( LTable globals ) {
LTable math = new LTable();
for ( int i=1; i<NAMES.length; i++ )
math.put(NAMES[i], new MathLib(i));
math.put( "huge", new LDouble( Double.MAX_VALUE ) );
math.put( "pi", new LDouble( Math.PI ) );
globals.put( "math", math );
PackageLib.setIsLoaded("math", math);
platform = Platform.getInstance();
}
private static Random random = null;
private final int id;
private MathLib( int id ) {
this.id = id;
}
public String toString() {
return NAMES[id]+"()";
}
private static void setResult( LuaState vm, double d ) {
vm.resettop();
vm.pushlvalue( LDouble.numberOf(d) );
}
public int invoke(LuaState vm) {
if ( id > LAST_DOUBLE_ARG ) {
vm.pushlvalue( platform.mathop(id, vm.checknumber(1) ) );
return 1;
} else if ( id > LAST_IRREGULAR ) {
vm.pushlvalue( platform.mathop(id, vm.checknumber(1), vm.checknumber(2) ) );
return 1;
} else {
switch ( id ) {
case INSTALL:
install( vm._G );
return 0;
case MAX: {
int n = vm.gettop();
double x = vm.checkdouble(1);
for ( int i=2; i<=n; i++ )
x = Math.max(x, vm.checkdouble(i));
vm.pushnumber( x );
return 1;
}
case MIN: {
int n = vm.gettop();
double x = vm.checkdouble(1);
for ( int i=2; i<=n; i++ )
x = Math.min(x, vm.checkdouble(i));
vm.pushnumber( x );
return 1;
}
case MODF: {
double x = vm.checkdouble(1);
double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
double fracPart = x - intPart;
vm.pushnumber( intPart );
vm.pushnumber( fracPart );
return 2;
}
case CEIL:
vm.pushnumber( Math.ceil( vm.checkdouble(1) ) );
return 1;
case FLOOR:
vm.pushnumber( Math.floor( vm.checkdouble(1) ) );
return 1;
case FREXP: {
long bits = Double.doubleToLongBits( vm.checkdouble(1) );
vm.pushnumber( ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))) );
vm.pushinteger( (((int) (bits >> 52)) & 0x7ff) - 1022 );
return 2;
}
case LDEXP: {
double m = vm.checkdouble(1);
int e = vm.checkint(2);
vm.pushnumber( m * Double.longBitsToDouble(((long)(e+1023)) << 52) );
return 1;
}
case RANDOM: {
if ( random == null )
random = new Random(1);
switch ( vm.gettop() ) {
case 0:
vm.pushnumber(random.nextDouble());
return 1;
case 1: {
int m = vm.checkint(1);
vm.argcheck(1<=m, 1, "interval is empty");
vm.pushinteger(1+random.nextInt(m));
return 1;
}
default: {
int m = vm.checkint(1);
int n = vm.checkint(2);
vm.argcheck(m<=n, 2, "interval is empty");
vm.pushinteger(m+random.nextInt(n+1-m));
return 1;
}
}
}
case RSEED:
random = new Random( vm.checkint(1) );
return 0;
default:
LuaState.vmerror( "bad math id" );
return 0;
}
}
}
}

View File

@@ -1,344 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 LuaJ. 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.lib;
import java.io.IOException;
import org.luaj.vm.LFunction;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
/**
* Base implementation of OsLib, with simplified stub functions
* for library functions that cannot be implemented uniformly
* on J2se and J2me.
*
* This can be installed as-is on either platform, or extended
* and refined to be used in a complete J2se implementation.
*/
public class OsLib extends LFunction {
public static String TMP_PREFIX = ".luaj";
public static String TMP_SUFFIX = "tmp";
/**
* Create a function stub with a specific index.
* This is a factory method so that subclasses can
* use install(LTable,OsLib) to install themselves.
*/
protected OsLib newInstance( int index ) {
return new OsLib(index);
}
public static final String[] NAMES = {
"os",
"clock",
"date",
"difftime",
"execute",
"exit",
"getenv",
"remove",
"rename",
"setlocale",
"time",
"tmpname",
};
private static final int INSTALL = 0;
private static final int CLOCK = 1;
private static final int DATE = 2;
private static final int DIFFTIME = 3;
private static final int EXECUTE = 4;
private static final int EXIT = 5;
private static final int GETENV = 6;
private static final int REMOVE = 7;
private static final int RENAME = 8;
private static final int SETLOCALE = 9;
private static final int TIME = 10;
private static final int TMPNAME = 11;
/**
* Install the os library using the OsLib class as a factory
*/
public static void install( LTable globals ) {
install(globals, new OsLib());
}
/**
* Initialize the os libaray using the subblied instance as a factory.
* @param factory instance to use as a factory for function stubs.
*/
public static void install( LTable globals, OsLib factory ) {
LTable os = new LTable();
for ( int i=CLOCK; i<=TMPNAME; i++ )
os.put(NAMES[i], factory.newInstance(i));
globals.put( "os", os );
PackageLib.setIsLoaded("os", os);
}
private static final long t0 = System.currentTimeMillis();
private static long tmpnames = t0;
private final int id;
protected OsLib() {
id = 0;
}
protected OsLib( int id ) {
this.id = id;
}
public LString luaAsString() {
return new LString(toJavaString());
}
public String toJavaString() {
return "os."+toString();
}
public String toString() {
return NAMES[id]+"()";
}
public int invoke( LuaState vm ) {
LValue v;
long t,t2;
int c;
String s;
try {
switch ( id ) {
case INSTALL:
install(vm._G, this);
return 0;
case CLOCK:
vm.pushnumber(clock());
return 1;
case DATE:
s = vm.optstring(1, null);
t = vm.optlong(2,-1);
vm.pushlvalue( date(s, t==-1? System.currentTimeMillis(): t) );
return 1;
case DIFFTIME:
t2 = vm.checklong(1);
t = vm.checklong(2);
vm.pushnumber(difftime(t2,t));
return 1;
case EXECUTE:
c = execute(vm.optstring(1, null));
vm.pushinteger(c);
return 1;
case EXIT:
exit(vm.optint(1, 0));
return 0;
case GETENV:
s = getenv(vm.checkstring(1));
vm.pushstring(s);
return 1;
case REMOVE:
remove(vm.checkstring(1));
vm.pushboolean(true);
return 1;
case RENAME:
rename(vm.checkstring(1), vm.checkstring(2));
vm.pushboolean(true);
return 1;
case SETLOCALE:
s = setlocale(vm.optstring(1,null), vm.optstring(2, "all"));
if ( s != null )
vm.pushstring(s);
else
vm.pushnil();
return 1;
case TIME:
t = time(vm.isnoneornil(1)? null: vm.checktable(1));
vm.pushnumber(t);
return 1;
case TMPNAME:
vm.pushstring(tmpname());
return 1;
default:
LuaState.vmerror( "bad os id" );
return 0;
}
} catch ( IOException e ) {
vm.pushnil();
vm.pushstring(e.getMessage());
return 2;
}
}
/**
* @return an approximation of the amount in seconds of CPU time used by
* the program.
*/
protected double clock() {
return (System.currentTimeMillis()-t0) / 1000.;
}
/**
* Returns the number of seconds from time t1 to time t2.
* In POSIX, Windows, and some other systems, this value is exactly t2-t1.
* @param t2
* @param t1
* @return diffeence in time values, in seconds
*/
protected double difftime(long t2, long t1) {
return (t2 - t1) / 1000.;
}
/**
* If the time argument is present, this is the time to be formatted
* (see the os.time function for a description of this value).
* Otherwise, date formats the current time.
*
* If format starts with '!', then the date is formatted in Coordinated
* Universal Time. After this optional character, if format is the string
* "*t", then date returns a table with the following fields: year
* (four digits), month (1--12), day (1--31), hour (0--23), min (0--59),
* sec (0--61), wday (weekday, Sunday is 1), yday (day of the year),
* and isdst (daylight saving flag, a boolean).
*
* If format is not "*t", then date returns the date as a string,
* formatted according to the same rules as the C function strftime.
*
* When called without arguments, date returns a reasonable date and
* time representation that depends on the host system and on the
* current locale (that is, os.date() is equivalent to os.date("%c")).
*
* @param format
* @param time time since epoch, or -1 if not supplied
* @return a LString or a LTable containing date and time,
* formatted according to the given string format.
*/
protected LValue date(String format, long time) {
return LString.valueOf( new java.util.Date(time).toString() );
}
/**
* This function is equivalent to the C function system.
* It passes command to be executed by an operating system shell.
* It returns a status code, which is system-dependent.
* If command is absent, then it returns nonzero if a shell
* is available and zero otherwise.
* @param command command to pass to the system
*/
protected int execute(String command) {
return 0;
}
/**
* Calls the C function exit, with an optional code, to terminate the host program.
* @param code
*/
protected void exit(int code) {
System.exit(code);
}
/**
* Returns the value of the process environment variable varname,
* or null if the variable is not defined.
* @param varname
* @return
*/
protected String getenv(String varname) {
return System.getProperty(varname);
}
/**
* Deletes the file or directory with the given name.
* Directories must be empty to be removed.
* If this function fails, it throws and IOException
*
* @param filename
* @throws IOException if it fails
*/
protected void remove(String filename) throws IOException {
throw new IOException( "not implemented" );
}
/**
* Renames file or directory named oldname to newname.
* If this function fails,it throws and IOException
*
* @param oldname old file name
* @param newname new file name
* @throws IOException if it fails
*/
protected void rename(String oldname, String newname) throws IOException {
throw new IOException( "not implemented" );
}
/**
* Sets the current locale of the program. locale is a string specifying
* a locale; category is an optional string describing which category to change:
* "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category
* is "all".
*
* If locale is the empty string, the current locale is set to an implementation-
* defined native locale. If locale is the string "C", the current locale is set
* to the standard C locale.
*
* When called with null as the first argument, this function only returns the
* name of the current locale for the given category.
*
* @param locale
* @param category
* @return the name of the new locale, or null if the request
* cannot be honored.
*/
protected String setlocale(String locale, String category) {
return null;
}
/**
* Returns the current time when called without arguments,
* or a time representing the date and time specified by the given table.
* This table must have fields year, month, and day,
* and may have fields hour, min, sec, and isdst
* (for a description of these fields, see the os.date function).
* @param table
* @return long value for the time
*/
protected long time(LTable table) {
return System.currentTimeMillis();
}
/**
* Returns a string with a file name that can be used for a temporary file.
* The file must be explicitly opened before its use and explicitly removed
* when no longer needed.
*
* On some systems (POSIX), this function also creates a file with that name,
* to avoid security risks. (Someone else might create the file with wrong
* permissions in the time between getting the name and creating the file.)
* You still have to open the file to use it and to remove it (even if you
* do not use it).
*
* @return String filename to use
*/
protected String tmpname() {
return TMP_PREFIX+(tmpnames++)+TMP_SUFFIX;
}
}

View File

@@ -1,416 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Vector;
import org.luaj.vm.CallInfo;
import org.luaj.vm.LBoolean;
import org.luaj.vm.LFunction;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class PackageLib extends LFunction {
public static String DEFAULT_LUA_PATH = "?.lua";
public static InputStream STDIN = null;
public static PrintStream STDOUT = System.out;
public static LTable LOADED = null;
private static final LString _M = new LString("_M");
private static final LString _NAME = new LString("_NAME");
private static final LString _PACKAGE = new LString("_PACKAGE");
private static final LString _DOT = new LString(".");
private static final LString _EMPTY = new LString("");
private static final LString __INDEX = new LString("__index");
private static final LString _LOADERS = new LString("loaders");
private static final LString _PRELOAD = new LString("preload");
private static final LString _PATH = new LString("path");
private static final LValue _SENTINEL = _EMPTY;
private static final String[] NAMES = {
"package",
"module",
"require",
"loadlib",
"seeall",
"preload_loader",
"lua_loader",
"java_loader",
};
private static final int INSTALL = 0;
private static final int MODULE = 1;
private static final int REQUIRE = 2;
private static final int LOADLIB = 3;
private static final int SEEALL = 4;
private static final int PRELOAD_LOADER = 5;
private static final int LUA_LOADER = 6;
private static final int JAVA_LOADER = 7;
// all functions in package share this environment
private static LTable pckg;
public static void install( LTable globals ) {
for ( int i=1; i<=REQUIRE; i++ )
globals.put( NAMES[i], new PackageLib(i) );
pckg = new LTable();
for ( int i=LOADLIB; i<=SEEALL; i++ )
pckg.put( NAMES[i], new PackageLib(i) );
LOADED = new LTable();
pckg.put( "loaded", LOADED );
pckg.put( _PRELOAD, new LTable() );
LTable loaders = new LTable(3,0);
for ( int i=PRELOAD_LOADER; i<=JAVA_LOADER; i++ )
loaders.luaInsertPos(0, new PackageLib(i) );
pckg.put( "loaders", loaders );
pckg.put( _PATH, new LString(DEFAULT_LUA_PATH) );
globals.put( "package", pckg );
setIsLoaded( "package", pckg );
}
/** Allow packages to mark themselves as loaded */
public static void setIsLoaded(String name, LTable value) {
LOADED.put(name, value);
}
public static void setLuaPath( String newLuaPath ) {
pckg.put( _PATH, new LString(newLuaPath) );
}
private final int id;
private PackageLib( int id ) {
this.id = id;
}
public String toString() {
return NAMES[id]+"()";
}
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL:
install(vm._G);
return 0;
case MODULE:
return module(vm);
case REQUIRE:
return require(vm);
case LOADLIB:
return loadlib(vm);
case SEEALL: {
LTable t = vm.checktable(1);
LTable m = t.luaGetMetatable();
if ( m == null )
t.luaSetMetatable(m = new LTable());
m.put(__INDEX, vm._G);
return 0;
}
case PRELOAD_LOADER: {
return loader_preload(vm);
}
case LUA_LOADER: {
return loader_Lua(vm);
}
case JAVA_LOADER: {
return loader_Java(vm);
}
default:
LuaState.vmerror( "bad package id" );
return 0;
}
}
// ======================== Module, Package loading =============================
/**
* module (name [, ...])
*
* Creates a module. If there is a table in package.loaded[name], this table
* is the module. Otherwise, if there is a global table t with the given
* name, this table is the module. Otherwise creates a new table t and sets
* it as the value of the global name and the value of package.loaded[name].
* This function also initializes t._NAME with the given name, t._M with the
* module (t itself), and t._PACKAGE with the package name (the full module
* name minus last component; see below). Finally, module sets t as the new
* environment of the current function and the new value of
* package.loaded[name], so that require returns t.
*
* If name is a compound name (that is, one with components separated by
* dots), module creates (or reuses, if they already exist) tables for each
* component. For instance, if name is a.b.c, then module stores the module
* table in field c of field b of global a.
*
* This function may receive optional options after the module name, where
* each option is a function to be applied over the module.
*/
public static int module(LuaState vm) {
LString modname = vm.checklstring(1);
int n = vm.gettop();
LValue value = LOADED.luaGetTable(vm, modname);
LTable module;
if ( ! value.isTable() ) { /* not found? */
/* try global variable (and create one if it does not exist) */
module = findtable( vm._G, modname );
if ( module == null )
vm.error( "name conflict for module '"+modname+"'" );
LOADED.luaSetTable(vm, modname, module);
} else {
module = (LTable) value;
}
/* check whether table already has a _NAME field */
LValue name = module.luaGetTable(vm, _NAME);
if ( name.isNil() ) {
modinit( vm, module, modname );
}
// set the environment of the current function
CallInfo ci = vm.getStackFrame(0);
ci.closure.env = module;
// apply the functions
for ( int i=2; i<=n; i++ ) {
vm.pushvalue( i ); /* get option (a function) */
vm.pushlvalue( module ); /* module */
vm.call( 1, 0 );
}
// returns no results
return 0;
}
/**
*
* @param table the table at which to start the search
* @param fname the name to look up or create, such as "abc.def.ghi"
* @return the table for that name, possible a new one, or null if a non-table has that name already.
*/
private static LTable findtable(LTable table, LString fname) {
int b, e=(-1);
do {
e = fname.indexOf(_DOT, b=e+1 );
if ( e < 0 )
e = fname.m_length;
LString key = fname.substring(b, e);
LValue val = table.get(key);
if ( val.isNil() ) { /* no such field? */
LTable field = new LTable(); /* new table for field */
table.put(key, field);
table = field;
} else if ( val.luaGetType() != Lua.LUA_TTABLE ) { /* field has a non-table value? */
return null;
} else {
table = (LTable) val;
}
} while ( e < fname.m_length );
return table;
}
private static void modinit(LuaState vm, LTable module, LString modname) {
/* module._M = module */
module.luaSetTable(vm, _M, module);
int e = modname.lastIndexOf(_DOT);
module.luaSetTable(vm, _NAME, modname );
module.luaSetTable(vm, _PACKAGE, (e<0? _EMPTY: modname.substring(0,e+1)) );
}
/**
* require (modname)
*
* Loads the given module. The function starts by looking into the package.loaded table to
* determine whether modname is already loaded. If it is, then require returns the value
* stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module.
*
* To find a loader, require is guided by the package.loaders array. By changing this array,
* we can change how require looks for a module. The following explanation is based on the
* default configuration for package.loaders.
*
* First require queries package.preload[modname]. If it has a value, this value
* (which should be a function) is the loader. Otherwise require searches for a Lua loader
* using the path stored in package.path. If that also fails, it searches for a C loader
* using the path stored in package.cpath. If that also fails, it tries an all-in-one loader
* (see package.loaders).
*
* Once a loader is found, require calls the loader with a single argument, modname.
* If the loader returns any value, require assigns the returned value to package.loaded[modname].
* If the loader returns no value and has not assigned any value to package.loaded[modname],
* then require assigns true to this entry. In any case, require returns the final value of
* package.loaded[modname].
*
* If there is any error loading or running the module, or if it cannot find any loader for
* the module, then require signals an error.
*/
public int require( LuaState vm ) {
LString name = vm.checklstring(1);
LValue loaded = LOADED.luaGetTable(vm, name);
if ( loaded.toJavaBoolean() ) {
if ( loaded == _SENTINEL )
vm.error("loop or previous error loading module '"+name+"'");
vm.pushlvalue( loaded );
return 1;
}
/* else must load it; iterate over available loaders */
LValue val = pckg.luaGetTable(vm, _LOADERS);
if ( ! val.isTable() )
vm.error( "'package.loaders' must be a table" );
LTable tbl = (LTable) val;
Vector v = new Vector();
for ( int i=1; true; i++ ) {
LValue loader = tbl.get(i);
if ( loader.isNil() ) {
vm.error( "module '"+name+"' not found: "+v );
}
/* call loader with module name as argument */
vm.pushlvalue(loader);
vm.pushlstring(name);
vm.call(1, 1);
if ( vm.isfunction(-1) )
break; /* module loaded successfully */
if ( vm.isstring(-1) ) /* loader returned error message? */
v.addElement(vm.tolstring(-1)); /* accumulate it */
vm.pop(1);
}
// load the module using the loader
LOADED.luaSetTable(vm, name, _SENTINEL);
vm.pushlstring( name ); /* pass name as argument to module */
vm.call( 1, 1 ); /* run loaded module */
if ( ! vm.isnil(-1) ) /* non-nil return? */
LOADED.luaSetTable(vm, name, vm.topointer(-1) ); /* _LOADED[name] = returned value */
LValue result = LOADED.luaGetTable(vm, name);
if ( result == _SENTINEL ) { /* module did not set a value? */
LOADED.luaSetTable(vm, name, result=LBoolean.TRUE ); /* _LOADED[name] = true */
}
vm.pushlvalue(result);
return 1;
}
public static int loadlib( LuaState vm ) {
vm.checkstring(1);
vm.pushnil();
vm.pushstring("dynamic libraries not enabled");
vm.pushstring("absent");
return 3;
}
private int loader_preload( LuaState vm ) {
LString name = vm.tolstring(1);
LValue preload = pckg.luaGetTable(vm, _PRELOAD);
if ( ! preload.isTable() )
vm.error("package.preload '"+name+"' must be a table");
LValue val = preload.luaGetTable(vm, name);
if ( val.isNil() )
vm.pushstring("\n\tno field package.preload['"+name+"']");
else
vm.pushlvalue(val);
return 1;
}
private int loader_Lua( LuaState vm ) {
String name = vm.tostring(1);
InputStream is = findfile( vm, name, _PATH );
if ( is != null ) {
String filename = vm.tostring(-1);
if ( ! BaseLib.loadis(vm, is, filename) )
loaderror( vm, filename );
}
return 1;
}
private int loader_Java( LuaState vm ) {
String name = vm.tostring(1);
Class c = null;
LValue v = null;
try {
c = Class.forName(name);
v = (LValue) c.newInstance();
vm.pushlvalue( v );
} catch ( ClassNotFoundException cnfe ) {
vm.pushstring("\n\tno class '"+name+"'" );
} catch ( Exception e ) {
vm.pushstring("\n\tjava load failed on '"+name+"', "+e );
}
return 1;
}
private InputStream findfile(LuaState vm, String name, LString pname) {
Platform p = Platform.getInstance();
LValue pkg = pckg.luaGetTable(vm, pname);
if ( ! pkg.isString() )
vm.error("package."+pname+" must be a string");
String path = pkg.toJavaString();
int e = -1;
int n = path.length();
StringBuffer sb = null;
name = name.replace('.','/');
while ( e < n ) {
// find next template
int b = e+1;
e = path.indexOf(';',b);
if ( e < 0 )
e = path.length();
String template = path.substring(b,e);
// create filename
int q = template.indexOf('?');
String filename = template;
if ( q >= 0 ) {
filename = template.substring(0,q) + name + template.substring(q+1);
}
// try opening the file
InputStream is = p.openFile(filename);
if ( is != null ) {
vm.pushstring(filename);
return is;
}
// report error
if ( sb == null )
sb = new StringBuffer();
sb.append( "\n\tno file '"+filename+"'");
}
// not found, push error on stack and return
vm.pushstring(sb.toString());
return null;
}
private static void loaderror(LuaState vm, String filename) {
vm.error( "error loading module '"+vm.tostring(1)+"' from file '"+filename+"':\n\t"+vm.tostring(-1) );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,210 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib;
import java.io.ByteArrayOutputStream;
import org.luaj.vm.LFunction;
import org.luaj.vm.LNil;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
public class TableLib extends LFunction {
public static final String[] NAMES = {
"table",
"concat",
"foreach",
"foreachi",
"getn",
"insert",
"maxn",
"remove",
"sort",
};
private static final int INSTALL = 0;
private static final int CONCAT = 1;
private static final int FOREACH = 2;
private static final int FOREACHI = 3;
private static final int GETN = 4;
private static final int INSERT = 5;
private static final int MAXN = 6;
private static final int REMOVE = 7;
private static final int SORT = 8;
public static void install( LTable globals ) {
LTable table = new LTable();
for ( int i=1; i<NAMES.length; i++ )
table.put( NAMES[i], new TableLib(i) );
globals.put( "table", table );
PackageLib.setIsLoaded("table", table);
}
private final int id;
/** Default constructor for loading the library dynamically */
private TableLib() {
id = 0;
}
/** Private constructor to construct a table function instance */
private TableLib( int id ) {
this.id = id;
}
public String toString() {
return NAMES[id]+"()";
}
public int invoke( LuaState vm ) {
switch ( id ) {
/* Load the table library dynamically
*/
case INSTALL:
install(vm._G);
return 0;
/* table.concat (table [, sep [, i [, j]]])
*
* Given an array where all elements are strings or numbers, returns table[i]..sep..table[i+1] ··· sep..table[j].
* The default value for sep is the empty string, the default for i is 1, and the default for j is the length of the table.
* If i is greater than j, returns the empty string.
*/
case CONCAT: {
// int n = vm.gettop();
LTable table = vm.checktable(1);
LString sep = vm.optlstring(2,null);
int i = vm.optint(3,1);
int j = vm.optint(4,-1);
if ( j == -1 )
j = table.luaLength();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for ( int k=i; k<=j; k++ ) {
LValue v = table.get(k);
if ( ! v.isString() )
vm.argerror(1, "table contains non-strings");
v.luaConcatTo(baos);
if ( k<j && sep!=null )
sep.luaConcatTo( baos );
}
vm.pushlstring( baos.toByteArray() );
return 1;
}
/* table.getn (table)
*
* Get length of table t.
*/
case FOREACH:
case FOREACHI:
{
LTable table = vm.checktable(1);
LFunction function = vm.checkfunction(2);
vm.pushlvalue( table.foreach( vm, function, id==FOREACHI ) );
return 1;
}
/* table.getn (table)
*
* Get length of table t.
*/
case GETN: {
LTable table = vm.checktable(1);
vm.pushinteger(table.luaLength());
return 1;
}
/* table.insert (table, [pos,] value)
*
* Inserts element value at position pos in table, shifting up other elements to open space, if necessary.
* The default value for pos is n+1, where n is the length of the table (see §2.5.5), so that a call
* table.insert(t,x) inserts x at the end of table t.
*/
case INSERT: {
LTable table = vm.checktable(1);
int pos = 0;
switch ( vm.gettop() ) {
case 2:
break;
case 3:
pos = vm.checkint(2);
break;
default:
vm.error( "wrong number of arguments to 'insert'" );
}
table.luaInsertPos( pos, vm.topointer(-1) );
return 0;
}
/* table.maxn (table)
*
* Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical
* indices. (To do its job this function does a linear traversal of the whole table.)
*/
case MAXN: {
LTable table = vm.checktable(1);
vm.pushlvalue( table.luaMaxN() );
return 1;
}
/* table.remove (table [, pos])
*
* Removes from table the element at position pos, shifting down other elements to close the space, if necessary.
* Returns the value of the removed element. The default value for pos is n, where n is the length of the table,
* so that a call table.remove(t) removes the last element of table t.
*/
case REMOVE: {
LTable table = vm.checktable(1);
int pos = vm.optint(2,0);
LValue v = table.luaRemovePos( pos );
vm.pushlvalue( v );
return v.isNil()? 0: 1;
}
/* table.sort (table [, comp])
*
* Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the length of the table.
* If comp is given, then it must be a function that receives two table elements, and returns true when the first
* is less than the second (so that not comp(a[i+1],a[i]) will be true after the sort). If comp is not given,
* then the standard Lua operator &lt; is used instead.
*
* The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
*/
case SORT: {
LTable table = vm.checktable(1);
LValue compare = (vm.isnoneornil(2)? (LValue) LNil.NIL: (LValue) vm.checkfunction(2));
table.luaSort( vm, compare );
return 0;
}
default:
LuaState.vmerror( "bad table id" );
return 0;
}
}
}

View File

@@ -1,91 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class CallInfo {
public LClosure closure;
public int base;
public int top;
public int pc;
public int resultbase;
public int nresults;
public CallInfo(LClosure c, int base, int top, int resultoff, int nresults) {
this.closure = c;
this.base = base;
this.top = top;
this.resultbase = resultoff;
this.nresults = nresults;
this.pc = 0;
}
public boolean isLua() {
return true;
}
/**
* @return current line number, or -1 if no line info found
*/
public int currentline() {
int[] li = closure.p.lineinfo;
int pc = currentpc();
if ( li != null && pc < li.length )
return li[pc];
return -1;
}
/**
* @param vm
* @return current function executing, or null
*/
public LFunction currentfunc(LuaState vm) {
int a = currentfunca(vm);
if ( a >= 0 ) {
LValue v = vm.stack[base + a];
if ( v.isFunction() )
return (LFunction) v;
}
return null;
}
/**
* @param vm
* @return register of the current function executing, or null
*/
public int currentfunca(LuaState vm) {
int i = closure.p.code[currentpc()];
int op = Lua.GET_OPCODE(i);
if ( op == Lua.OP_CALL || op == Lua.OP_TAILCALL )
return Lua.GETARG_A(i);
return -1;
}
/**
* Get current program counter or instruction being executed now.
*/
public int currentpc() {
return pc>0? pc-1: 0;
}
}

View File

@@ -1,22 +0,0 @@
package org.luaj.vm;
import java.io.IOException;
public interface DebugNetSupport {
/**
* Starts the networking for debug support.
* @throws IOException
*/
public abstract void start() throws IOException;
/**
* Shuts down the networking for the debug support.
*/
public abstract void stop();
/**
* Disconnect all connected clients.
*/
public abstract void disconnect();
}

View File

@@ -1,64 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public final class LBoolean extends LValue {
public static final LBoolean TRUE = new LBoolean("true",true);
public static final LBoolean FALSE = new LBoolean("false",false);
private final String m_sname;
private final LString m_name;
private final boolean m_value;
private LBoolean( String name, boolean value ) {
this.m_sname = name;
this.m_name = new LString( name );
this.m_value = value;
}
public final String toJavaString() {
return m_sname;
}
public final LString luaAsString() {
return m_name;
}
public final boolean toJavaBoolean() {
return m_value;
}
public final int toJavaInt() {
return m_value? 1: 0;
}
public final static LBoolean valueOf(boolean value) {
return value? TRUE: FALSE;
}
public int luaGetType() {
return Lua.LUA_TBOOLEAN;
}
}

View File

@@ -1,67 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class LClosure extends LFunction {
public LPrototype p;
public UpVal[] upVals;
public LTable env;
/**
* Construct using a prototype and initial environment.
* @param p
* @param env
*/
protected LClosure(LPrototype p, LTable env) {
this.p = p;
this.env = env;
upVals = new UpVal[p.nups];
}
// called by vm when there is an OP_CALL
// in this case, we are on the stack,
// and simply need to cue the VM to treat it as a stack call
public boolean luaStackCall(LuaState vm) {
vm.prepStackCall();
return true;
}
/** Set the environment if a thread, or closure, and return 1, otherwise return 0 */
public boolean luaSetEnv(LTable t) {
this.env = t;
return true;
}
/** Get the enviroment for this closure */
public LTable luaGetEnv(LTable d) {
return env;
}
/** Returns true if this is a lua closure, false otherwise */
public boolean isClosure() {
return true;
}
}

View File

@@ -1,150 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class LDouble extends LNumber {
private final double m_value;
public static LDouble valueOf(double value) {
return new LDouble(value);
}
/** Convert to LNumber, using LInteger if possible */
public static LNumber numberOf(double z) {
int iz = (int) z;
return (z==iz? (LNumber) LInteger.valueOf(iz): (LNumber) new LDouble(z));
}
public LDouble(double value) {
this.m_value = value;
}
public int hashCode() {
if ( m_value == 0 ) {
return 0;
} else {
int iz = (int) m_value;
if ( iz == m_value ) return iz;
long bits = Double.doubleToLongBits( m_value );
return ((int) (bits >> 32)) + ((int)bits);
}
}
public String toJavaString() {
if ( Double.isNaN(m_value) )
return "nan";
if ( Double.isInfinite(m_value) )
return (m_value>0? "inf": "-inf");
if ( m_value == 0.0 ) {
long bits = Double.doubleToLongBits( m_value );
return ( bits >> 63 == 0 ) ? "0" : "-0";
}
long l = (long) m_value;
if ( (m_value == (double) l) && (m_value <= Long.MAX_VALUE) && (m_value >= Long.MIN_VALUE) ) {
return Long.toString( l );
} else {
return Double.toString( m_value );
}
}
// return true if value survives as an integer
public boolean isInteger() {
return ( (double) ( (int) m_value ) ) == m_value;
}
// binary operations on integers, first dispatch
public LValue luaBinOpUnknown(int opcode, LValue lhs) {
return lhs.luaBinOpDouble( opcode, this.m_value );
}
// binary operations on mixtures of doubles and integers
public LValue luaBinOpInteger(int opcode, int rhs) {
return luaBinOpDoubleDouble( opcode, m_value, (double) rhs );
}
// binary operations on doubles
public LValue luaBinOpDouble(int opcode, double rhs) {
return luaBinOpDoubleDouble( opcode, m_value, rhs );
}
public static LValue luaBinOpDoubleDouble( int opcode, double lhs, double rhs ) {
switch ( opcode ) {
case Lua.OP_ADD: return LDouble.numberOf( lhs + rhs );
case Lua.OP_SUB: return LDouble.numberOf( lhs - rhs );
case Lua.OP_MUL: return LDouble.numberOf( lhs * rhs );
case Lua.OP_DIV: return LDouble.numberOf( lhs / rhs );
case Lua.OP_MOD: return LDouble.numberOf( lhs - Math.floor(lhs/rhs) * rhs );
case Lua.OP_POW: return Platform.getInstance().mathPow( LDouble.numberOf(lhs), LDouble.numberOf(rhs));
}
LuaState.vmerror( "bad bin opcode" );
return null;
}
public int toJavaInt() {
return (int) m_value;
}
public long toJavaLong() {
return (long) m_value;
}
public float toJavaFloat() {
return (float) m_value;
}
public double toJavaDouble() {
return m_value;
}
// binary compares on integers, first dispatch
public boolean luaBinCmpUnknown(int opcode, LValue lhs) {
return lhs.luaBinCmpDouble( opcode, this.m_value );
}
// binary compares on mixtures of doubles and integers
public boolean luaBinCmpInteger(int opcode, int rhs) {
return luaBinCmpDoubleDouble( opcode, m_value, (double) rhs );
}
// binary compares on doubles
public boolean luaBinCmpDouble(int opcode, double rhs) {
return luaBinCmpDoubleDouble( opcode, m_value, rhs );
}
// compare two doubles
public static boolean luaBinCmpDoubleDouble( int opcode, double lhs, double rhs ) {
switch ( opcode ) {
case Lua.OP_EQ: return lhs == rhs;
case Lua.OP_LT: return lhs < rhs;
case Lua.OP_LE: return lhs <= rhs;
}
LuaState.vmerror( "bad cmp opcode" );
return false;
}
/** Arithmetic negative */
public LValue luaUnaryMinus() {
return new LDouble( -m_value );
}
}

View File

@@ -1,96 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
abstract
public class LFunction extends LValue {
public String toJavaString() {
return "function: "+hashCode();
}
public boolean isFunction() {
return true;
}
public int luaGetType() {
return Lua.LUA_TFUNCTION;
}
/**
* Set up a Java invocation, and leave the results on the stack
* starting at base. The default implementation for LFunction
* delegates to the VM which provides convenience.
*/
public boolean luaStackCall(LuaState vm) {
vm.invokeJavaFunction( this );
return false;
}
/**
* Called to invoke a JavaFunction.
*
* The implementation should manipulate the stack
* via the VM Java API in the same way that lua_CFunctions
* do so in standard lua.
*
* Arguments to the function will be in position 1-n.
* Return values can be pushed onto the stack, and will be
* copied down to the appropriate location by the calling LuaState.
*
*
* @param lua the LuaState calling this function.
* @return number of results pushed onto the stack.
*/
public int invoke( LuaState lua ) {
return 0;
}
/**
* Process lua tag method __index when it points to a function.
* Default method calls the function using the vm.
*
* @param vm
* @param table
* @param key
* @return
*/
public LValue __index(LuaState vm, LValue table, LValue key) {
return vm.luaV_call_index(this, table, key);
}
/**
* Process lua tag method __newindex when it points to a function
* Default method calls the function using the vm.
*
* @param vm
* @param table
* @param key
* @param val
*/
public void __newindex(LuaState vm, LValue table, LValue key, LValue val) {
vm.luaV_call_newindex(this, table, key, val);
}
}

View File

@@ -1,136 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class LInteger extends LNumber {
private final int m_value;
/* local cache of commonly used LInteger values */
private static final int INTS_MIN = -16;
private static final int INTS_MAX = 32;
private static final LInteger s_ints[] = new LInteger[1+INTS_MAX-INTS_MIN];
static {
for ( int i=INTS_MIN; i<=INTS_MAX; i++ )
s_ints[i-INTS_MIN] = new LInteger(i);
}
/** Get an LInteger corresponding to a particular int value */
public static LInteger valueOf(int n) {
if ( n >= INTS_MIN && n <= INTS_MAX )
return s_ints[n-INTS_MIN];
return new LInteger(n);
}
/** use LInteger.valueOf() instead */
private LInteger(int value) {
this.m_value = value;
}
public final int hashCode() {
return hashCodeOf( m_value );
}
public static int hashCodeOf( int v ) {
return v;
}
public int toJavaInt() {
return m_value;
}
public long toJavaLong() {
return m_value;
}
public float toJavaFloat() {
return m_value;
}
public double toJavaDouble() {
return m_value;
}
public LString luaAsString() {
return LString.valueOf(m_value);
}
public String toJavaString() {
return String.valueOf(m_value);
}
public boolean isInteger() {
return true;
}
// binary operations on integers, first dispatch
public LValue luaBinOpUnknown(int opcode, LValue lhs) {
return lhs.luaBinOpInteger( opcode, this.m_value );
}
// binary operations on integers
public LValue luaBinOpInteger(int opcode, int rhs) {
switch ( opcode ) {
case Lua.OP_ADD: return LInteger.valueOf( m_value + rhs );
case Lua.OP_SUB: return LInteger.valueOf( m_value - rhs );
case Lua.OP_MUL: return LInteger.valueOf( m_value * rhs );
case Lua.OP_DIV:
case Lua.OP_MOD:
case Lua.OP_POW:
return LDouble.luaBinOpDoubleDouble(opcode, m_value, rhs);
}
LuaState.vmerror( "bad bin opcode" );
return null;
}
// binary operations on mixed integer, double
public LValue luaBinOpDouble(int opcode, double rhs) {
return LDouble.luaBinOpDoubleDouble(opcode, (double) m_value, rhs );
}
// binary compare for integers, first dispatch
public boolean luaBinCmpUnknown(int opcode, LValue lhs) {
return lhs.luaBinCmpInteger( opcode, this.m_value );
}
// unsupported except for numbers
public boolean luaBinCmpInteger(int opcode, int rhs) {
switch ( opcode ) {
case Lua.OP_EQ: return m_value == rhs;
case Lua.OP_LT: return m_value < rhs;
case Lua.OP_LE: return m_value <= rhs;
}
LuaState.vmerror( "bad cmp opcode" );
return false;
}
// unsupported except for numbers
public boolean luaBinCmpDouble(int opcode, double rhs) {
return LDouble.luaBinCmpDoubleDouble(opcode, (double) m_value, rhs );
}
/** Arithmetic negative */
public LValue luaUnaryMinus() {
return LInteger.valueOf( -m_value );
}
}

View File

@@ -1,80 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public final class LNil extends LValue {
public static final LNil NIL = new LNil();
public final LString luaAsString() {
return luaGetTypeName();
}
public boolean isNil() {
return true;
}
public boolean toJavaBoolean() {
return false;
}
public int luaGetType() {
return Lua.LUA_TNIL;
}
public int toJavaInt() {
return 0;
}
public String toJavaString() {
return "nil";
}
public Byte toJavaBoxedByte() {
return null;
}
public Character toJavaBoxedCharacter() {
return null;
}
public Double toJavaBoxedDouble() {
return null;
}
public Float toJavaBoxedFloat() {
return null;
}
public Integer toJavaBoxedInteger() {
return null;
}
public Long toJavaBoxedLong() {
return null;
}
public Short toJavaBoxedShort() {
return null;
}
}

View File

@@ -1,104 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
import java.io.ByteArrayOutputStream;
abstract
public class LNumber extends LValue {
/** Compare for equivalence by using lua op comparator */
public boolean equals(Object o) {
if ( ! ( o instanceof LValue) )
return false;
LValue v = (LValue) o;
return this.luaBinCmpUnknown(Lua.OP_EQ, v );
}
public int luaGetType() {
return Lua.LUA_TNUMBER;
}
/**
* Returns false by default for non-LNumbers, but subclasses of LNumber must
* override.
*/
public abstract boolean isInteger();
/**
* In lua all numbers are strings !
*/
public boolean isString() {
return true;
}
/** Convert to a Byte value */
public Byte toJavaBoxedByte() {
return new Byte(toJavaByte());
}
/** Convert to a boxed Character value */
public Character toJavaBoxedCharacter() {
return new Character(toJavaChar());
}
/** Convert to a boxed Double value */
public Double toJavaBoxedDouble() {
return new Double(toJavaDouble());
}
/** Convert to a boxed Float value */
public Float toJavaBoxedFloat() {
return new Float(toJavaFloat());
}
/** Convert to a boxed Integer value */
public Integer toJavaBoxedInteger() {
return new Integer(toJavaInt());
}
/** Convert to a boxed Long value */
public Long toJavaBoxedLong() {
return new Long(toJavaLong());
}
/** Convert to a boxed Short value */
public Short toJavaBoxedShort() {
return new Short(toJavaShort());
}
/** Convert to a number if possible, or nil otherwise */
public LValue luaToNumber() {
return this;
}
/** Write as a string */
public void luaConcatTo(ByteArrayOutputStream baos) {
luaAsString().luaConcatTo( baos );
}
/** Returns true if this is or can be made into a number */
public boolean isNumber() {
return true;
}
}

View File

@@ -1,77 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
/*
** Function Prototypes
*/
public class LPrototype {
public LPrototype() {
}
public LClosure newClosure(LTable env) {
return new LClosure(this,env);
}
/* constants used by the function */
public LValue[] k;
public int[] code;
/* functions defined inside the function */
public LPrototype[] p;
/* map from opcodes to source lines */
public int[] lineinfo;
/* information about local variables */
public LocVars[] locvars;
/* upvalue names */
public LString[] upvalues;
public LString source;
public int nups;
public int linedefined;
public int lastlinedefined;
public int numparams;
public int is_vararg;
public int maxstacksize;
/** Get the name of a local variable.
*
* @param number the local variable number to look up
* @param pc the program counter
* @return the name, or null if not found
*/
public LString getlocalname(int number, int pc) {
int i;
for (i = 0; i<locvars.length && locvars[i].startpc <= pc; i++) {
if (pc < locvars[i].endpc) { /* is variable active? */
number--;
if (number == 0)
return locvars[i].varname;
}
}
return null; /* not found */
}
public String sourceshort() {
return LoadState.getSourceName(source.toJavaString());
}
}

View File

@@ -1,474 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* A String implementation for Lua using bytes instead of chars.
*
* This should have the following advantages:
*
* (1) We can use strings as byte buffers, as Lua does, and therefore avoid
* questions about how to adapt Lua APIs that use strings with binary data.
*
* (2) Half the memory usage when strings are primarily ASCII
*
*
* TODO: Decide if/when to copy the bytes to a new array to ensure memory does
* not "leak" in the form of unused portions of byte arrays. Currently, for
* efficiency, new LStrings and substrings never create copies.
*/
public class LString extends LValue {
public byte[] m_bytes;
public int m_offset;
public final int m_length;
public final int m_hash;
private static LTable s_stringMT;
public static final LString[] LTYPENAMES;
static {
int n = Lua.TYPE_NAMES.length;
LTYPENAMES = new LString[n];
for ( int i=0; i<n; i++ )
LTYPENAMES[i] = new LString(Lua.TYPE_NAMES[i]);
}
/**
* Construct a Lua string from the given Java string.
* Characters are encoded using UTF-8.
*/
public LString(String string) {
// measure bytes required to encode
int b = lengthAsUtf8( string );
byte[] bytes = new byte[b];
encodeToUtf8( string, bytes, 0 );
this.m_bytes = bytes;
this.m_offset = 0;
this.m_length = b;
this.m_hash = hashBytes( bytes, 0, b );
}
/**
* Convert to Java string using UTF-8 encoding
*/
public String toJavaString() {
char[] c=new char[m_length];
int i, j, b, n=0;
for ( i=m_offset, j=m_offset+m_length; i<j; ) {
if ((b = m_bytes[i++]) == 0)
return new String(c,0,n);
c[n++] = (char) (
(b>=0||i>=j)?
b:
(b<-32||i+1>=j)?
(((b&0x3f) << 6)
| (m_bytes[i++]&0x3f)):
(((b&0xf) << 12)
| ((m_bytes[i++]&0x3f)<<6)
| (m_bytes[i++]&0x3f))
);
}
return new String(c,0,n);
}
/**
* Construct a string from the given byte array.
*
* new LString(b) is identical to new LString(b, 0, b.length)
*/
public LString(byte[] bytes) {
this( bytes, 0, bytes.length );
}
/**
* Construct a string from the given byte array and range. For efficiency,
* the byte array is not copied. Lua strings are immutable so the bytes must
* not be modified after the string is constructed.
*/
public LString(byte[] bytes, int off, int len) {
if ( off < 0 || len < 0 || off+len > bytes.length )
throw new IndexOutOfBoundsException();
this.m_bytes = bytes;
this.m_offset = off;
this.m_length = len;
this.m_hash = hashBytes( bytes, off, len );
}
public static LString newStringCopy(LString src) {
return newStringCopy( src.m_bytes, src.m_offset, src.m_length );
}
public static LString newStringCopy(byte[] buf, int off, int len) {
byte[] b = new byte[len];
System.arraycopy( buf, off, b, 0, len );
return new LString( b, 0, len );
}
public static LString newStringNoCopy(byte[] buf, int off, int len) {
return new LString( buf, off, len );
}
/**
* Count the number of bytes required to encode the string as UTF-8.
*/
public static int lengthAsUtf8(String string) {
int n = string.length();
int b = n;
char c;
for ( int i=0; i<n; i++ ) {
if ( (c = string.charAt(i)) >= 0x80 ) {
++b;
if ( c >= 0x800 )
++b;
}
}
return b;
}
/**
* Encode the given Java string as UTF-8 bytes, writing the result to bytes
* starting at offset. The string should be measured first with lengthAsUtf8
* to make sure the given byte array is large enough.
*/
public static void encodeToUtf8(String string, byte[] bytes, final int startOffset) {
final int n = string.length();
for ( int i=0, j=startOffset; i<n; i++ ) {
int c;
if ( (c = string.charAt(i)) < 0x80 ) {
bytes[j++] = (byte) c;
} else if ( c < 0x800 ) {
bytes[j++] = (byte) (0xC0 | ((c>>6) & 0x1f));
bytes[j++] = (byte) (0x80 | ( c & 0x3f));
} else {
bytes[j++] = (byte) (0xE0 | ((c>>12) & 0x0f));
bytes[j++] = (byte) (0x80 | ((c>>6) & 0x3f));
bytes[j++] = (byte) (0x80 | ( c & 0x3f));
}
}
}
public boolean isString() {
return true;
}
public boolean equals(Object o) {
if ( this == o )
return true;
if ( o != null && o instanceof LString ) {
LString s = (LString) o;
if ( m_hash == s.m_hash && m_length == s.m_length ) {
if ( m_bytes == s.m_bytes && m_offset == s.m_offset )
return true;
if ( equals( m_bytes, m_offset, s.m_bytes, s.m_offset, m_length ) ) {
if ( m_bytes.length < s.m_bytes.length ) {
s.m_bytes = m_bytes;
s.m_offset = m_offset;
} else {
m_bytes = s.m_bytes;
m_offset = s.m_offset;
}
return true;
}
}
}
return false;
}
public int compareTo( LString o ) {
final byte[] a = this.m_bytes;
final byte[] b = o.m_bytes;
int i = this.m_offset;
int j = o.m_offset;
final int imax = i + m_length;
final int jmax = j + o.m_length;
if ( a == b && i == j && imax == jmax )
return 0;
while ( i < imax && j < jmax ) {
if ( a[i] != b[j] ) {
return ( ( (int)a[i] ) & 0x0FF ) - ( ( (int)b[j] ) & 0x0FF );
}
i++;
j++;
}
return m_length - o.m_length;
}
public int hashCode() {
return m_hash;
}
public int length() {
return m_length;
}
public LString substring( int beginIndex, int endIndex ) {
return new LString( m_bytes, m_offset + beginIndex, endIndex - beginIndex );
}
public int charAt( int index ) {
if ( index < 0 || index >= m_length )
throw new IndexOutOfBoundsException();
return luaByte( index );
}
/** Java version of strpbrk, which is a terribly named C function. */
public int indexOfAny( LString accept ) {
final int ilimit = m_offset + m_length;
final int jlimit = accept.m_offset + accept.m_length;
for ( int i = m_offset; i < ilimit; ++i ) {
for ( int j = accept.m_offset; j < jlimit; ++j ) {
if ( m_bytes[i] == accept.m_bytes[j] ) {
return i - m_offset;
}
}
}
return -1;
}
public int indexOf( byte b, int start ) {
for ( int i = m_offset + start; i < m_length; ++i ) {
if ( m_bytes[i] == b )
return i;
}
return -1;
}
public int indexOf( LString s, int start ) {
final int slen = s.length();
final int limit = m_offset + m_length - slen;
for ( int i = m_offset + start; i <= limit; ++i ) {
if ( equals( m_bytes, i, s.m_bytes, s.m_offset, slen ) ) {
return i;
}
}
return -1;
}
public int lastIndexOf( LString s ) {
final int slen = s.length();
final int limit = m_offset + m_length - slen;
for ( int i = limit; i >= m_offset; --i ) {
if ( equals( m_bytes, i, s.m_bytes, s.m_offset, slen ) ) {
return i;
}
}
return -1;
}
public static LString valueOf( double d ) {
return new LString( String.valueOf( d ) );
}
public static LString valueOf( int x ) {
return new LString( String.valueOf( x ) );
}
public static LString valueOf(String s) {
return new LString( s );
}
/**
* Write the specified substring of this string to the given output stream.
*/
public void write( OutputStream os, int offset, int len ) throws IOException {
if ( offset < 0 || len < 0 )
throw new IndexOutOfBoundsException();
if ( offset + len > m_length )
throw new IndexOutOfBoundsException();
os.write( m_bytes, m_offset+offset, len );
}
public void write(OutputStream os) throws IOException {
write(os, 0, m_length);
}
/**
* Copy the bytes of the string into the given byte array.
*/
public void copyInto( int strOffset, byte[] bytes, int arrayOffset, int len ) {
System.arraycopy( m_bytes, m_offset+strOffset, bytes, arrayOffset, len );
}
/**
* Produce an InputStream instance from which the bytes of this LString can be read.
* Underlying byte array is not copied.
*/
public ByteArrayInputStream toInputStream() {
// Well, this is really something.
// Javadoc for java versions 1.3 and earlier states that if reset() is
// called on a ByteArrayInputStream constructed with the 3-argument
// constructor, then bytes 0 .. offset will be returned by the next
// calls to read(). In JDK 1.4, the behavior improved, so that the
// initial mark is set to the initial offset. We still need to
// override ByteArrayInputStream here just in case we run on a
// JVM with the older behavior.
return new ByteArrayInputStream( m_bytes, m_offset, m_length ) {
public synchronized void reset() {
pos = Math.max( m_offset, mark );
}
};
}
public boolean luaBinCmpUnknown(int opcode, LValue lhs) {
return lhs.luaBinCmpString(opcode, this);
}
public boolean luaBinCmpString(int opcode, LString rhs) {
switch ( opcode ) {
case Lua.OP_EQ: return equals(rhs);
case Lua.OP_LT: return compareTo(rhs) < 0;
case Lua.OP_LE: return compareTo(rhs) <= 0;
}
LuaState.vmerror( "bad cmp opcode" );
return false;
}
public LValue luaBinOpDouble( int opcode, double m_value ) {
return luaToNumber().luaBinOpDouble( opcode, m_value );
}
public LValue luaBinOpInteger( int opcode, int m_value ) {
return luaToNumber().luaBinOpInteger( opcode, m_value );
}
public LValue luaBinOpUnknown( int opcode, LValue lhs ) {
return luaToNumber().luaBinOpUnknown( opcode, lhs );
}
public LValue luaUnaryMinus() {
return luaToNumber().luaUnaryMinus();
}
public LValue luaToNumber() {
return luaToNumber( 10 );
}
public LValue luaToNumber( int base ) {
if ( base >= 2 && base <= 36 ) {
String str = toJavaString().trim();
if ( ( base == 10 || base == 16 ) && ( str.startsWith("0x") || str.startsWith("0X") ) ) {
base = 16;
str = str.substring(2);
}
try {
long x = Long.parseLong(str, base);
if (x < Integer.MIN_VALUE || x > Integer.MAX_VALUE)
return new LDouble((double) x);
else
return LInteger.valueOf((int) x);
} catch ( NumberFormatException nfe ) {
if ( base == 10 ) {
try {
return LDouble.numberOf( Double.parseDouble( str ) );
} catch ( NumberFormatException nfe2 ) {
}
}
}
}
return LNil.NIL;
}
public LString luaAsString() {
return this;
}
/** Built-in opcode LEN, for Strings and Tables */
public int luaLength() {
return m_length;
}
public int luaGetType() {
return Lua.LUA_TSTRING;
}
public LTable luaGetMetatable() {
synchronized ( LString.class ) {
return s_stringMT;
}
}
/**
* Get the metatable for all string values. Creates the table if it does not
* exist yet, and sets its __index entry to point to itself.
*
* @return metatable that will be used for all strings
*/
public static synchronized LTable getMetatable() {
if ( s_stringMT == null ) {
s_stringMT = new LTable();
s_stringMT.put( TM_INDEX, s_stringMT );
}
return s_stringMT;
}
public static boolean equals( LString a, int i, LString b, int j, int n ) {
return equals( a.m_bytes, a.m_offset + i, b.m_bytes, b.m_offset + j, n );
}
public static boolean equals( byte[] a, int i, byte[] b, int j, int n ) {
if ( a.length < i + n || b.length < j + n )
return false;
while ( --n>=0 )
if ( a[i++]!=b[j++] )
return false;
return true;
}
private static int hashBytes( byte[] bytes, int offset, int length ) {
// Compute the hash of the given bytes.
// This code comes right out of Lua 5.1.2 (translated from C to Java)
int h = length; /* seed */
int step = (length>>5)+1; /* if string is too long, don't hash all its chars */
for (int l1=length; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+(((int) bytes[offset+l1-1] ) & 0x0FF ));
return h;
}
public int luaByte(int index) {
return m_bytes[m_offset + index] & 0x0FF;
}
public void luaConcatTo(ByteArrayOutputStream baos) {
baos.write( m_bytes, m_offset, m_length );
}
/** Returns true if this is or can be made into a number */
public boolean isNumber() {
return ! this.luaToNumber().isNil();
}
}

View File

@@ -1,683 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
import java.util.Vector;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LString;
import org.luaj.vm.LValue;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
/**
* Simple implementation of table structure for Lua VM. Maintains both an array
* part and a hash part. Does not attempt to achieve the same performance as the
* C version.
*
* Java code can put values in the table or get values out (bypassing the
* metatable, if there is one) using put() and get(). There are specializations
* of put() and get() for integers and Strings to avoid allocating wrapper
* objects when possible.
*
* remove() methods are private: setting a key's value to nil is the correct way
* to remove an entry from the table.
*
*
*/
public class LTable extends LValue {
protected Object[] array;
protected LValue[] hashKeys;
protected Object[] hashValues;
private int hashEntries;
private LTable m_metatable;
private static final int MIN_HASH_CAPACITY = 2;
private static final LValue[] NONE = {};
/** Construct an empty LTable with no initial capacity. */
public LTable() {
array = NONE;
hashKeys = NONE;
}
/**
* Construct an empty LTable that is expected to contain entries with keys
* in the range 1 .. narray and nhash non-integer keys.
*/
public LTable( int narray, int nhash ) {
if ( nhash > 0 && nhash < MIN_HASH_CAPACITY )
nhash = MIN_HASH_CAPACITY;
array = new Object[narray];
hashKeys = new LValue[nhash];
hashValues = new Object[nhash];
}
public boolean isTable() {
return true;
}
/** Get capacity of hash part */
public int getArrayCapacity() {
return array.length;
}
/** Get capacity of hash part */
public int getHashCapacity() {
return hashKeys.length;
}
/**
* Return total number of keys mapped to non-nil values. Not to be confused
* with luaLength, which returns some number n such that the value at n+1 is
* nil.
*
* @deprecated this is not scalable. Does a linear search through the table. Use luaLength() instead.
*/
public int size() {
int count = 0;
for ( int i=array.length; --i>=0; )
if ( array[i] != null )
count++;
for ( int i=hashKeys.length; --i>=0; )
if ( hashKeys[i] != null )
count++;
return count;
}
/**
* Generic put method for all types of keys, but does not use the metatable.
*/
public void put( LValue key, LValue val ) {
if ( key.isInteger() ) {
int pos = key.toJavaInt() - 1;
int n = array.length;
if ( pos>=0 && pos<=n ) {
if ( pos == n )
expandArrayPart();
array[pos] = normalizePut(val);
return;
}
}
hashSet( key, normalizePut(val) );
}
/**
* Method for putting an integer-keyed value. Bypasses the metatable, if
* any.
*/
public void put( int key, LValue val ) {
int pos = key - 1;
int n = array.length;
if ( pos>=0 && pos<=n ) {
if ( pos == n )
expandArrayPart();
array[pos] = normalizePut(val);
} else {
hashSet( LInteger.valueOf(key), normalizePut(val) );
}
}
/**
* Utility method for putting a string-keyed value directly, typically for
* initializing a table. Bypasses the metatable, if any.
*/
public void put( String key, LValue val ) {
hashSet( LString.valueOf(key), normalizePut(val) );
}
/**
* Utility method for putting a string key, int value directly, typically for
* initializing a table. Bypasses the metatable, if any.
*/
public void put( String key, int val ) {
hashSet( LString.valueOf(key), LInteger.valueOf(val) );
}
/**
* Expand the array part of the backing for more values to fit in.
*/
private void expandArrayPart() {
int n = array.length;
int m = Math.max(2,n*2);
arrayExpand(m);
for ( int i=n; i<m; i++ ) {
LInteger k = LInteger.valueOf(i+1);
Object v = hashGet(k);
if ( v != null ) {
hashSet(k, null);
array[i] = v;
}
}
}
/** Check for nil, and convert to null or leave alone
*/
protected Object normalizePut(LValue val) {
return val==LNil.NIL? null: val;
}
/**
* Utility method to directly get the value in a table, without metatable
* calls. Must never return null, use LNil.NIL instead.
*/
public LValue get( LValue key ) {
if ( key.isInteger() ) {
int ikey = key.toJavaInt();
if ( ikey>0 && ikey<=array.length )
return normalizeGet(array[ikey-1]);
}
return normalizeGet(hashGet(key));
}
/** Utility method for retrieving an integer-keyed value */
public LValue get( int key ) {
return normalizeGet( key>0 && key<=array.length?
array[key-1]:
hashGet(LInteger.valueOf(key)) );
}
/** Check for null, and convert to nilor leave alone
*/
protected LValue normalizeGet(Object val) {
return val==null? LNil.NIL: (LValue) val;
}
/**
* Return true if the table contains an entry with the given key,
* false if not. Ignores the metatable.
*/
public boolean containsKey( LValue key ) {
if ( key.isInteger() ) {
int ikey = key.toJavaInt();
if ( ikey>0 && ikey<=array.length )
return null != array[ikey-1];
}
return null != hashGet(key);
}
/**
* Return true if the table contains an entry with the given integer-valued key,
* false if not. Ignores the metatable.
*/
public boolean containsKey( int key ) {
return (key>0 && key<=array.length?
array[key-1] != null:
(hashKeys.length>0 && hashKeys[hashFindSlot(LInteger.valueOf(key))]!=null));
}
private static final int MAX_KEY = 0x3fffffff;
/**
* Try to find a boundary in table `t'. A `boundary' is an integer index
* such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
public int luaLength() {
// find `i' and `j' such that i is present and j is not
int i = 0;
int j = array.length;
if (j<=0 || containsKey(j)) {
if ( hashKeys.length == 0 )
return j;
for ( ++j; containsKey(j) && j < MAX_KEY; j*=2 )
i = j;
}
// binary search
while ( j - i > 1) {
int m = (i+j) / 2;
if ( ! containsKey(m) )
j = m;
else
i = m;
}
return i;
}
/** Valid for tables */
public LTable luaGetMetatable() {
return this.m_metatable;
}
/** Valid for tables */
public LTable luaSetMetatable(LValue metatable) {
if ( m_metatable != null && m_metatable.containsKey(TM_METATABLE) )
throw new LuaErrorException("cannot change a protected metatable");
if ( metatable == null || metatable.isNil() )
this.m_metatable = null;
else if ( metatable.luaGetType() == Lua.LUA_TTABLE ) {
org.luaj.vm.LTable t = (org.luaj.vm.LTable) metatable;
LValue m = t.get(TM_MODE);
if ( m.isString() && m.toJavaString().indexOf('v')>=0 ) {
LTable w = new LWeakTable(this);
w.m_metatable = t;
return w;
}
this.m_metatable = t;
} else {
throw new LuaErrorException("not a table: "+metatable.luaGetTypeName());
}
return this;
}
public String toJavaString() {
return "table: "+id();
}
public int luaGetType() {
return Lua.LUA_TTABLE;
}
/**
* Helper method to get all the keys in this table in an array. Meant to be
* used instead of keys() (which returns an enumeration) when an array is
* more convenient. Note that for a very large table, getting an Enumeration
* instead would be more space efficient.
*
* @deprecated this is not scalable. Does a linear search through the table.
*/
public LValue[] getKeys() {
int n = array.length;
int o = hashKeys.length;
LValue k;
Vector v = new Vector();
// array parts
for ( int pos=0; pos<n; ++pos ) {
if ( array[pos] != null )
v.addElement( LInteger.valueOf( pos+1 ) );
}
// hash parts
for ( int pos=0; pos<o; pos++ ) {
if ( null != (k = hashKeys[pos]) )
v.addElement( k );
}
LValue[] keys = new LValue[ v.size() ];
v.copyInto( keys );
return keys;
}
/**
* Insert element at a position in the list, shifting contiguous elements up.
* @pos index to insert at, or 0 to insert at end.
*/
public void luaInsertPos(int ikey, LValue value) {
if ( ikey == 0 )
ikey = luaLength()+1;
do {
LValue tmp = get(ikey);
put(ikey++, value);
value = tmp;
} while ( ! value.isNil() );
}
/**
* Remove an element from the list, moving contiguous elements down
* @param pos position to remove, or 0 to remove last element
*/
public LValue luaRemovePos(int ikey) {
int n = luaLength();
if ( ikey == 0 )
ikey = n;
if ( ikey <= 0 || ikey > n )
return LNil.NIL;
LValue removed = get(ikey);
LValue replaced;
do {
put(ikey, replaced=get(ikey+1));
ikey++;
} while ( ! replaced.isNil() );
return removed;
}
/**
* Returns the largest positive numerical index of the given table,
* or zero if the table has no positive numerical indices.
* (To do its job this function does a linear traversal of the whole table.)
* @return LValue that is the largest int
*/
public LValue luaMaxN() {
int n = array.length;
int m = hashKeys.length;
int r = Integer.MIN_VALUE;
// array part
for ( int i=n; --i>=0; ) {
if ( array[i] != null ) {
r = i+1;
break;
}
}
// hash part
for ( int i=0; i<m; i++ ) {
LValue key = hashKeys[i];
if ( key != null && key.isInteger() ) {
int k = key.toJavaInt();
if ( k > r )
r = k;
}
}
return LInteger.valueOf( r == Integer.MIN_VALUE? 0: r );
}
// ----------------- sort support -----------------------------
//
// implemented heap sort from wikipedia
//
public void luaSort(LuaState vm, LValue compare) {
heapSort(luaLength(), vm, compare);
}
private void heapSort(int count, LuaState vm, LValue cmpfunc) {
heapify(count, vm, cmpfunc);
for ( int end=count-1; end>0; ) {
swap(end, 0);
siftDown(0, --end, vm, cmpfunc);
}
}
private void heapify(int count, LuaState vm, LValue cmpfunc) {
for ( int start=count/2-1; start>=0; --start )
siftDown(start, count - 1, vm, cmpfunc);
}
private void siftDown(int start, int end, LuaState vm, LValue cmpfunc) {
for ( int root=start; root*2+1 <= end; ) {
int child = root*2+1;
if (child < end && compare(child, child + 1, vm, cmpfunc))
++child;
if (compare(root, child, vm, cmpfunc)) {
swap(root, child);
root = child;
} else
return;
}
}
private boolean compare(int i, int j, LuaState vm, LValue cmpfunc) {
LValue a = get(i+1);
LValue b = get(j+1);
if ( a.isNil() || b.isNil() )
return false;
if ( ! cmpfunc.isNil() ) {
vm.pushlvalue(cmpfunc);
vm.pushlvalue(a);
vm.pushlvalue(b);
vm.call(2, 1);
boolean result = vm.toboolean(-1);
vm.resettop();
return result;
} else {
return b.luaBinCmpUnknown( Lua.OP_LT, a );
}
}
private void swap(int i, int j) {
LValue a = get(i+1);
put(i+1, get(j+1));
put(j+1, a);
}
/**
* Leave key,value pair on top, or nil if at end of list.
* @param vm the LuaState to leave the values on
* @param indexedonly TODO
* @param index index to start search
* @return true if next exists, false if at end of list
*/
public boolean next(LuaState vm, LValue key, boolean indexedonly ) {
int n = array.length;
int m = (indexedonly? -1: hashKeys.length);
int i = findindex(key, n, m);
if ( i < 0 )
vm.error( "invalid key to 'next'" );
// check array part
for ( ; i<n; ++i ) {
Object a = array[i];
if ( a != null ) {
vm.pushinteger(i+1);
vm.pushlvalue(normalizeGet(a));
return true;
} else if ( indexedonly ) {
vm.pushnil();
return false;
}
}
// check hash part
if ( (! indexedonly) ) {
for ( i-=n; i<m; ++i ) {
Object v = hashValues[i];
if ( v != null ) {
LValue k = hashKeys[i];
vm.pushlvalue(k);
vm.pushlvalue(normalizeGet(v));
return true;
}
}
}
// nothing found, push nil, return nil.
vm.pushnil();
return false;
}
private int findindex (LValue key, int n, int m) {
// first iteration
if ( key.isNil() )
return 0;
// is `key' inside array part?
if ( key.isInteger() ) {
int i = key.toJavaInt();
if ( (0 < i) && (i <= n) ) {
if ( array[i-1] == null )
return -1;
return i;
}
}
// array only?
if ( m < 0 )
return n;
// bad index?
if ( m == 0 )
return -1;
// find slot
int slot = hashFindSlot(key);
if ( hashKeys[slot] == null )
return -1;
// return next slot!
return n + slot + 1;
}
/**
* Executes the given f over all elements of table. For each element, f is
* called with the index and respective value as arguments. If f returns a
* non-nil value, then the loop is broken, and this value is returned as the
* final value of foreach.
*
* @param vm
* @param function
* @param indexedonly is a table.foreachi() call, not a table.foreach() call
* @return
*/
public LValue foreach(LuaState vm, LFunction function, boolean indexedonly) {
LValue key = LNil.NIL;
while ( true ) {
// push function onto stack
vm.resettop();
vm.pushlvalue(function);
// get next value
if ( ! next(vm,key,indexedonly) )
return LNil.NIL;
key = vm.topointer(2);
// call function
vm.call(2, 1);
if ( ! vm.isnil(-1) )
return vm.poplvalue();
}
}
// ============== array part ===============
public void arrayExpand(int newLength) {
Object[] v = new Object[newLength];
System.arraycopy(array, 0, v, 0, array.length);
array = v;
}
public void arrayPresize(int minSize) {
if ( array.length < minSize )
arrayExpand(minSize);
}
// ============= Hashtable ================
public void hashSet(LValue key, Object value) {
if ( value == null )
hashRemove(key);
else {
if ( checkLoadFactor() )
rehash();
int slot = hashFindSlot( key );
if ( hashFillSlot( slot, value ) )
return;
hashKeys[slot] = key;
hashValues[slot] = value;
}
}
public Object hashGet(LValue key) {
if ( hashKeys.length <= 0 )
return null;
return hashValues[hashFindSlot(key)];
}
public int hashFindSlot(LValue key) {
int i = ( key.hashCode() & 0x7FFFFFFF ) % hashKeys.length;
// This loop is guaranteed to terminate as long as we never allow the
// table to get 100% full.
LValue k;
while ( ( k = hashKeys[i] ) != null && !k.luaBinCmpUnknown( Lua.OP_EQ, key ) ) {
i = ( i + 1 ) % hashKeys.length;
}
return i;
}
private boolean hashFillSlot( int slot, Object value ) {
hashValues[ slot ] = value;
if ( hashKeys[ slot ] != null ) {
return true;
} else {
++hashEntries;
return false;
}
}
protected void hashRemove( LValue key ) {
if ( hashKeys.length > 0 ) {
int slot = hashFindSlot( key );
hashClearSlot( slot );
}
}
protected void hashClearSlot( int i ) {
if ( hashKeys[ i ] != null ) {
int j = i;
int n = hashKeys.length;
while ( hashKeys[ j = ( ( j + 1 ) % n ) ] != null ) {
final int k = ( ( hashKeys[ j ].hashCode() )& 0x7FFFFFFF ) % n;
if ( ( j > i && ( k <= i || k > j ) ) ||
( j < i && ( k <= i && k > j ) ) ) {
hashKeys[ i ] = hashKeys[ j ];
hashValues[ i ] = hashValues[ j ];
i = j;
}
}
--hashEntries;
hashKeys[ i ] = null;
hashValues[ i ] = null;
if ( hashEntries == 0 ) {
hashKeys = NONE;
hashValues = null;
}
}
}
protected boolean checkLoadFactor() {
// Using a load factor of 2/3 because that is easy to compute without
// overflow or division.
final int hashCapacity = hashKeys.length;
return ( hashCapacity >> 1 ) >= ( hashCapacity - hashEntries );
}
protected void rehash() {
final int oldCapacity = hashKeys.length;
final int newCapacity = ( oldCapacity > 0 ) ? 2 * oldCapacity : MIN_HASH_CAPACITY;
final LValue[] oldKeys = hashKeys;
final Object[] oldValues = hashValues;
hashKeys = new LValue[ newCapacity ];
hashValues = new Object[ newCapacity ];
for ( int i = 0; i < oldCapacity; ++i ) {
final LValue k = oldKeys[i];
if ( k != null ) {
final Object v = oldValues[i];
final int slot = hashFindSlot( k );
hashKeys[slot] = k;
hashValues[slot] = v;
}
}
}
}

View File

@@ -1,182 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
/**
* Implementation of lua coroutines using Java Threads
*/
public class LThread extends LValue implements Runnable {
private static final boolean USE_JAVA_THREADS = true;
private static final int STATUS_SUSPENDED = 0;
private static final int STATUS_RUNNING = 1;
private static final int STATUS_NORMAL = 2;
private static final int STATUS_DEAD = 3;
private static final String[] NAMES = {
"suspended",
"running",
"normal",
"dead" };
private int status = STATUS_SUSPENDED;
public final LuaState vm;
private Thread thread;
static LThread running;
public LThread(LFunction c, LTable env) {
vm = new LuaState(env);
vm.pushlvalue(c);
}
public int luaGetType() {
return Lua.LUA_TTHREAD;
}
public String toJavaString() {
return "thread: "+hashCode();
}
// Set the environment if a thread, or closure, and return 1, otherwise return 0
public boolean luaSetEnv(LTable t) {
vm._G = t;
return true;
}
public String getStatus() {
return NAMES[status];
}
public static LThread getRunning() {
return running;
}
public void run() {
synchronized ( this ) {
try {
vm.execute();
} finally {
status = STATUS_DEAD;
this.notify();
}
}
}
public void yield() {
synchronized ( this ) {
if ( status != STATUS_RUNNING )
vm.error(this+" not running");
status = STATUS_SUSPENDED;
if ( USE_JAVA_THREADS ) {
this.notify();
try {
this.wait();
status = STATUS_RUNNING;
} catch ( InterruptedException e ) {
status = STATUS_DEAD;
vm.error(this+" "+e);
}
}
}
}
// This needs to leave any values returned by yield in the coroutine
// on the calling vm stack
// @param vm
// @param nargs
//
public void resumeFrom(LuaState vm, int nargs) {
synchronized ( this ) {
if ( status == STATUS_DEAD ) {
vm.resettop();
vm.pushboolean(false);
vm.pushstring("cannot resume dead coroutine");
return;
}
// set prior thread to normal status while we are running
LThread prior = running;
try {
// set our status to running
if ( prior != null )
prior.status = STATUS_NORMAL;
running = this;
status = STATUS_RUNNING;
// copy args in
if (this.vm.cc < 0) {
vm.xmove(this.vm, nargs);
this.vm.prepStackCall();
} else {
this.vm.resettop();
vm.xmove(this.vm, nargs);
}
// execute in the other thread
if ( USE_JAVA_THREADS ) {
// start the thread
if ( thread == null ) {
thread = new Thread(this);
thread.start();
}
// run this vm until it yields
this.notify();
this.wait();
} else {
// run this vm until it yields
while (this.vm.cc >= 0 && status == STATUS_RUNNING)
this.vm.exec();
}
// copy return values from yielding stack state
vm.resettop();
if ( this.vm.cc >= 0 ) {
vm.pushboolean(status != STATUS_DEAD);
this.vm.xmove(vm, this.vm.gettop());
} else {
vm.pushboolean(true);
this.vm.base = 0;
this.vm.xmove(vm, this.vm.gettop());
}
} catch ( Throwable t ) {
status = STATUS_DEAD;
vm.resettop();
vm.pushboolean(false);
vm.pushstring("thread: "+t);
if ( USE_JAVA_THREADS ) {
this.notify();
}
} finally {
// previous thread is now running again
running = prior;
}
}
}
}

View File

@@ -1,73 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class LUserData extends LValue {
public final Object m_instance;
public LTable m_metatable;
public LUserData(Object obj) {
m_instance = obj;
}
public LUserData(Object obj, LTable metatable) {
m_instance = obj;
m_metatable = metatable;
}
public String toJavaString() {
return String.valueOf(m_instance);
}
public boolean equals(Object obj) {
return (this == obj) ||
(obj instanceof LUserData && this.m_instance == ((LUserData) obj).m_instance);
}
public int hashCode() {
return System.identityHashCode( m_instance );
}
public int luaGetType() {
return Lua.LUA_TUSERDATA;
}
public LTable luaGetMetatable() {
return m_metatable;
}
public Object toJavaInstance() {
return m_instance;
}
public boolean luaBinCmpUnknown( int opcode, LValue lhs ) {
if ( opcode == Lua.OP_EQ )
return lhs.equals( this );
return super.luaBinCmpUnknown( opcode, lhs );
}
public boolean isUserData() {
return true;
}
}

View File

@@ -1,363 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
import java.io.ByteArrayOutputStream;
abstract
public class LValue {
/** Metatable tag for intercepting table gets */
public static final LString TM_INDEX = new LString("__index");
/** Metatable tag for intercepting table sets */
public static final LString TM_NEWINDEX = new LString("__newindex");
/** Metatable tag for intercepting table sets */
public static final LString TM_METATABLE = new LString("__metatable");
/** Metatable tag for setting table mode */
public static final LString TM_MODE = new LString("__mode");
private static final int MAXTAGLOOP = 100;
protected void conversionError(String target) {
throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target );
}
private static LValue arithmeticError( Object type ) {
throw new LuaErrorException( "attempt to perform arithmetic on ? (a "+type+" value)" );
}
protected static LValue compareError( Object typea, Object typeb ) {
throw new LuaErrorException( "attempt to compare "+typea+" with "+typeb );
}
private LValue indexError(LuaState vm, LValue nontable) {
vm.error( "attempt to index ? (a "+nontable.luaGetTypeName()+" value)" );
return LNil.NIL;
}
public String id() {
return Integer.toHexString(hashCode());
}
/** Return true if this value can be represented as an "int" */
public boolean isInteger() {
return false;
}
/** Return true if this value is LNil.NIL, false otherwise */
public boolean isNil() {
return false;
}
// perform a lua call, return true if the call is to a lua function, false
// if it ran to completion.
public boolean luaStackCall(LuaState vm) {
vm.error("attempt to call "+this);
return false;
}
// unsupported except for numbers
public LValue luaBinOpUnknown(int opcode, LValue lhs) {
return arithmeticError(luaGetTypeName());
}
// unsupported except for numbers
public LValue luaBinOpInteger(int opcode, int m_value) {
return arithmeticError(luaGetTypeName());
}
// unsupported except for numbers
public LValue luaBinOpDouble(int opcode, double m_value) {
return arithmeticError(luaGetTypeName());
}
// unsupported except for numbers, strings, and == with various combinations of Nil, Boolean, etc.
public boolean luaBinCmpUnknown(int opcode, LValue lhs) {
if ( opcode == Lua.OP_EQ )
return lhs == this;
compareError(lhs.luaGetTypeName(), luaGetTypeName());
return false;
}
// unsupported except for strings
public boolean luaBinCmpString(int opcode, LString rhs) {
if ( opcode == Lua.OP_EQ )
return false;
compareError(luaGetTypeName(), "string");
return false;
}
// unsupported except for numbers
public boolean luaBinCmpInteger(int opcode, int rhs) {
if ( opcode == Lua.OP_EQ )
return false;
compareError(luaGetTypeName(), "number");
return false;
}
// unsupported except for numbers
public boolean luaBinCmpDouble(int opcode, double rhs) {
if ( opcode == Lua.OP_EQ )
return false;
compareError(luaGetTypeName(), "number");
return false;
}
/** Dispatch a settable operation.
* Default method delegates back to the vm for metatable processing.
*/
public void luaSetTable(LuaState vm, LValue key, LValue val) {
vm.luaV_settable(this, key, val);
}
/** Dispatch a gettable operation.
* Default method delegates back to the vm for metatable processing.
*/
public LValue luaGetTable(LuaState vm, LValue key) {
return vm.luaV_gettable(this, key);
}
/** Get the value as a LString
*/
public LString luaAsString() {
return new LString(toJavaString());
}
/** Override standard toString with lua String conversion by default */
public String toString() {
return toJavaString();
}
/** Arithmetic negative */
public LValue luaUnaryMinus() {
return arithmeticError(luaGetTypeName());
}
/** Built-in opcode LEN, for Strings and Tables */
public int luaLength() {
throw new LuaErrorException( "attempt to get length of ? (a "+luaGetTypeName()+" value)" );
}
/**
* Valid for all types: get a metatable. Only tables and userdata can have a
* different metatable per instance, though, other types are restricted to
* one metatable per type.
*
* Since metatables on non-tables can only be set through Java and not Lua,
* this function should be overridden for each value type as necessary.
*
* @return null if there is no meta-table
*/
public LTable luaGetMetatable() {
return null;
}
/** Valid for tables
* @param the new LTable, or null or LNil.NIL to reset the metatable to none
* @return this if unchanged, or new LTable if copied using weak table
*/
public LTable luaSetMetatable(LValue metatable) {
throw new LuaErrorException( "cannot set metatable for "+this.luaGetTypeName());
}
/** Valid for all types: return the int value identifying the type of this value */
abstract public int luaGetType();
/** Valid for all types: return the type of this value as an LString */
public LString luaGetTypeName() {
return LString.LTYPENAMES[luaGetType()];
}
/** Convert to a Java String */
public String toJavaString() {
return null;
}
/** Return value as a boolean */
public boolean toJavaBoolean() {
return true;
}
/** Return value as a byte */
public byte toJavaByte() {
conversionError("number");
return 0;
}
/** Return value as a char */
public char toJavaChar() {
conversionError("number");
return 0;
}
/** Return value as a double */
public double toJavaDouble() {
conversionError("number");
return 0;
}
/** Return value as a float */
public float toJavaFloat() {
conversionError("number");
return 0;
}
/** Return value as an integer */
public int toJavaInt() {
conversionError("number");
return 0;
}
/** Return value as a long */
public long toJavaLong() {
conversionError("number");
return 0;
}
/** Return value as a double */
public short toJavaShort() {
conversionError("number");
return 0;
}
/** Convert to a Boolean value */
public Boolean toJavaBoxedBoolean() {
conversionError("Boolean");
return null;
}
/** Convert to a Byte value */
public Byte toJavaBoxedByte() {
conversionError("Byte");
return null;
}
/** Convert to a boxed Character value */
public Character toJavaBoxedCharacter() {
conversionError("Character");
return null;
}
/** Convert to a boxed Double value */
public Double toJavaBoxedDouble() {
conversionError("Double");
return null;
}
/** Convert to a boxed Float value */
public Float toJavaBoxedFloat() {
conversionError("Float");
return null;
}
/** Convert to a boxed Integer value */
public Integer toJavaBoxedInteger() {
conversionError("Integer");
return null;
}
/** Convert to a boxed Long value */
public Long toJavaBoxedLong() {
conversionError("Long");
return null;
}
/** Convert to a boxed Short value */
public Short toJavaBoxedShort() {
conversionError("Short");
return null;
}
/** Convert to a Java Object iff this is a LUserData value */
public Object toJavaInstance() {
conversionError("instance");
return null;
}
/** Set the environment if a thread, or closure, and return true, otherwise return false */
public boolean luaSetEnv(LTable t) {
return false;
}
/** Get the environment of the object if it is a closure, or d if not a closure.
* @param d global environment to return if this is not a closure
*/
public LTable luaGetEnv(LTable d) {
return d;
}
/** Convert to a number if possible, or nil otherwise */
public LValue luaToNumber() {
return LNil.NIL;
}
/** Dereference a potentially weak reference, and return the value */
public LValue toStrongReference() {
return this;
}
/** Concatenate this value to a ByteArrayOutputStream */
public void luaConcatTo(ByteArrayOutputStream baos) {
throw new LuaErrorException( "attempt to concatenate "+luaGetTypeName() );
}
/** Return true if this is a lua string, meaning it is
* either a LString or LNumber,since all numbers are
* convertible to strings in lua
*/
public boolean isString() {
return false;
}
/** Return true if this is a LTable */
public boolean isTable() {
return false;
}
/** Return true if this is a LFunction */
public boolean isFunction() {
return false;
}
/** Returns true if this is an LUserData */
public boolean isUserData() {
return false;
}
/** Returns true if this is or can be made into a number */
public boolean isNumber() {
return false;
}
/** Returns true if this is a lua closure, false otherwise */
public boolean isClosure() {
return false;
}
}

View File

@@ -1,112 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.vm;
import java.lang.ref.WeakReference;
import org.luaj.vm.LNil;
import org.luaj.vm.LValue;
public class LWeakTable extends LTable {
public LWeakTable() {
super();
}
public LWeakTable(int narray, int nhash) {
super(narray, nhash);
}
public LWeakTable(LTable copy) {
super( copy.array.length, copy.hashKeys.length );
for ( int i=0, k=1, n=copy.array.length; i<n; i++, k++ )
this.put( k, copy.get(k) );
for ( int i=0, n=copy.hashKeys.length; i<n; i++ ) {
LValue k = copy.hashKeys[i];
if ( k != null )
this.put( k, copy.get(k) );
}
}
protected LValue normalizeGet(Object val) {
if ( val instanceof WeakReference )
val = ((WeakReference)val).get();
else if ( val instanceof LUserData ) {
LUserData ud = (LUserData) val;
Object o = ((WeakReference) ud.m_instance).get();
if ( o != null )
val = new LUserData(o, ud.m_metatable);
else
val = LNil.NIL;
}
return val==null? LNil.NIL: (LValue) val;
}
protected Object normalizePut(LValue val) {
if ( val.isNil() ) {
return null;
} else if ( val.isUserData() ) {
LUserData ud = (LUserData) val;
return new LUserData(new WeakReference(ud.m_instance), ud.m_metatable);
} else {
return new WeakReference(val);
}
}
public boolean next(LuaState vm, LValue key, boolean indexedonly) {
while ( super.next(vm, key, indexedonly) ) {
if ( ! vm.isnil(-1) )
return true;
vm.pop(1);
key = vm.poplvalue();
}
return false;
}
protected void rehash() {
final LValue[] keys = this.hashKeys;
final Object[] values = this.hashValues;
final int n = hashKeys.length;
for ( int i = 0; i < n; ++i ) {
if ( keys[i] != null && normalizeGet(values[i]).isNil() ) {
// key has dropped out, clear the slot
// It's necessary to call hashClearSlot instead of just nulling
// out the slot because the table must be left in a consistent
// state if an OutOfMemoryError occurs later in the rehash
// process.
hashClearSlot(i);
// If number of hash entries gets to zero, hashClearSlot will
// set hashKeys back to an empty array. Check for that so we
// don't have an out-of-bounds index operation.
if ( hashKeys != keys )
break;
}
}
// check load factor again since rehash might not be required if enough
// entries dropped out.
if ( checkLoadFactor() )
super.rehash();
}
}

View File

@@ -1,298 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.luaj.compiler.DumpState;
/*
** Function Prototypes
*/
public class LoadState {
/** Interface for the compiler, if it is installed. */
public interface LuaCompiler {
public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException;
}
/** Compiler instance, if installed */
public static LuaCompiler compiler = null;
/** Signature byte indicating the file is a compiled binary chunk */
private static final byte[] LUA_SIGNATURE = { '\033', 'L', 'u', 'a' };
/** Name for compiled chunks */
public static final String SOURCE_BINARY_STRING = "binary string";
/** for header of binary files -- this is Lua 5.1 */
public static final int LUAC_VERSION = 0x51;
/** for header of binary files -- this is the official format */
public static final int LUAC_FORMAT = 0;
/** size of header of binary files */
public static final int LUAC_HEADERSIZE = 12;
// values read from the header
private int luacVersion;
private int luacFormat;
private boolean luacLittleEndian;
private int luacSizeofInt;
private int luacSizeofSizeT;
private int luacSizeofInstruction;
private int luacSizeofLuaNumber;
private int luacNumberFormat;
/** input stream from which we are loading */
private DataInputStream is;
/** Name of what is being loaded? */
String name;
/** The VM doing the loading */
LuaState L;
/** Read buffer */
private byte[] buf = new byte[512];
private static int[] EMPTY_INT_ARRAY = {};
int loadInt() throws IOException {
is.readFully(buf,0,4);
return luacLittleEndian?
(buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]):
(buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]);
}
int[] loadIntArray() throws IOException {
int n = loadInt();
if ( n == 0 )
return EMPTY_INT_ARRAY;
// read all data at once
int m = n << 2;
if ( buf.length < m )
buf = new byte[m];
is.readFully(buf,0,m);
int[] array = new int[n];
for ( int i=0, j=0; i<n; ++i, j+=4 )
array[i] = luacLittleEndian?
(buf[j+3] << 24) | ((0xff & buf[j+2]) << 16) | ((0xff & buf[j+1]) << 8) | (0xff & buf[j+0]):
(buf[j+0] << 24) | ((0xff & buf[j+1]) << 16) | ((0xff & buf[j+2]) << 8) | (0xff & buf[j+3]);
return array;
}
long loadInt64() throws IOException {
int a,b;
if ( this.luacLittleEndian ) {
a = loadInt();
b = loadInt();
} else {
b = loadInt();
a = loadInt();
}
return (((long)b)<<32) | (((long)a)&0xffffffffL);
}
LString loadString() throws IOException {
int size = loadInt();
if ( size == 0 )
return null;
byte[] bytes = new byte[size];
is.readFully( bytes, 0, size );
return new LString( bytes, 0, bytes.length - 1 );
}
public static LNumber longBitsToLuaNumber( long bits ) {
if ( ( bits & ( ( 1L << 63 ) - 1 ) ) == 0L ) {
return LInteger.valueOf( 0 );
}
int e = (int)((bits >> 52) & 0x7ffL) - 1023;
if ( e >= 0 && e < 31 ) {
long f = bits & 0xFFFFFFFFFFFFFL;
int shift = 52 - e;
long intPrecMask = ( 1L << shift ) - 1;
if ( ( f & intPrecMask ) == 0 ) {
int intValue = (int)( f >> shift ) | ( 1 << e );
return LInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue );
}
}
double value = Double.longBitsToDouble(bits);
return LDouble.numberOf( value );
}
LNumber loadNumber() throws IOException {
if ( luacNumberFormat == DumpState.NUMBER_FORMAT_INTS_ONLY ) {
return LInteger.valueOf( loadInt() );
} else {
return longBitsToLuaNumber( loadInt64() );
}
}
void loadConstants(LPrototype f) throws IOException {
int n = loadInt();
LValue[] values = new LValue[n];
for ( int i=0; i<n; i++ ) {
switch ( is.readByte() ) {
case Lua.LUA_TNIL:
values[i] = LNil.NIL;
break;
case Lua.LUA_TBOOLEAN:
values[i] = (0 != is.readUnsignedByte()? LBoolean.TRUE: LBoolean.FALSE);
break;
case Lua.LUA_TINT:
values[i] = LInteger.valueOf( loadInt() );
break;
case Lua.LUA_TNUMBER:
values[i] = loadNumber();
break;
case Lua.LUA_TSTRING:
values[i] = loadString();
break;
default:
throw new IllegalStateException("bad constant");
}
}
f.k = values;
n = loadInt();
LPrototype[] protos = new LPrototype[n];
for ( int i=0; i<n; i++ )
protos[i] = loadFunction(f.source);
f.p = protos;
}
void loadDebug( LPrototype f ) throws IOException {
f.lineinfo = loadIntArray();
int n = loadInt();
f.locvars = new LocVars[n];
for ( int i=0; i<n; i++ ) {
LString varname = loadString();
int startpc = loadInt();
int endpc = loadInt();
f.locvars[i] = new LocVars(varname, startpc, endpc);
}
n = loadInt();
f.upvalues = new LString[n];
for ( int i=0; i<n; i++ ) {
f.upvalues[i] = loadString();
}
}
public LPrototype loadFunction(LString p) throws IOException {
LPrototype f = new LPrototype();
// this.L.push(f);
f.source = loadString();
if ( f.source == null )
f.source = p;
f.linedefined = loadInt();
f.lastlinedefined = loadInt();
f.nups = is.readUnsignedByte();
f.numparams = is.readUnsignedByte();
f.is_vararg = is.readUnsignedByte();
f.maxstacksize = is.readUnsignedByte();
f.code = loadIntArray();
loadConstants(f);
loadDebug(f);
// TODO: add check here, for debugging purposes, I believe
// see ldebug.c
// IF (!luaG_checkcode(f), "bad code");
// this.L.pop();
return f;
}
public void loadHeader() throws IOException {
luacVersion = is.readByte();
luacFormat = is.readByte();
luacLittleEndian = (0 != is.readByte());
luacSizeofInt = is.readByte();
luacSizeofSizeT = is.readByte();
luacSizeofInstruction = is.readByte();
luacSizeofLuaNumber = is.readByte();
luacNumberFormat = is.readByte();
}
public static LPrototype undump( LuaState L, InputStream stream, String name ) throws IOException {
// check first byte to see if its a precompiled chunk
int c = stream.read();
if ( c != LUA_SIGNATURE[0] ) {
if ( compiler != null )
return compiler.compile(c, stream, name);
throw new IllegalArgumentException("no compiler");
}
// check rest of signature
for ( int i=1; i<4; i++ ) {
if ( stream.read() != LUA_SIGNATURE[i] )
throw new IllegalArgumentException("bad signature");
}
// load file as a compiled chunk
String sname = getSourceName(name);
LoadState s = new LoadState( L, stream, sname );
s.loadHeader();
// check format
switch ( s.luacNumberFormat ) {
case DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES:
case DumpState.NUMBER_FORMAT_INTS_ONLY:
case DumpState.NUMBER_FORMAT_NUM_PATCH_INT32:
break;
default:
L.error("unsupported int size");
}
return s.loadFunction( LString.valueOf(sname) );
}
public static String getSourceName(String name) {
String sname = name;
if ( name.startsWith("@") || name.startsWith("=") )
sname = name.substring(1);
else if ( name.startsWith("\033") )
sname = SOURCE_BINARY_STRING;
return sname;
}
/** Private constructor for create a load state */
private LoadState( LuaState L, InputStream stream, String name ) {
this.L = L;
this.name = name;
this.is = new DataInputStream( stream );
}
}

View File

@@ -1,36 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class LocVars {
public LString varname;
public int startpc;
public int endpc;
public LocVars(LString varname, int startpc, int endpc) {
this.varname = varname;
this.startpc = startpc;
this.endpc = endpc;
}
}

View File

@@ -1,360 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
/**
* Constants for lua limits and opcodes
*
*/
public class Lua {
/** version is supplied by ant build task */
public static final String _VERSION = "Luaj 0.0";
/** use return values from previous op */
public static final int LUA_MULTRET = -1;
/** masks for new-style vararg */
public static final int VARARG_HASARG = 1;
public static final int VARARG_ISVARARG = 2;
public static final int VARARG_NEEDSARG = 4;
// from lopcodes.h
/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
`A' : 8 bits
`B' : 9 bits
`C' : 9 bits
`Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
represented by 2*max), which is half the maximum for the corresponding
unsigned argument.
===========================================================================*/
/* basic instruction format */
public static final int iABC = 0;
public static final int iABx = 1;
public static final int iAsBx = 2;
/*
** size and position of opcode arguments.
*/
public static final int SIZE_C = 9;
public static final int SIZE_B = 9;
public static final int SIZE_Bx = (SIZE_C + SIZE_B);
public static final int SIZE_A = 8;
public static final int SIZE_OP = 6;
public static final int POS_OP = 0;
public static final int POS_A = (POS_OP + SIZE_OP);
public static final int POS_C = (POS_A + SIZE_A);
public static final int POS_B = (POS_C + SIZE_C);
public static final int POS_Bx = POS_C;
public static final int MAX_OP = ((1<<SIZE_OP)-1);
public static final int MAXARG_A = ((1<<SIZE_A)-1);
public static final int MAXARG_B = ((1<<SIZE_B)-1);
public static final int MAXARG_C = ((1<<SIZE_C)-1);
public static final int MAXARG_Bx = ((1<<SIZE_Bx)-1);
public static final int MAXARG_sBx = (MAXARG_Bx>>1); /* `sBx' is signed */
public static final int MASK_OP = ((1<<SIZE_OP)-1)<<POS_OP;
public static final int MASK_A = ((1<<SIZE_A)-1)<<POS_A;
public static final int MASK_B = ((1<<SIZE_B)-1)<<POS_B;
public static final int MASK_C = ((1<<SIZE_C)-1)<<POS_C;
public static final int MASK_Bx = ((1<<SIZE_Bx)-1)<<POS_Bx;
public static final int MASK_NOT_OP = ~MASK_OP;
public static final int MASK_NOT_A = ~MASK_A;
public static final int MASK_NOT_B = ~MASK_B;
public static final int MASK_NOT_C = ~MASK_C;
public static final int MASK_NOT_Bx = ~MASK_Bx;
/*
** the following macros help to manipulate instructions
*/
public static int GET_OPCODE(int i) {
return (i >> POS_OP) & MAX_OP;
}
public static int GETARG_A(int i) {
return (i >> POS_A) & MAXARG_A;
}
public static int GETARG_B(int i) {
return (i >> POS_B) & MAXARG_B;
}
public static int GETARG_C(int i) {
return (i >> POS_C) & MAXARG_C;
}
public static int GETARG_Bx(int i) {
return (i >> POS_Bx) & MAXARG_Bx;
}
public static int GETARG_sBx(int i) {
return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx;
}
/*
** Macros to operate RK indices
*/
/** this bit 1 means constant (0 means register) */
public static final int BITRK = (1 << (SIZE_B - 1));
/** test whether value is a constant */
public static boolean ISK(int x) {
return 0 != ((x) & BITRK);
}
/** gets the index of the constant */
public static int INDEXK(int r) {
return ((int)(r) & ~BITRK);
}
public static final int MAXINDEXRK = (BITRK - 1);
/** code a constant index as a RK value */
public static int RKASK(int x) {
return ((x) | BITRK);
}
/**
** invalid register that fits in 8 bits
*/
public static final int NO_REG = MAXARG_A;
/*
** R(x) - register
** Kst(x) - constant (in constant table)
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
*/
/*
** grep "ORDER OP" if you change these enums
*/
/*----------------------------------------------------------------------
name args description
------------------------------------------------------------------------*/
public static final int OP_MOVE = 0;/* A B R(A) := R(B) */
public static final int OP_LOADK = 1;/* A Bx R(A) := Kst(Bx) */
public static final int OP_LOADBOOL = 2;/* A B C R(A) := (Bool)B; if (C) pc++ */
public static final int OP_LOADNIL = 3; /* A B R(A) := ... := R(B) := nil */
public static final int OP_GETUPVAL = 4; /* A B R(A) := UpValue[B] */
public static final int OP_GETGLOBAL = 5; /* A Bx R(A) := Gbl[Kst(Bx)] */
public static final int OP_GETTABLE = 6; /* A B C R(A) := R(B)[RK(C)] */
public static final int OP_SETGLOBAL = 7; /* A Bx Gbl[Kst(Bx)] := R(A) */
public static final int OP_SETUPVAL = 8; /* A B UpValue[B] := R(A) */
public static final int OP_SETTABLE = 9; /* A B C R(A)[RK(B)] := RK(C) */
public static final int OP_NEWTABLE = 10; /* A B C R(A) := {} (size = B,C) */
public static final int OP_SELF = 11; /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
public static final int OP_ADD = 12; /* A B C R(A) := RK(B) + RK(C) */
public static final int OP_SUB = 13; /* A B C R(A) := RK(B) - RK(C) */
public static final int OP_MUL = 14; /* A B C R(A) := RK(B) * RK(C) */
public static final int OP_DIV = 15; /* A B C R(A) := RK(B) / RK(C) */
public static final int OP_MOD = 16; /* A B C R(A) := RK(B) % RK(C) */
public static final int OP_POW = 17; /* A B C R(A) := RK(B) ^ RK(C) */
public static final int OP_UNM = 18; /* A B R(A) := -R(B) */
public static final int OP_NOT = 19; /* A B R(A) := not R(B) */
public static final int OP_LEN = 20; /* A B R(A) := length of R(B) */
public static final int OP_CONCAT = 21; /* A B C R(A) := R(B).. ... ..R(C) */
public static final int OP_JMP = 22; /* sBx pc+=sBx */
public static final int OP_EQ = 23; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
public static final int OP_LT = 24; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
public static final int OP_LE = 25; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
public static final int OP_TEST = 26; /* A C if not (R(A) <=> C) then pc++ */
public static final int OP_TESTSET = 27; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
public static final int OP_CALL = 28; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_TAILCALL = 29; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_RETURN = 30; /* A B return R(A), ... ,R(A+B-2) (see note) */
public static final int OP_FORLOOP = 31; /* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
public static final int OP_FORPREP = 32; /* A sBx R(A)-=R(A+2); pc+=sBx */
public static final int OP_TFORLOOP = 33; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
public static final int OP_SETLIST = 34; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
public static final int OP_CLOSE = 35; /* A close all variables in the stack up to (>=) R(A)*/
public static final int OP_CLOSURE = 36; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
public static final int OP_VARARG = 37; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
public static final int NUM_OPCODES = OP_VARARG + 1;
/*===========================================================================
Notes:
(*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
and can be 0: OP_CALL then sets `top' to last_result+1, so
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
(*) In OP_RETURN, if (B == 0) then return up to `top'
(*) In OP_SETLIST, if (B == 0) then B = `top';
if (C == 0) then next `instruction' is real C
(*) For comparisons, A specifies what condition the test should accept
(true or false).
(*) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/
/*
** masks for instruction properties. The format is:
** bits 0-1: op mode
** bits 2-3: C arg mode
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test
*/
public static final int OpArgN = 0; /* argument is not used */
public static final int OpArgU = 1; /* argument is used */
public static final int OpArgR = 2; /* argument is a register or a jump offset */
public static final int OpArgK = 3; /* argument is a constant or register/constant */
public static final int[] luaP_opmodes = {
/* T A B C mode opcode */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_MOVE */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_LOADK */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_LOADBOOL */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LOADNIL */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_GETUPVAL */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_GETGLOBAL */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABLE */
(0<<7) | (0<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_SETGLOBAL */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_SETUPVAL */
(0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABLE */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_NEWTABLE */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_SELF */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_ADD */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */
(0<<7) | (0<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_JMP */
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_EQ */
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LT */
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LE */
(1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TEST */
(1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TESTSET */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_CALL */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_TAILCALL */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_RETURN */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORLOOP */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORPREP */
(1<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TFORLOOP */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_SETLIST */
(0<<7) | (0<<6) | (OpArgN<<4) | (OpArgN<<2) | (iABC), /* OP_CLOSE */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABx), /* OP_CLOSURE */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_VARARG */
};
public static int getOpMode(int m) {
return luaP_opmodes[m] & 3;
}
public static int getBMode(int m) {
return (luaP_opmodes[m] >> 4) & 3;
}
public static int getCMode(int m) {
return (luaP_opmodes[m] >> 2) & 3;
}
public static boolean testAMode(int m) {
return 0 != (luaP_opmodes[m] & (1 << 6));
}
public static boolean testTMode(int m) {
return 0 != (luaP_opmodes[m] & (1 << 7));
}
/* number of list items to accumulate before a SETLIST instruction */
public static final int LFIELDS_PER_FLUSH = 50;
// type constants
public static final int LUA_TINT = (-2);
public static final int LUA_TNONE = (-1);
public static final int LUA_TNIL = 0;
public static final int LUA_TBOOLEAN = 1;
public static final int LUA_TLIGHTUSERDATA = 2;
public static final int LUA_TNUMBER = 3;
public static final int LUA_TSTRING = 4;
public static final int LUA_TTABLE = 5;
public static final int LUA_TFUNCTION = 6;
public static final int LUA_TUSERDATA = 7;
public static final int LUA_TTHREAD = 8;
public static final int LUA_TVALUE = 9;
public static final String[] TYPE_NAMES = {
"nil",
"boolean",
"lightuserdata",
"number",
"string",
"table",
"function",
"userdata",
"thread",
"value",
};
}

View File

@@ -1,91 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
/**
* RuntimeException that is thrown and caught in response to a lua error.
* This error does not indicate any problem with the normal functioning
* of the Lua VM, but rather indicates that the lua script being interpreted
* has encountered a lua error, eigher via LuaState.error() or lua error() calls.
*
*/
public class LuaErrorException extends RuntimeException {
private static final String DEFAULT_MESSAGE = "lua error";
/**
* Construct a LuaErrorException with the default message.
*/
public LuaErrorException() {
this(DEFAULT_MESSAGE);
}
/**
* Construct a LuaErrorException in response to a Throwable that was caught
* and with the default message.
*/
public LuaErrorException(Throwable cause) {
this(DEFAULT_MESSAGE+": "+cause);
}
/**
* Construct a LuaErrorException with a specific message.
*
* @param message message to supply
*/
public LuaErrorException(String message) {
this(null, message, -1);
}
/**
* Construct the message around a specific vm and with a particular level of debug info
* @param vm
* @param message
* @param level 0 for no message, >=1 for current call or above, -1 for most recent lua call
*/
public LuaErrorException(LuaState vm, String message, int level) {
super( addLineInfo( vm, message, level ) );
}
/**
* Append line info as per level
* @param vm
* @param message
* @param level
* @return
*/
private static String addLineInfo(LuaState vm, String message, int level) {
// add position information
if ( vm == null ) {
if ( LThread.running != null )
vm = LThread.running.vm;
else
vm = LuaState.mainState;
if ( vm == null )
return message;
}
if ( level > 0 ) {
message = vm.getFileLine(level);
}
return vm.luaV_call_errfunc( message );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,186 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
import java.io.InputStream;
import java.io.Reader;
/**
* Singleton to manage platform-specific behaviors.
* <p>
* Here is the sample code to set up the platform instance and create a new
* LuaState instance.
* <pre>
* Platform.setInstance(new J2meMidp20Cldc11Platform());
* LuaState vm = Platform.newLuaState();
* </pre>
*/
abstract public class Platform {
/**
* When non-null, name of a Java Class that implements LuaState
* and has a default constructor which will be used to construct
* a new lua state using Platform.newLuaState()
* @see newLuaState
*/
public static String LUA_STATE_CLASS_NAME = null;
/**
* The singleton Platform instance in use by this JVM
*/
private static Platform instance;
/**
* Singleton to be used for platform operations.
*
* The default Platform gets files as resources, and converts them to
* characters using the default InputStreamReader class.
*/
public static Platform getInstance() {
if (instance == null) {
throw new RuntimeException("Platform instance is null. Use Platform.setInstance(Platform p) to set the instance first.");
}
return instance;
}
/**
* Set the Platform instance.
*
* This may be useful to define a file search path, or custom character
* encoding conversion properties.
*/
public static void setInstance(Platform platform) {
instance = platform;
}
/**
* Creates a new instance of LuaState.
*
* If Platform.LUA_STATE_CLASS_NAME is not null, this method
* will attempt to create an instance using a construction such as
* (LuaState) Class.forName(Platform.LUA_STATE_CLASS_NAME).newInstance()
*
* If Platform.LUA_STATE_CLASS_NAME is null or the specified class cannot
* be instantiated for some reason, a new instance of LuaState
* will be created and used.
*
* In either case, the method LuaState.init() will be invoked, followed by
* Platform.installOptionalProperties(LuaState) on the new instance.
*
* @return a new instance of LuaState initialized via init() and installOptionalProperties()
*
* @see LUA_STATE_CLASS_NAME
* @see LuaState
*/
public static LuaState newLuaState() {
Platform p = Platform.getInstance();
LuaState vm = null;
if (LUA_STATE_CLASS_NAME != null) {
try {
vm = (LuaState) Class.forName(LUA_STATE_CLASS_NAME).newInstance();
} catch (Exception e) {
System.out.println("Warning: no debug support, " + e);
}
}
if (vm == null)
vm = new LuaState();
vm.init();
p.installOptionalLibs(vm);
return vm;
}
/** Get the name of the platform
*/
abstract public String getName();
/**
* Return an InputStream or null if not found for a particular file name.
*
* @param fileName
* Name of the file to open
* @return InputStream or null if not found.
*/
abstract public InputStream openFile(String fileName);
/**
* Create Reader from an InputStream
*
* @param inputStream
* InputStream to read from
* @return Reader instance to use for character input
*/
abstract public Reader createReader(InputStream inputStream);
/**
* Returns the value for the given platform property.
*
* @param propertyName
* Property name
* @return Property value
*/
abstract public String getProperty(String propertyName);
/**
* Install optional libraries on the LuaState.
* @param vm LuaState instance
*/
abstract protected void installOptionalLibs(LuaState vm);
/**
* Compute math.pow() for two numbers using double math when available.
* @param lhs LNumber base
* @param rhs LNumber exponent
* @return base ^ exponent as a LNumber, throw RuntimeException if not implemented
*/
abstract public LNumber mathPow(LNumber base, LNumber exponent);
/**
* Compute a math operation that takes a single double argument and returns a double
* @param id the math op, from MathLib constants
* @param x the argument
* @return the value as an LNumber
* @throws LuaErrorException if the id is not supported by this platform.
*/
abstract public LNumber mathop(int id, LNumber x);
/**
* Compute a math operation that takes a two double arguments and returns a double
* @param id the math op, from MathLib constants
* @param x the first argument as an LNumber
* @param y the second arugment as an LNumber
* @return the value as an LNumber
* @throws LuaErrorException if the id is not supported by this platform.
*/
abstract public LNumber mathop(int id, LNumber x, LNumber y);
/** Throw an error indicating the math operation is not accepted */
public LNumber unsupportedMathOp() {
throw new LuaErrorException("math op not supported on "+getName());
}
}

View File

@@ -1,357 +0,0 @@
package org.luaj.vm;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class Print extends Lua {
/** opcode names */
private static final String STRING_FOR_NULL = "null";
public static PrintStream ps = System.out;
private static final String[] luaP_opnames = {
"MOVE",
"LOADK",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETGLOBAL",
"GETTABLE",
"SETGLOBAL",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"SELF",
"ADD",
"SUB",
"MUL",
"DIV",
"MOD",
"POW",
"UNM",
"NOT",
"LEN",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"TEST",
"TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
"FORPREP",
"TFORLOOP",
"SETLIST",
"CLOSE",
"CLOSURE",
"VARARG",
null,
};
static void printString(PrintStream ps, final LString s) {
final byte[] bytes = s.m_bytes;
final int off = s.m_offset;
ps.print('"');
for (int i = 0, n = s.m_length; i < n; i++) {
int c = bytes[i+off] & 0x0FF;
if ( c >= ' ' && c <= '~' && c != '\"' && c != '\\' )
ps.print((char) c);
else {
switch (c) {
case '"':
ps.print("\\\"");
break;
case '\\':
ps.print("\\\\");
break;
case 0x0007: /* bell */
ps.print("\\a");
break;
case '\b': /* backspace */
ps.print("\\f");
break;
case '\f': /* form feed */
ps.print("\\f");
break;
case '\r': /* carriage return */
ps.print("\\r");
break;
case '\n': /* newline */
ps.print("\\n");
break;
case 0x000B: /* vertical tab */
ps.print("\\v");
break;
default:
ps.print('\\');
ps.print(Integer.toString(1000 + c).substring(1));
break;
}
}
}
ps.print('"');
}
static void printValue( PrintStream ps, LValue v ) {
if ( v instanceof LString )
printString( ps, v.luaAsString() );
else if ( v instanceof LInteger ) {
ps.print( v.toJavaInt() );
} else if ( v instanceof LDouble ) {
double d = v.toJavaDouble();
if ( d == ((int)d) )
ps.print( (int) d );
else
ps.print( d );
} else if ( v instanceof LFunction ) {
ps.print(v.getClass().getName());
} else {
ps.print( String.valueOf(v) );
}
}
static void printConstant(PrintStream ps, LPrototype f, int i) {
printValue( ps, f.k[i] );
}
public static void printCode(LPrototype f) {
int[] code = f.code;
int pc, n = code.length;
for (pc = 0; pc < n; pc++) {
printOpCode(f, pc);
ps.println();
}
}
public static void printOpCode(LPrototype f, int pc) {
printOpCode(ps,f,pc);
}
public static void printOpCode(PrintStream ps, LPrototype f, int pc) {
int[] code = f.code;
int i = code[pc];
int o = GET_OPCODE(i);
int a = GETARG_A(i);
int b = GETARG_B(i);
int c = GETARG_C(i);
int bx = GETARG_Bx(i);
int sbx = GETARG_sBx(i);
int line = getline(f, pc);
ps.print(" " + (pc + 1) + " ");
if (line > 0)
ps.print("[" + line + "] ");
else
ps.print("[-] ");
ps.print(luaP_opnames[o] + " ");
switch (getOpMode(o)) {
case iABC:
ps.print( a );
if (getBMode(o) != OpArgN)
ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b));
if (getCMode(o) != OpArgN)
ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c));
break;
case iABx:
if (getBMode(o) == OpArgK) {
ps.print(a + " " + (-1 - bx));
} else {
ps.print(a + " " + (bx));
}
break;
case iAsBx:
if (o == OP_JMP)
ps.print( sbx );
else
ps.print(a + " " + sbx);
break;
}
switch (o) {
case OP_LOADK:
ps.print(" ; ");
printConstant(ps, f, bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
ps.print(" ; ");
if ( f.upvalues.length > b )
printValue(ps, f.upvalues[b]);
else
ps.print( "-" );
break;
case OP_GETGLOBAL:
case OP_SETGLOBAL:
ps.print(" ; ");
printConstant( ps, f, bx );
break;
case OP_GETTABLE:
case OP_SELF:
if (ISK(c)) {
ps.print(" ; ");
printConstant(ps, f, INDEXK(c));
}
break;
case OP_SETTABLE:
case OP_ADD:
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_POW:
case OP_EQ:
case OP_LT:
case OP_LE:
if (ISK(b) || ISK(c)) {
ps.print(" ; ");
if (ISK(b))
printConstant(ps, f, INDEXK(b));
else
ps.print("-");
ps.print(" ");
if (ISK(c))
printConstant(ps, f, INDEXK(c));
else
ps.print("-");
}
break;
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
ps.print(" ; to " + (sbx + pc + 2));
break;
case OP_CLOSURE:
ps.print(" ; " + f.p[bx].getClass().getName());
break;
case OP_SETLIST:
if (c == 0)
ps.print(" ; " + ((int) code[++pc]));
else
ps.print(" ; " + ((int) c));
break;
case OP_VARARG:
ps.print( " ; is_vararg="+ f.is_vararg );
break;
default:
break;
}
}
private static int getline(LPrototype f, int pc) {
return pc>0 && f.lineinfo!=null && pc<f.lineinfo.length? f.lineinfo[pc]: -1;
}
static void printHeader(LPrototype f) {
String s = String.valueOf(f.source);
if (s.startsWith("@") || s.startsWith("="))
s = s.substring(1);
else if ("\033Lua".equals(s))
s = "(bstring)";
else
s = "(string)";
String a = (f.linedefined == 0) ? "main" : "function";
ps.print("\n%" + a + " <" + s + ":" + f.linedefined + ","
+ f.lastlinedefined + "> (" + f.code.length + " instructions, "
+ f.code.length * 4 + " bytes at " + id(f) + ")\n");
ps.print(f.numparams + " param, " + f.maxstacksize + " slot, "
+ f.upvalues.length + " upvalue, ");
ps.print(f.locvars.length + " local, " + f.k.length
+ " constant, " + f.p.length + " function\n");
}
static void printConstants(LPrototype f) {
int i, n = f.k.length;
ps.print("constants (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) {
ps.print(" " + (i + 1) + " ");
printValue( ps, f.k[i] );
ps.print( "\n");
}
}
static void printLocals(LPrototype f) {
int i, n = f.locvars.length;
ps.print("locals (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) {
ps.println(" "+i+" "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1));
}
}
static void printUpValues(LPrototype f) {
int i, n = f.upvalues.length;
ps.print("upvalues (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) {
ps.print(" " + i + " " + f.upvalues[i] + "\n");
}
}
public void printFunction(LPrototype f, boolean full) {
int i, n = f.p.length;
printHeader(f);
printCode(f);
if (full) {
printConstants(f);
printLocals(f);
printUpValues(f);
}
for (i = 0; i < n; i++)
printFunction(f.p[i], full);
}
private static void format( String s, int maxcols ) {
int n = s.length();
if ( n > maxcols )
ps.print( s.substring(0,maxcols) );
else {
ps.print( s );
for ( int i=maxcols-n; --i>=0; )
ps.print( ' ' );
}
}
public static void printState(LuaState state, int base, int top, int max,
LClosure cl, int pc) {
// print opcode into buffer
PrintStream previous = ps;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ps = new PrintStream( baos );
printOpCode( cl.p, pc );
ps.flush();
ps.close();
ps = previous;
format( baos.toString(), 40 );
ps.print( " b,t=(" );
format( String.valueOf(base), 3 );
ps.print( "," );
format( String.valueOf(top), 3 );
ps.print( ") " );
// print stack
int i=0;
for ( ; i<base; i++ )
ps.print('.');
ps.print('[');
for ( ; i<max; i++ ) {
Object v = state.stack[i];
ps.print( v!=null? String.valueOf(v): STRING_FOR_NULL );
if ( i+1 == top )
ps.print(']');
ps.print( " | " );
}
ps.println();
}
private static String id(LPrototype f) {
return "Proto";
}
}

View File

@@ -1,67 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.vm;
public class UpVal {
LuaState state;
int position;
LValue value;
public UpVal( LuaState state, int i ) {
this.state = state;
this.position = i;
}
public String toString() {
return "up."+position;
}
public LValue getValue() {
if ( state == null )
return value;
else
return state.stack[ position ];
}
public void setValue( LValue value ) {
if ( state == null )
this.value = value;
else
state.stack[ position ] = value;
}
public boolean close( int limit ) {
if ( position >= limit ) {
value = state.stack[ position ];
state = null;
return true;
} else {
return false;
}
}
public boolean isClosed() {
return state == null;
}
}

View File

@@ -1,211 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.lib.j2me;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import org.luaj.lib.BaseLib;
import org.luaj.lib.IoLib;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
/**
* Implementation of the lua io library based on CLDC 1.0 and StreamConnection.
*
* Seek is not supported.
*/
public class Cldc10IoLib extends IoLib {
public static void install( LTable globals ) {
new Cldc10IoLib().initialize(globals);
}
public Cldc10IoLib() {
super();
}
public Cldc10IoLib(int index) {
super(index);
}
protected IoLib newInstance(int index) {
return new Cldc10IoLib(index);
}
protected File wrapStdin() throws IOException {
return new FileImpl(BaseLib.STDIN);
}
protected File wrapStdout() throws IOException {
return new FileImpl(BaseLib.STDOUT != null? BaseLib.STDOUT: System.out);
}
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
String url = "file:///" + filename;
int mode = readMode? Connector.READ: Connector.READ_WRITE;
StreamConnection conn = (StreamConnection) Connector.open( url, mode );
File f = readMode?
new FileImpl(conn, conn.openInputStream(), null):
new FileImpl(conn, conn.openInputStream(), conn.openOutputStream());
/*
if ( appendMode ) {
f.seek("end",0);
} else {
if ( ! readMode )
conn.truncate(0);
}
*/
return f;
}
private static void notimplemented() throws IOException {
throw new IOException("not implemented");
}
protected File openProgram(String prog, String mode) throws IOException {
notimplemented();
return null;
}
protected File tmpFile() throws IOException {
notimplemented();
return null;
}
private static final class FileImpl implements File {
private final StreamConnection conn;
private final InputStream is;
private final OutputStream os;
private boolean closed = false;
private boolean nobuffer = false;
private int lookahead = -1;
private FileImpl( StreamConnection conn, InputStream is, OutputStream os ) {
this.conn = conn;
this.is = is;
this.os = os;
}
private FileImpl( InputStream i ) {
this( null, i, null );
}
private FileImpl( OutputStream o ) {
this( null, null, o );
}
public String toString() {
return "file ("+this.hashCode()+")";
}
public boolean isstdfile() {
return conn == null;
}
public void close() throws IOException {
closed = true;
if ( conn != null ) {
conn.close();
}
}
public void flush() throws IOException {
if ( os != null )
os.flush();
}
public void write(LString s) throws IOException {
if ( os != null )
os.write( s.m_bytes, s.m_offset, s.m_length );
else
notimplemented();
if ( nobuffer )
flush();
}
public boolean isclosed() {
return closed;
}
public int seek(String option, int pos) throws IOException {
/*
if ( conn != null ) {
if ( "set".equals(option) ) {
conn.seek(pos);
return (int) conn.getFilePointer();
} else if ( "end".equals(option) ) {
conn.seek(conn.length()+1+pos);
return (int) conn.length()+1;
} else {
conn.seek(conn.getFilePointer()+pos);
return (int) conn.getFilePointer();
}
}
*/
notimplemented();
return 0;
}
public void setvbuf(String mode, int size) {
nobuffer = "no".equals(mode);
}
// get length remaining to read
public int remaining() throws IOException {
return -1;
}
// peek ahead one character
public int peek() throws IOException {
if ( lookahead < 0 )
lookahead = is.read();
return lookahead;
}
// return char if read, -1 if eof, throw IOException on other exception
public int read() throws IOException {
if ( lookahead >= 0 ) {
int c = lookahead;
lookahead = -1;
return c;
}
if ( is != null )
return is.read();
notimplemented();
return 0;
}
// return number of bytes read if positive, -1 if eof, throws IOException
public int read(byte[] bytes, int offset, int length) throws IOException {
int n,i=0;
if (is!=null) {
if ( length > 0 && lookahead >= 0 ) {
bytes[offset] = (byte) lookahead;
lookahead = -1;
i += 1;
}
for ( ; i<length; ) {
n = is.read(bytes, offset+i, length-i);
if ( n < 0 )
return ( i > 0 ? i : -1 );
i += n;
}
} else {
notimplemented();
}
return length;
}
}
}

View File

@@ -1,53 +0,0 @@
package org.luaj.platform;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.microedition.midlet.MIDlet;
import org.luaj.vm.LNumber;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class J2meMidp10Cldc10Platform extends Platform {
protected MIDlet midlet;
public String getName() {
return "j2me";
}
public J2meMidp10Cldc10Platform(MIDlet midlet) {
this.midlet = midlet;
}
public Reader createReader(InputStream inputStream) {
return new InputStreamReader(inputStream);
}
public InputStream openFile(String fileName) {
if (!fileName.startsWith("/"))
fileName = "/" + fileName;
InputStream is = this.getClass().getResourceAsStream(fileName);
return is;
}
public String getProperty(String key) {
return midlet.getAppProperty(key);
}
protected void installOptionalLibs(LuaState vm) {
vm.installStandardLibs();
}
public LNumber mathPow(LNumber base, LNumber exponent) {
return unsupportedMathOp();
}
public LNumber mathop(int id, LNumber x, LNumber y) {
return unsupportedMathOp();
}
public LNumber mathop(int id, LNumber x) {
return unsupportedMathOp();
}
}

View File

@@ -1,84 +0,0 @@
package org.luaj.platform;
import javax.microedition.midlet.MIDlet;
import org.luaj.lib.MathLib;
import org.luaj.vm.LDouble;
import org.luaj.vm.LNumber;
public class J2meMidp20Cldc11Platform extends J2meMidp10Cldc10Platform {
public J2meMidp20Cldc11Platform(MIDlet midlet) {
super(midlet);
}
public LNumber mathPow(LNumber base, LNumber exp) {
return LDouble.numberOf(dpow(base.toJavaDouble(),exp.toJavaDouble()));
}
public LNumber mathop(int id, LNumber la, LNumber lb) {
double a = la.toJavaDouble();
double b = lb.toJavaDouble();
double z = 0;
switch ( id ) {
default: return unsupportedMathOp();
//case MathLib.ATAN2: z =
// b>0? Math.atan(a/b):
// b<0? (a>=0? Math.PI-Math.atan(a/-b): -Math.PI-Math.atan(a/-b)):
// (a>0? Math.PI/2: a<0? -Math.PI/2: 0);
// break;
case MathLib.FMOD: z = a - (b * ((int)(a/b))); break;
case MathLib.POW: z = dpow(a, b); break;
}
return LDouble.numberOf(z);
}
public LNumber mathop(int id, LNumber lx) {
double x = lx.toJavaDouble();
double z = 0;
switch ( id ) {
default: return unsupportedMathOp();
case MathLib.ABS: z = Math.abs(x); break;
//case MathLib.ACOS: z = Math.acos(x); break;
//case MathLib.ASIN: z = Math.asin(x); break;
//case MathLib.ATAN: z = Math.atan(x); break;
case MathLib.COS: z = Math.cos(x); break;
//case MathLib.COSH: z = (Math.exp(x) + Math.exp(-x)) / 2; break;
case MathLib.DEG: z = Math.toDegrees(x); break;
//case MathLib.EXP: z = Math.exp(x); break;
//case MathLib.LOG: z = Math.log(x); break;
//case MathLib.LOG10: z = Math.log10(x); break;
case MathLib.RAD: z = Math.toRadians(x); break;
case MathLib.SIN: z = Math.sin(x); break;
//case MathLib.SINH: z = (Math.exp(x) - Math.exp(-x)) / 2; break;
case MathLib.SQRT: z = Math.sqrt(x); break;
case MathLib.TAN: z = Math.tan(x); break;
//case MathLib.TANH: {
// double e = Math.exp(2*x);
// z = (e-1) / (e+1);
// break;
//}
}
return LDouble.numberOf(z);
}
public static double dpow(double a, double b) {
if ( b < 0 )
return 1 / dpow( a, -b );
double p = 1;
int whole = (int) b;
for ( double v=a; whole > 0; whole>>=1, v*=v )
if ( (whole & 1) != 0 )
p *= v;
if ( (b -= whole) > 0 ) {
int frac = (int) (0x10000 * b);
for ( ; (frac&0xffff)!=0; frac<<=1 ) {
a = Math.sqrt(a);
if ( (frac & 0x8000) != 0 )
p *= a;
}
}
return p;
}
}

View File

@@ -1,211 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.
******************************************************************************/
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.luaj.compiler.LuaC;
import org.luaj.lib.DebugLib;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LFunction;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
* lua command for use in java se environments.
*/
public class lua {
private static final String version = Lua._VERSION + " Copyright (C) 2009 luaj.org";
private static final String usage =
"usage: java -cp luaj-j2se.jar lua [options] [script [args]].\n" +
"Available options are:\n" +
" -e stat execute string 'stat'\n" +
" -l name require library 'name'\n" +
" -i enter interactive mode after executing 'script'\n" +
" -v show version information\n" +
" -- stop handling options\n" +
" - execute stdin and stop handling options";
private static void usageExit() {
System.out.println(usage);
System.exit(-1);
}
public static void main( String[] args ) throws IOException {
// new lua state
Platform.setInstance(new J2sePlatform());
LuaC.install();
LuaState vm = Platform.newLuaState();
DebugLib.install(vm);
// process args
boolean interactive = (args.length == 0);
boolean versioninfo = false;
boolean processing = true;
try {
// stateful argument processing
for ( int i=0; i<args.length; i++ ) {
if ( ! processing || ! args[i].startsWith("-") ) {
// input file - defer to last stage
break;
} else if ( args[i].length() <= 1 ) {
// input file - defer to last stage
break;
} else {
switch ( args[i].charAt(1) ) {
case 'e':
if ( ++i >= args.length )
usageExit();
// input script - defer to last stage
break;
case 'l':
if ( ++i >= args.length )
usageExit();
loadLibrary( vm, args[i] );
break;
case 'i':
interactive = true;
break;
case 'v':
versioninfo = true;
break;
case '-':
if ( args[i].length() > 2 )
usageExit();
processing = false;
break;
default:
usageExit();
break;
}
}
}
// echo version
if ( versioninfo )
System.out.println(version);
// input script processing
processing = true;
for ( int i=0; i<args.length; i++ ) {
if ( ! processing || ! args[i].startsWith("-") ) {
LTable arg = new LTable();
for ( int j=0; j<args.length; j++ )
arg.put( j-i, new LString(args[j]) );
arg.put( -i-1, new LString("lua") );
arg.put( -i-2, new LString("java") );
vm._G.put( "arg", arg );
processScript( vm, new FileInputStream(args[i]), args[i], args, i );
break;
} else if ( args[i].length() <= 1 ) {
processScript( vm, System.in, "-", args, i );
break;
} else {
switch ( args[i].charAt(1) ) {
case 'l':
++i;
break;
case 'e':
++i;
processScript( vm, new ByteArrayInputStream(args[i].getBytes()), args[i], args, i );
break;
case '-':
processing = false;
break;
}
}
}
if ( interactive )
interactiveMode( vm );
} catch ( IOException ioe ) {
System.err.println( ioe.toString() );
System.exit(-2);
}
}
private static void loadLibrary( LuaState vm, String libname ) throws IOException {
try {
// load via "require"
vm.getglobal("require");
vm.pushstring(libname);
int status = vm.pcall(1, 0);
if ( status == 0 )
return;
// load as java class
Class c = Class.forName( libname );
Object i = c.newInstance();
LFunction f = (LFunction) i;
vm.call(f);
} catch ( Exception e ) {
throw new IOException("loadLibrary("+libname+") failed: "+e );
}
}
private static void processScript( LuaState vm, InputStream script, String chunkname, String[] args, int offset ) throws IOException {
try {
switch ( vm.load(script, chunkname) ) {
case 0:
if ( args != null )
for ( int i=offset; i<args.length; i++ )
vm.pushstring(args[i]);
vm.call(args.length-offset, 0);
break;
case LuaState.LUA_ERRMEM:
System.out.println("out of memory during chunk load");
break;
case LuaState.LUA_ERRSYNTAX:
System.out.println("syntax error: "+vm.tostring(-1) );
break;
}
} catch ( Throwable t ) {
t.printStackTrace( System.err );
} finally {
script.close();
}
}
private static void interactiveMode( LuaState vm ) throws IOException {
BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
while ( true ) {
System.out.print("> ");
System.out.flush();
String line = reader.readLine();
if ( line == null )
return;
processScript( vm, new ByteArrayInputStream(line.getBytes()), "-", null, 0 );
}
}
}

View File

@@ -1,185 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.
******************************************************************************/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.luaj.compiler.DumpState;
import org.luaj.compiler.LuaC;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LPrototype;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
import org.luaj.vm.Print;
/**
* luac command for use in java se environments.
*/
public class luac {
private static final String version = Lua._VERSION + "Copyright (C) 2008 luaj.org";
private static final String usage =
"usage: java -cp luaj-j2se.jar luac [options] [filenames].\n" +
"Available options are:\n" +
" - process stdin\n" +
" -l list\n" +
" -o name output to file 'name' (default is \"luac.out\")\n" +
" -p parse only\n" +
" -s strip debug information\n" +
" -e little endian format for numbers\n" +
" -i<n> number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" +
" -v show version information\n" +
" -- stop handling options\n";
private static void usageExit() {
System.out.println(usage);
System.exit(-1);
}
private boolean list = false;
private String output = "luac.out";
private boolean parseonly = false;
private boolean stripdebug = false;
private boolean littleendian = false;
private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT;
private boolean versioninfo = false;
private boolean processing = true;
public static void main( String[] args ) throws IOException {
new luac( args );
}
private luac( String[] args ) throws IOException {
// new lua state
Platform.setInstance(new J2sePlatform());
LuaC.install();
LuaState vm = Platform.newLuaState();
// process args
try {
// get stateful args
for ( int i=0; i<args.length; i++ ) {
if ( ! processing || ! args[i].startsWith("-") ) {
// input file - defer to next stage
} else if ( args[i].length() <= 1 ) {
// input file - defer to next stage
} else {
switch ( args[i].charAt(1) ) {
case 'l':
list = true;
break;
case 'o':
if ( ++i >= args.length )
usageExit();
output = args[i];
break;
case 'p':
parseonly = true;
break;
case 's':
stripdebug = true;
break;
case 'e':
littleendian = true;
break;
case 'i':
if ( args[i].length() <= 2 )
usageExit();
numberformat = Integer.parseInt(args[i].substring(2));
break;
case 'v':
versioninfo = true;
break;
case '-':
if ( args[i].length() > 2 )
usageExit();
processing = false;
break;
default:
usageExit();
break;
}
}
}
// echo version
if ( versioninfo )
System.out.println(version);
// open output file
OutputStream fos = new FileOutputStream( output );
// process input files
try {
processing = true;
for ( int i=0; i<args.length; i++ ) {
if ( ! processing || ! args[i].startsWith("-") ) {
processScript( vm, new FileInputStream(args[i]), args[i], fos );
} else if ( args[i].length() <= 1 ) {
processScript( vm, System.in, "-", fos );
} else {
switch ( args[i].charAt(1) ) {
case 'o':
++i;
break;
case '-':
processing = false;
break;
}
}
}
} finally {
fos.close();
}
} catch ( IOException ioe ) {
System.err.println( ioe.toString() );
System.exit(-2);
}
}
private void processScript( LuaState vm, InputStream script, String chunkname, OutputStream out ) throws IOException {
try {
// create the chunk
LPrototype chunk = org.luaj.compiler.LuaC.compile(script, chunkname);
// list the chunk
if (list)
Print.printCode(chunk);
// write out the chunk
if (!parseonly) {
DumpState.dump(chunk, out, stripdebug, numberformat, littleendian);
}
} catch ( Throwable t ) {
t.printStackTrace( System.err );
} finally {
script.close();
}
}
}

View File

@@ -1,152 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.
******************************************************************************/
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import javax.swing.JApplet;
import org.luaj.lib.j2se.CoerceJavaToLua;
import org.luaj.lib.j2se.J2seIoLib;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
* JApplet that runs a lua script in the init phase, and calls
* global functions for applet lifecycle events.
*
* The script(s) should be located relative to the document root in order
* for the lua scripts to be loaded.
*
* The functions init(), start(), stop() and destroy() and the script itself
* are called with the applet as the first argument, so that the
* lua script can perform whatever operations it needs to using the applet
* as the main context and making use of the luajava api.
*
* The applet runs the script identified by the applet parameter 'script'
* or 'main.lua' if applet parameter 'script' is not provided.
*/
public class luajapplet extends JApplet {
private static final long serialVersionUID = 1L;
// the script will be loaded as a resource
private static final String DEFAULT_SCRIPT = "main.lua";
private LuaState vm;
private String base;
private final LValue lthis = CoerceJavaToLua.coerce(this);
public synchronized void init() {
System.out.println("init() called");
super.init();
if ( vm == null ) {
// get the script as an app property
String script = this.getParameter("script");
if ( script == null )
script = DEFAULT_SCRIPT;
base = tobase( getDocumentBase().toExternalForm() );
System.out.println("script: "+script);
System.out.println("base: "+base);
// set up the j2me platform.
// files will be loaded relative to "base"
Platform.setInstance( new J2sePlatform() {
public InputStream openFile(String fileName) {
// System.out.println("openFile('"+fileName+"')");
URLConnection c = null;
try {
URL u = new URL(base + fileName);
c = u.openConnection();
return c.getInputStream();
} catch ( Exception e ) {
e.printStackTrace( System.out );
if ( c instanceof HttpURLConnection )
((HttpURLConnection)c).disconnect();
return null;
}
}
});
vm = Platform.newLuaState();
// extend the basic vm to include the compiler and io packages
org.luaj.compiler.LuaC.install();
J2seIoLib.install(vm._G);
// run the script
try {
vm.getglobal( "loadfile" );
vm.pushstring( script );
vm.call( 1, 1 );
vm.pushlvalue( lthis );
vm.call( 1, 0 );
} catch ( Throwable t ) {
t.printStackTrace( System.err );
}
}
callFunction( "init" );
}
private String tobase(String path) {
int i = path.lastIndexOf('/');
return i>=0? path.substring(0,i+1): path;
}
private boolean callFunction( String name ) {
try {
vm.getglobal( name );
if ( ! vm.isfunction(-1) ) {
vm.pop(1);
return false;
}
else {
vm.pushlvalue( lthis );
vm.call( 1, 0 );
return true;
}
} catch ( Throwable t ) {
System.err.println(name+"():");
t.printStackTrace( System.err );
return true;
}
}
public synchronized void start() {
super.start();
callFunction( "start" );
}
public synchronized void stop() {
callFunction( "stop" );
super.stop();
}
public synchronized void destroy() {
callFunction( "destroy" );
super.destroy();
}
}

View File

@@ -1,93 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib.j2se;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm.LBoolean;
import org.luaj.vm.LDouble;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LString;
import org.luaj.vm.LValue;
public class CoerceJavaToLua {
public static interface Coercion {
public LValue coerce( Object javaValue );
};
private static Map COERCIONS = new HashMap();
static {
Coercion boolCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Boolean b = (Boolean) javaValue;
return b.booleanValue()? LBoolean.TRUE: LBoolean.FALSE;
}
} ;
Coercion intCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return LInteger.valueOf( n.intValue() );
}
} ;
Coercion charCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Character c = (Character) javaValue;
return LInteger.valueOf( c.charValue() );
}
} ;
Coercion doubleCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return LDouble.numberOf( n.doubleValue() );
}
} ;
Coercion stringCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
return new LString( javaValue.toString() );
}
} ;
COERCIONS.put( Boolean.class, boolCoercion );
COERCIONS.put( Byte.class, intCoercion );
COERCIONS.put( Character.class, charCoercion );
COERCIONS.put( Short.class, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Float.class, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
}
public static LValue coerce(Object o) {
if ( o == null )
return LNil.NIL;
Class clazz = o.getClass();
Coercion c = (Coercion) COERCIONS.get( clazz );
if ( c != null )
return c.coerce( o );
return LuajavaLib.toUserdata( o, clazz );
}
}

View File

@@ -1,283 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib.j2se;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm.LBoolean;
import org.luaj.vm.LDouble;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNumber;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaErrorException;
public class CoerceLuaToJava {
public static interface Coercion {
public Object coerce( LValue value );
public int score( LValue value );
};
private static Map COERCIONS = new HashMap();
private static Coercion OBJECT_COERCION;
static {
Coercion boolCoercion = new Coercion() {
public Object coerce(LValue value) {
return value.toJavaBoolean()? Boolean.TRUE: Boolean.FALSE;
}
public int score(LValue value) {
if ( value instanceof LBoolean || value.isNil() )
return 0;
if ( value instanceof LNumber )
return 1;
return 4;
}
};
Coercion byteCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Byte( value.toJavaByte() );
}
public int score(LValue value) {
if ( value instanceof LInteger )
return 1;
if ( value instanceof LNumber )
return 2;
return 4;
}
};
Coercion charCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Character( value.toJavaChar() );
}
public int score(LValue value) {
if ( value instanceof LInteger )
return 1;
if ( value instanceof LNumber )
return 2;
return 4;
}
};
Coercion shortCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Short( value.toJavaShort() );
}
public int score(LValue value) {
if ( value instanceof LInteger )
return 1;
if ( value instanceof LNumber )
return 2;
return 4;
}
};
Coercion intCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Integer( value.toJavaInt() );
}
public int score(LValue value) {
if ( value instanceof LInteger )
return 0;
if ( value instanceof LNumber )
return 1;
if ( value instanceof LBoolean || value.isNil() )
return 2;
return 4;
}
};
Coercion longCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Long( value.toJavaLong() );
}
public int score(LValue value) {
if ( value instanceof LInteger )
return 1;
if ( value instanceof LNumber )
return 2;
return 4;
}
};
Coercion floatCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Float( value.toJavaFloat() );
}
public int score( LValue value ) {
if ( value instanceof LNumber )
return 1;
if ( value instanceof LBoolean )
return 2;
return 4;
}
};
Coercion doubleCoercion = new Coercion() {
public Object coerce(LValue value) {
return new Double( value.toJavaDouble() );
}
public int score(LValue value) {
if ( value instanceof LDouble )
return 0;
if ( value instanceof LNumber )
return 1;
if ( value instanceof LBoolean )
return 2;
return 4;
}
};
Coercion stringCoercion = new Coercion() {
public Object coerce(LValue value) {
return value.toJavaString();
}
public int score(LValue value) {
if ( value instanceof LUserData )
return 0;
return 1;
}
};
Coercion objectCoercion = new Coercion() {
public Object coerce(LValue value) {
if ( value instanceof LUserData )
return ((LUserData)value).m_instance;
if ( value instanceof LString )
return value.toJavaString();
if ( value instanceof LInteger )
return new Integer(value.toJavaInt());
if ( value instanceof LDouble )
return new Double(value.toJavaDouble());
if ( value instanceof LBoolean )
return Boolean.valueOf(value.toJavaBoolean());
if ( value.isNil() )
return null;
return value;
}
public int score(LValue value) {
if ( value instanceof LString )
return 0;
return 0x10;
}
};
COERCIONS.put( Boolean.TYPE, boolCoercion );
COERCIONS.put( Boolean.class, boolCoercion );
COERCIONS.put( Byte.TYPE, byteCoercion );
COERCIONS.put( Byte.class, byteCoercion );
COERCIONS.put( Character.TYPE, charCoercion );
COERCIONS.put( Character.class, charCoercion );
COERCIONS.put( Short.TYPE, shortCoercion );
COERCIONS.put( Short.class, shortCoercion );
COERCIONS.put( Integer.TYPE, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Long.TYPE, longCoercion );
COERCIONS.put( Long.class, longCoercion );
COERCIONS.put( Float.TYPE, floatCoercion );
COERCIONS.put( Float.class, floatCoercion );
COERCIONS.put( Double.TYPE, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
COERCIONS.put( Object.class, objectCoercion );
}
/** Score a single parameter, including array handling */
private static int scoreParam(LValue a, Class c) {
if ( a instanceof LUserData ) {
Object o = ((LUserData) a).m_instance;
if ( c.isAssignableFrom(o.getClass()) )
return 0;
}
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
return co.score( a );
}
if ( c.isArray() ) {
Class typ = c.getComponentType();
if ( a instanceof LTable ) {
return scoreParam( ((LTable)a).get(1), typ );
} else {
return 0x10 + (scoreParam(a, typ) << 8);
}
}
return 0x1000;
}
/** Do a conversion */
public static Object coerceArg(LValue a, Class c) {
if ( a instanceof LUserData ) {
Object o = ((LUserData) a).m_instance;
if ( c.isAssignableFrom(o.getClass()) )
return o;
}
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
return co.coerce( a );
}
if ( c.isArray() ) {
boolean istable = (a instanceof LTable);
int n = istable? a.luaLength(): 1;
Class typ = c.getComponentType();
Object o = Array.newInstance(typ, n);
for ( int i=0; i<n; i++ ) {
LValue ele = (istable? ((LTable)a).get(i+1): a);
if ( ele != null )
Array.set(o, i, coerceArg(ele, typ));
}
return o;
}
if ( a.isNil() )
return null;
throw new LuaErrorException("no coercion found for "+a.getClass()+" to "+c);
}
static Object[] coerceArgs(LValue[] suppliedArgs, Class[] parameterTypes) {
int nargs = suppliedArgs.length;
int n = parameterTypes.length;
Object[] args = new Object[n];
for ( int i=0; i<n && i<nargs; i++ )
args[i] = coerceArg( suppliedArgs[i], parameterTypes[i] );
return args;
}
/*
* Score parameter types for match with supplied parameter list
*
* 1) exact number of args
* 2) java has more args
* 3) java has less args
* 4) types coerce well
*/
public static int scoreParamTypes(LValue[] suppliedArgs, Class[] paramTypes) {
int nargs = suppliedArgs.length;
int njava = paramTypes.length;
int score = (njava == nargs? 0: njava > nargs? 0x4000: 0x8000);
for ( int i=0; i<nargs && i<njava; i++ ) {
LValue a = suppliedArgs[i];
Class c = paramTypes[i];
int s = scoreParam( a, c );
score += s;
}
return score;
}
}

View File

@@ -1,203 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.lib.j2se;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import org.luaj.lib.BaseLib;
import org.luaj.lib.IoLib;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
/**
* Implementation of the lua io library for J2se using RandomAccessFile
* to implement seek.
*/
public class J2seIoLib extends IoLib {
public static void install( LTable globals ) {
new J2seIoLib().initialize(globals);
}
public J2seIoLib() {
super();
}
public J2seIoLib(int index) {
super(index);
}
protected IoLib newInstance(int index) {
return new J2seIoLib(index);
}
protected File wrapStdin() throws IOException {
return new FileImpl(BaseLib.STDIN != null? BaseLib.STDIN: System.in);
}
protected File wrapStdout() throws IOException {
return new FileImpl(BaseLib.STDOUT != null? BaseLib.STDOUT: System.out);
}
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw");
if ( appendMode ) {
f.seek(f.length());
} else {
if ( ! readMode )
f.setLength(0);
}
return new FileImpl( f );
}
protected File openProgram(String prog, String mode) throws IOException {
final Process p = Runtime.getRuntime().exec(prog);
return "w".equals(mode)?
new FileImpl( p.getOutputStream() ):
new FileImpl( p.getInputStream() );
}
protected File tmpFile() throws IOException {
java.io.File f = java.io.File.createTempFile(".luaj","bin");
f.deleteOnExit();
return new FileImpl( new RandomAccessFile(f,"rw") );
}
private static void notimplemented() {
throw new RuntimeException("not implemented");
}
private static final class FileImpl implements File {
private final RandomAccessFile file;
private final InputStream is;
private final OutputStream os;
private boolean closed = false;
private boolean nobuffer = false;
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) {
this.file = file;
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
this.os = os;
}
private FileImpl( RandomAccessFile f ) {
this( f, null, null );
}
private FileImpl( InputStream i ) {
this( null, i, null );
}
private FileImpl( OutputStream o ) {
this( null, null, o );
}
public String toString() {
return "file ("+this.hashCode()+")";
}
public boolean isstdfile() {
return file == null;
}
public void close() throws IOException {
closed = true;
if ( file != null ) {
file.close();
}
}
public void flush() throws IOException {
if ( os != null )
os.flush();
}
public void write(LString s) throws IOException {
if ( os != null )
os.write( s.m_bytes, s.m_offset, s.m_length );
else if ( file != null )
file.write( s.m_bytes, s.m_offset, s.m_length );
else
notimplemented();
if ( nobuffer )
flush();
}
public boolean isclosed() {
return closed;
}
public int seek(String option, int pos) throws IOException {
if ( file != null ) {
if ( "set".equals(option) ) {
file.seek(pos);
} else if ( "end".equals(option) ) {
file.seek(file.length()+pos);
} else {
file.seek(file.getFilePointer()+pos);
}
return (int) file.getFilePointer();
}
notimplemented();
return 0;
}
public void setvbuf(String mode, int size) {
nobuffer = "no".equals(mode);
}
// get length remaining to read
public int remaining() throws IOException {
return file!=null? (int) (file.length()-file.getFilePointer()): -1;
}
// peek ahead one character
public int peek() throws IOException {
if ( is != null ) {
is.mark(1);
int c = is.read();
is.reset();
return c;
} else if ( file != null ) {
int c = file.read();
file.seek(file.getFilePointer()-1);
return c;
}
notimplemented();
return 0;
}
// return char if read, -1 if eof, throw IOException on other exception
public int read() throws IOException {
if ( is != null )
return is.read();
else if ( file != null ) {
return file.read();
}
notimplemented();
return 0;
}
// return number of bytes read if positive, -1 if eof, throws IOException
public int read(byte[] bytes, int offset, int length) throws IOException {
if (file!=null) {
return file.read(bytes, offset, length);
} else if (is!=null) {
return is.read(bytes, offset, length);
} else {
notimplemented();
}
return length;
}
}
}

View File

@@ -1,92 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 LuaJ. 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.lib.j2se;
import java.io.File;
import java.io.IOException;
import org.luaj.lib.OsLib;
import org.luaj.vm.LTable;
/**
* Implementation of the lua os library for J2se
*/
public class J2seOsLib extends OsLib {
public static int EXEC_IOEXCEPTION = -1;
public static int EXEC_INTERRUPTED = -2;
public static int EXEC_ERROR = -3;
/**
* Install the os library using the J2seOsLib class as a factory
*/
public static void install(LTable globals) {
OsLib.install(globals, new J2seOsLib());
}
public J2seOsLib() {
super();
}
protected OsLib newInstance(int index) {
return new J2seOsLib(index);
}
private J2seOsLib(int id) {
super(id);
}
protected int execute(String command) {
Runtime r = Runtime.getRuntime();
try {
final Process p = r.exec(command);
try {
p.waitFor();
return p.exitValue();
} finally {
p.destroy();
}
} catch (IOException ioe) {
return EXEC_IOEXCEPTION;
} catch (InterruptedException e) {
return EXEC_INTERRUPTED;
} catch (Throwable t) {
return EXEC_ERROR;
}
}
protected void remove(String filename) throws IOException {
new File(filename).delete();
}
protected void rename(String oldname, String newname) throws IOException {
new File(oldname).renameTo(new File(newname));
}
protected String tmpname() {
try {
java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX);
return f.getName();
} catch ( IOException ioe ) {
return super.tmpname();
}
}
}

View File

@@ -1,463 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.lib.j2se;
/** LuaJava-like bindings to Java scripting.
*
* TODO: coerce types on way in and out, pick method base on arg count ant types.
*/
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
public final class LuajavaLib extends LFunction {
public static void install(LTable globals) {
LTable luajava = new LTable();
for ( int i=0; i<NAMES.length; i++ )
luajava.put( NAMES[i], new LuajavaLib(i) );
globals.put( "luajava", luajava );
}
private static final int INIT = 0;
private static final int BINDCLASS = 1;
private static final int NEWINSTANCE = 2;
private static final int NEW = 3;
private static final int CREATEPROXY = 4;
private static final int LOADLIB = 5;
private static final String[] NAMES = {
"luajava",
"bindClass",
"newInstance",
"new",
"createProxy",
"loadLib" };
private static final Map classMetatables = new HashMap();
private int id;
public LuajavaLib() {
}
private LuajavaLib( int id ) {
this.id = id;
}
public String toString() {
return "luajava."+NAMES[id];
}
// perform a lua call
public boolean luaStackCall(final LuaState vm) {
String className;
switch ( id ) {
case INIT:
install(vm._G);
break;
case BINDCLASS:
className = vm.tostring(2);
try {
Class clazz = Class.forName(className);
vm.resettop();
vm.pushlvalue( toUserdata( clazz, clazz ) );
} catch (Exception e) {
throw new LuaErrorException(e);
}
break;
case NEWINSTANCE:
case NEW:
try {
// get constructor
LValue c = vm.topointer(2);
Class clazz = (id==NEWINSTANCE? Class.forName(c.toJavaString()): (Class) c.toJavaInstance());
ParamsList params = new ParamsList( vm );
Constructor con = resolveConstructor( clazz, params );
// coerce args
Object[] args = CoerceLuaToJava.coerceArgs( params.values, con.getParameterTypes() );
Object o = con.newInstance( args );
// set the result
vm.resettop();
vm.pushlvalue( toUserdata( o, clazz ) );
} catch (Exception e) {
throw new LuaErrorException(e);
}
break;
case CREATEPROXY:
final int ninterfaces = Math.max(0,vm.gettop()-2);
if ( ninterfaces <= 0 )
throw new LuaErrorException("no interfaces");
final LValue lobj = vm.totable(-1);
try {
// get the interfaces
final Class[] ifaces = new Class[ninterfaces];
for ( int i=0; i<ninterfaces; i++ )
ifaces[i] = Class.forName(vm.tostring(i+2));
// create the invocation handler
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
vm.pushlvalue(lobj);
vm.getfield( -1, LString.valueOf(method.getName()) );
vm.remove( -2 );
LValue result;
if ( !vm.isnil( -1 ) ) {
int n = ( args != null ) ? args.length : 0;
for ( int i=0; i<n; i++ )
vm.pushlvalue( CoerceJavaToLua.coerce(args[i]) );
vm.call(n, 1);
}
result = vm.poplvalue();
return CoerceLuaToJava.coerceArg(result, method.getReturnType());
}
};
// create the proxy object
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);
// return the proxy
vm.resettop();
vm.pushuserdata(proxy);
} catch (Exception e) {
throw new LuaErrorException(e);
}
break;
case LOADLIB:
try {
// get constructor
String classname = vm.tostring(2);
String methodname = vm.tostring(3);
Class clazz = Class.forName(classname);
Method method = clazz.getMethod(methodname, new Class[] { LuaState.class });
Object result = method.invoke(clazz, new Object[] { vm });
if ( result instanceof Integer ) {
int nresults = ((Integer)result).intValue();
int nremove = vm.gettop() - nresults;
for ( int i=0; i<nremove; i++ )
vm.remove(1);
} else {
vm.resettop();
}
} catch (Exception e) {
throw new LuaErrorException(e);
}
break;
default:
throw new LuaErrorException("not yet supported: "+this);
}
return false;
}
public static class ParamsList {
public final LValue[] values;
public final Class[] classes;
public int hash;
public boolean cantcache;
ParamsList( LuaState vm ) {
int n = Math.max(vm.gettop()-2,0);
values = new LValue[n];
classes = new Class[n];
for ( int i=0; i<n; i++ ) {
values[i] = vm.topointer(i-n);
classes[i] = values[i].getClass();
hash += classes[i].hashCode();
Class c = classes[i];
if ( values[i] instanceof LUserData || values[i] instanceof LTable )
cantcache = true;
}
}
public int hashCode() {
return hash;
}
public boolean equals( Object o ) {
return ( o instanceof ParamsList )?
Arrays.equals( classes, ((ParamsList) o).classes ):
false;
}
}
private static LString LENGTH = LString.valueOf("length");
static LUserData toUserdata(Object obj, final Class clazz) {
LTable mt = (LTable) classMetatables.get(clazz);
if ( mt == null ) {
mt = new LTable();
mt.put( LValue.TM_INDEX, new LFunction() {
public boolean luaStackCall(LuaState vm) {
Object instance = vm.touserdata(2);
LValue key = vm.topointer(3);
if ( key instanceof LInteger ) {
if ( clazz.isArray() ) {
vm.resettop();
int index = key.toJavaInt()-1;
if ( index >= 0 && index < Array.getLength(instance) )
vm.pushlvalue( CoerceJavaToLua.coerce( Array.get(instance, index) ) );
else
vm.pushnil();
return false;
}
}
final String s = key.toJavaString();
vm.resettop();
try {
Field f = clazz.getField(s);
Object o = f.get(instance);
vm.pushlvalue( CoerceJavaToLua.coerce( o ) );
} catch (NoSuchFieldException nsfe) {
if ( clazz.isArray() && key.equals(LENGTH) ) {
vm.pushinteger( Array.getLength(instance) );
} else {
vm.pushlvalue( new LMethod(clazz,s) );
}
} catch (Exception e) {
throw new LuaErrorException(e);
}
return false;
}
});
mt.put( LValue.TM_NEWINDEX, new LFunction() {
public boolean luaStackCall(LuaState vm) {
Object instance = vm.touserdata(2);
LValue key = vm.topointer(3);
LValue val = vm.topointer(4);
if ( key instanceof LInteger ) {
if ( clazz.isArray() ) {
vm.resettop();
Object v = CoerceLuaToJava.coerceArg(val, clazz.getComponentType());
int index = key.toJavaInt()-1;
if ( index >= 0 && index < Array.getLength(instance) )
Array.set(instance, key.toJavaInt()-1, v);
else
throw new LuaErrorException("array bounds exceeded "+index);
vm.resettop();
return false;
}
}
String s = key.toJavaString();
try {
Field f = clazz.getField(s);
Object v = CoerceLuaToJava.coerceArg(val, f.getType());
f.set(instance,v);
vm.resettop();
} catch (Exception e) {
throw new LuaErrorException(e);
}
return false;
}
});
classMetatables.put(clazz, mt);
}
return new LUserData(obj,mt);
}
private static final class LMethod extends LFunction {
private final Class clazz;
private final String s;
private LMethod(Class clazz, String s) {
this.clazz = clazz;
this.s = s;
}
public String toString() {
return clazz.getName()+"."+s+"()";
}
public boolean luaStackCall(LuaState vm) {
try {
// find the method
Object instance = vm.touserdata(2);
ParamsList params = new ParamsList( vm );
Method meth = resolveMethod( clazz, s, params );
// coerce the arguments
Object[] args = CoerceLuaToJava.coerceArgs( params.values, meth.getParameterTypes() );
Object result = meth.invoke( instance, args );
// coerce the result
vm.resettop();
vm.pushlvalue( CoerceJavaToLua.coerce(result) );
return false;
} catch (Exception e) {
throw new LuaErrorException(e);
}
}
}
private static Map consCache =
new HashMap();
private static Map consIndex =
new HashMap();
private static Constructor resolveConstructor(Class clazz, ParamsList params ) {
// get the cache
Map cache = (Map) consCache.get( clazz );
if ( cache == null )
consCache.put( clazz, cache = new HashMap() );
// look up in the cache
Constructor c = (Constructor) cache.get( params );
if ( c != null )
return c;
// get index
Map index = (Map) consIndex.get( clazz );
if ( index == null ) {
consIndex.put( clazz, index = new HashMap() );
Constructor[] cons = clazz.getConstructors();
for ( int i=0; i<cons.length; i++ ) {
Constructor con = cons[i];
Integer n = new Integer( con.getParameterTypes().length );
List list = (List) index.get(n);
if ( list == null )
index.put( n, list = new ArrayList() );
list.add( con );
}
}
// figure out best list of arguments == supplied args
Integer n = new Integer( params.classes.length );
List list = (List) index.get(n);
if ( list == null )
throw new IllegalArgumentException("no constructor with "+n+" args");
// find constructor with best score
int bests = Integer.MAX_VALUE;
int besti = 0;
for ( int i=0, size=list.size(); i<size; i++ ) {
Constructor con = (Constructor) list.get(i);
int s = CoerceLuaToJava.scoreParamTypes(params.values, con.getParameterTypes());
if ( s < bests ) {
bests = s;
besti = i;
}
}
// put into cache
c = (Constructor) list.get(besti);
if ( ! params.cantcache )
cache.put( params, c );
return c;
}
private static Map methCache =
new HashMap();
private static Map methIndex =
new HashMap();
private static Method resolveMethod(Class clazz, String methodName, ParamsList params ) {
// get the cache
Map nameCache = (Map) methCache.get( clazz );
if ( nameCache == null )
methCache.put( clazz, nameCache = new HashMap() );
Map cache = (Map) nameCache.get( methodName );
if ( cache == null )
nameCache.put( methodName, cache = new HashMap() );
// look up in the cache
Method m = (Method) cache.get( params );
if ( m != null )
return m;
// get index
Map index = (Map) methIndex.get( clazz );
if ( index == null ) {
methIndex.put( clazz, index = new HashMap() );
Method[] meths = clazz.getMethods();
for ( int i=0; i<meths.length; i++ ) {
Method meth = meths[i];
String s = meth.getName();
Integer n = new Integer(meth.getParameterTypes().length);
Map map = (Map) index.get(s);
if ( map == null )
index.put( s, map = new HashMap() );
List list = (List) map.get(n);
if ( list == null )
map.put( n, list = new ArrayList() );
list.add( meth );
}
}
// figure out best list of arguments == supplied args
Map map = (Map) index.get(methodName);
if ( map == null )
throw new IllegalArgumentException("no method named '"+methodName+"'");
Integer n = new Integer( params.classes.length );
List list = (List) map.get(n);
if ( list == null )
throw new IllegalArgumentException("no method named '"+methodName+"' with "+n+" args");
// trivial lists match
if ( list.size() == 1 ) {
m = (Method) list.get(0);
if ( ! params.cantcache )
cache.put( params, m );
return m;
}
// find constructor with best score
int bests = Integer.MAX_VALUE;
int besti = 0;
for ( int i=0, size=list.size(); i<size; i++ ) {
Method meth = (Method) list.get(i);
int s = CoerceLuaToJava.scoreParamTypes(params.values, meth.getParameterTypes());
if ( s < bests ) {
bests = s;
besti = i;
}
}
// put into cache
m = (Method) list.get(besti);
if ( ! params.cantcache )
cache.put( params, m );
return m;
}
}

View File

@@ -1,88 +0,0 @@
package org.luaj.platform;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import org.luaj.lib.MathLib;
import org.luaj.lib.j2se.J2seIoLib;
import org.luaj.lib.j2se.LuajavaLib;
import org.luaj.vm.LDouble;
import org.luaj.vm.LNumber;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class J2sePlatform extends Platform {
public String getName() {
return "j2se";
}
public Reader createReader(InputStream inputStream) {
return new InputStreamReader(inputStream);
}
public String getProperty(String propertyName) {
return System.getProperty(propertyName);
}
protected void installOptionalLibs(LuaState vm) {
vm.installStandardLibs();
J2seIoLib.install(vm._G);
LuajavaLib.install(vm._G);
}
public InputStream openFile(String fileName) {
File file = new File(fileName);
try {
return new FileInputStream(file);
} catch (FileNotFoundException e) {
return null;
}
}
public LNumber mathPow(LNumber base, LNumber exp) {
return LDouble.numberOf(Math.pow(base.toJavaDouble(),exp.toJavaDouble()));
}
public LNumber mathop(int id, LNumber la, LNumber lb) {
double a = la.toJavaDouble();
double b = lb.toJavaDouble();
double z = 0;
switch ( id ) {
default: return unsupportedMathOp();
case MathLib.ATAN2: z = Math.atan2(a, b); break;
case MathLib.FMOD: z = a - (b * ((int)(a/b))); break;
case MathLib.POW: z = Math.pow(a, b); break;
}
return LDouble.numberOf(z);
}
public LNumber mathop(int id, LNumber lx) {
double x = lx.toJavaDouble();
double z = 0;
switch ( id ) {
default: return unsupportedMathOp();
case MathLib.ABS: z = Math.abs(x); break;
case MathLib.ACOS: z = Math.acos(x); break;
case MathLib.ASIN: z = Math.asin(x); break;
case MathLib.ATAN: z = Math.atan(x); break;
case MathLib.COS: z = Math.cos(x); break;
case MathLib.COSH: z = Math.cosh(x); break;
case MathLib.DEG: z = Math.toDegrees(x); break;
case MathLib.EXP: z = Math.exp(x); break;
case MathLib.LOG: z = Math.log(x); break;
case MathLib.LOG10: z = Math.log10(x); break;
case MathLib.RAD: z = Math.toRadians(x); break;
case MathLib.SIN: z = Math.sin(x); break;
case MathLib.SINH: z = Math.sinh(x); break;
case MathLib.SQRT: z = Math.sqrt(x); break;
case MathLib.TAN: z = Math.tan(x); break;
case MathLib.TANH: z = Math.tanh(x); break;
}
return LDouble.numberOf(z);
}
}

View File

@@ -1,89 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.sample;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.luaj.jit.LuaJit;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
* Program to run a lua chunk
*
* @author jim_roseborough
*/
public class LuaJitRunner {
public static void main( String[] args ) throws IOException {
// new lua state
Platform.setInstance(new J2sePlatform());
LuaState state = Platform.newLuaState();
LuaJit.install();
// get script name
for ( int i=0; i<args.length; i++ ) {
String script = args[i];
try {
System.out.println("loading '"+script+"'");
// load the file
InputStream is = null;
File f = new File(script);
if ( f.exists() )
is = new FileInputStream( f );
else
is = LuaJitRunner.class.getResourceAsStream( script );
if ( is == null )
throw new java.io.FileNotFoundException( "not found: "+script );
LPrototype p = LoadState.undump(state, is, script);
// create closure and execute
LClosure c = p.newClosure( state._G );
// do the call
state.pushlvalue(c);
state.call(0, 0);
} catch ( LuaErrorException lee ) {
System.err.println(script+" lua error, "+lee.getMessage() );
} catch ( Throwable t ) {
System.err.println(script+" threw "+t);
t.printStackTrace();
} finally {
System.out.flush();
System.err.flush();
}
}
}
}

View File

@@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.sample;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.luaj.compiler.LuaC;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
* Program to run a lua chunk
*
* @author jim_roseborough
*/
public class LuaRunner {
public static void main( String[] args ) throws IOException {
// new lua state
Platform.setInstance(new J2sePlatform());
LuaState state = Platform.newLuaState();
LuaC.install();
// get script name
for ( int i=0; i<args.length; i++ ) {
String script = args[i];
try {
System.out.println("loading '"+script+"'");
// load the file
InputStream is = null;
File f = new File(script);
if ( f.exists() )
is = new FileInputStream( f );
else
is = LuaRunner.class.getResourceAsStream( script );
if ( is == null )
throw new java.io.FileNotFoundException( "not found: "+script );
LPrototype p = LoadState.undump(state, is, script);
// create closure and execute
LClosure c = p.newClosure( state._G );
// do the call
state.doCall( c, new LValue[0] );
} catch ( LuaErrorException lee ) {
System.err.println(script+" lua error, "+lee.getMessage() );
} catch ( Throwable t ) {
System.err.println(script+" threw "+t);
t.printStackTrace();
} finally {
System.out.flush();
System.err.flush();
}
}
}
}

View File

@@ -1,67 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.sample;
import java.io.IOException;
import java.io.InputStream;
import org.luaj.compiler.LuaC;
import org.luaj.lib.j2se.LuajavaLib;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
* Program to run a compiled lua chunk for test purposes,
* but with the LuaJava add-ons added in
*
* @author jim_roseborough
*/
public class LuajavaRunner {
public static void main( String[] args ) throws IOException {
Platform.setInstance(new J2sePlatform());
LuaC.install();
// new lua state
LuaState state = Platform.newLuaState();
// get script name
String script = (args.length>0? args[0]: "/swingapp.lua");
System.out.println("loading '"+script+"'");
// load the file
InputStream is = LuajavaRunner.class.getResourceAsStream( script );
LPrototype p = LoadState.undump(state, is, script);
// create closure and execute
LClosure c = p.newClosure( state._G );
state.doCall(c, new LValue[0]);
}
}

View File

@@ -1,53 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.sample;
public class SampleClass {
public Object o;
public String s;
public String t;
public SampleClass() {
}
public SampleClass(String a, String b) {
s = a;
t = b;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
public void setObj(Object o) {
this.o = o;
}
public Object getObj() {
return o;
}
}

View File

@@ -1,18 +0,0 @@
package org.luaj.sample;
import org.luaj.platform.*;
import org.luaj.vm.*;
public class SampleJ2seMain {
public static void main(String[] args) {
String script = (args.length>0? args[0]: "src/test/res/swingapp.lua");
Platform.setInstance( new J2sePlatform() );
LuaState vm = Platform.newLuaState();
// uncomment to install the debug library
// org.luaj.lib.DebugLib.install(vm);
org.luaj.compiler.LuaC.install();
vm.getglobal( "dofile" );
vm.pushstring( script );
vm.call( 1, 0 );
}
}

View File

@@ -1,42 +0,0 @@
package org.luaj.sample;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import org.luaj.lib.j2me.Cldc10IoLib;
import org.luaj.platform.J2meMidp20Cldc11Platform;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class SampleMIDlet extends MIDlet {
// the script will be loaded as a resource
private static final String DEFAULT_SCRIPT = "test1.lua";
protected void startApp() throws MIDletStateChangeException {
// get the script as an app property
String script = this.getAppProperty("script");
if ( script == null )
script = DEFAULT_SCRIPT;
// set up the j2me platform. files will be loaded as resources
Platform.setInstance( new J2meMidp20Cldc11Platform(this) );
LuaState vm = Platform.newLuaState();
// extend the basic vm to include the compiler and io packages
org.luaj.compiler.LuaC.install();
Cldc10IoLib.install(vm._G);
// run the script
vm.getglobal( "dofile" );
vm.pushstring( script );
vm.call( 1, 0 );
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
}
protected void pauseApp() {
}
}

View File

@@ -1,69 +0,0 @@
package org.luaj.sample;
import org.luaj.lib.j2se.CoerceJavaToLua;
import org.luaj.platform.*;
import org.luaj.vm.*;
/**
* Program that illustrates how userdata is mapped into lua using
* LuaJava's automated coercion
*/
public class SampleUserdataMain {
public static class MyData {
public int x = 7;
public String y = "seven";
public int xx[] = new int[] { 11, 22, 33, };
public String yy[] = new String[] { "aa", "bb" };
public int xxx[][] = new int[][] { {444, 555}, {666, 777} } ;
public String yyy[][] = new String[][] { { "ccc", "ddd" }, { "eee", "fff" } };
public void initScalars( int newx, String newy ) {
x = newx;
y = newy;
}
public void initArrays( int[] newxx, String[] newyy ) {
xx = newxx;
yy = newyy;
}
public void initMatrices( int[][] newxxx, String[][] newyyy ) {
xxx = newxxx;
yyy = newyyy;
}
public int getx() { return x; }
public String gety() { return y; }
public int[] getxx() { return xx; }
public String[] getyy() { return yy; }
public int[][] getxxx() { return xxx; }
public String[][] getyyy() { return yyy; }
}
public static void main(String[] args) {
Platform.setInstance( new J2sePlatform() );
LuaState vm = Platform.newLuaState();
org.luaj.compiler.LuaC.install();
// test script
vm.getglobal( "loadstring" );
vm.pushstring( "local mydata = ...\n" +
"print( 'mydata', mydata )\n" +
"print( 'mydata.x, mydata.y', mydata.x, mydata.y )\n" +
"print( 'mydata:getx()', mydata:getx() )\n" +
"print( 'mydata:getxx()', mydata:getxx()[1], mydata:getxx()[2] )\n" +
"print( 'mydata:getxxx()', mydata:getxxx()[1][1], mydata:getxxx()[1][2] )\n" +
"print( 'mydata:getyyy()', mydata:getyyy()[1][1], mydata:getyyy()[1][2] )\n" +
"mydata:initScalars(3,'pqr')\n" +
"mydata:initArrays({55,66},{'abc','def'})\n" +
"mydata:initMatrices({{44,55},{66}},{{'qq','rr'},{'ss','tt'}})\n" +
"print( 'mydata:getx()', mydata:getx() )\n" +
"print( 'mydata:getxx()', mydata:getxx()[1], mydata:getxx()[2] )\n" +
"print( 'mydata:getxxx()', mydata:getxxx()[1][1], mydata:getxxx()[1][2] )\n" +
"print( 'mydata:getyyy()', mydata:getyyy()[1][1], mydata:getyyy()[1][2] )\n" +
"");
vm.call( 1, 2 );
System.out.println("load result: "+vm.tostring(-2)+", "+vm.tostring(-1));
vm.settop(1);
// load argument to test script
vm.pushlvalue( CoerceJavaToLua.coerce(new MyData()) );
vm.call( 1, 0 );
}
}

View File

@@ -1 +0,0 @@
org.luaj.script.LuaScriptEngineFactory

View File

@@ -1,45 +0,0 @@
package org.luaj.jit;
import org.luaj.vm.LClosure;
import org.luaj.vm.LNil;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
abstract
public class JitPrototype extends LPrototype {
protected LPrototype p;
public JitPrototype() {
super();
}
protected void unimplemented() {
throw new RuntimeException("unimplemented");
}
protected void setLuaPrototype(LPrototype lp) {
this.p = lp;
}
public LClosure newClosure(LTable env) {
return new JitClosure(this, env);
}
protected static final class JitClosure extends LClosure {
private final JitPrototype jp;
public JitClosure(JitPrototype jitPrototype, LTable env) {
super( jitPrototype.p, env );
this.jp = jitPrototype;
}
public boolean luaStackCall(LuaState vm) {
jp.jitCall(vm,env,this);
return false;
}
}
public abstract void jitCall( LuaState vm, LTable env, JitClosure jcl );
}

View File

@@ -1,718 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. 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.jit;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import org.luaj.compiler.LuaC;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaState;
import org.luaj.vm.Print;
import org.luaj.vm.LoadState.LuaCompiler;
public class LuaJit extends Lua implements LuaCompiler {
private static LuaC luac;
public static void install() {
luac = new LuaC();
LoadState.compiler = new LuaJit();
}
private static int filenum = 0;
private static synchronized String filename() {
return "LuaJit"+(filenum++);
}
public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException {
return jitCompile( luac.compile(firstByte, stream, name) );
}
public static LPrototype jitCompile( LPrototype p ) {
try {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
System.err.println("no java compiler");
return p;
}
// write the file
String name = filename();
new File("jit").mkdirs();
File source = new File("jit/"+name+JavaFileObject.Kind.SOURCE.extension);
PrintStream ps = new PrintStream(new FileOutputStream(source));
writeSource(ps, name, p);
ps.close();
// set up output location
Iterable<? extends File> dest = Arrays.asList(new File[] { new File("bin") });
StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null);
fm.setLocation(StandardLocation.CLASS_OUTPUT, dest);
// compile the file
Iterable<? extends JavaFileObject> compilationUnits = fm.getJavaFileObjects(source);
CompilationTask task = compiler.getTask(null, fm, null, null, null, compilationUnits);
boolean success = task.call();
// instantiate, config and return
if (success) {
// compile sub-prototypes
if ( p.p != null ) {
for ( int i=0, n=p.p.length; i<n; i++ ) {
if ( ! (p.p[i] instanceof JitPrototype) )
p.p[i] = jitCompile( p.p[i] );
}
}
// create JitPrototype instance
Class clazz = Class.forName(name);
Object instance = clazz.newInstance();
JitPrototype jp = (JitPrototype) instance;
jp.setLuaPrototype(p);
return jp;
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
return p;
}
private static String RKBC_jit(int bc) {
return LuaState.ISK(bc) ?
"k"+LuaState.INDEXK(bc):
"s"+bc;
}
private static String GETARG_RKB_jit(int i) {
return RKBC_jit(GETARG_B(i));
}
private static String GETARG_RKC_jit(int i) {
return RKBC_jit(GETARG_C(i));
}
private static Set<Integer> TESTS = new HashSet<Integer>();
static {
TESTS.add( OP_TEST );
TESTS.add( OP_EQ );
TESTS.add( OP_LT );
TESTS.add( OP_LE );
TESTS.add( OP_TESTSET );
}
private static boolean istest(int instr) {
int opcode = Lua.GET_OPCODE(instr);
return TESTS.contains(opcode);
}
private static boolean isjump(int instr) {
if ( OP_JMP != Lua.GET_OPCODE(instr) )
return false;
return true;
}
private static boolean isbackwardjump(int instr) {
return isjump(instr) && (LuaState.GETARG_sBx(instr) < 0);
}
private static boolean isforwardjump(int instr) {
return isjump(instr) && (LuaState.GETARG_sBx(instr) > 0);
}
private static boolean isloopbottom(int instr) {
return isbackwardjump(instr) || OP_FORLOOP == Lua.GET_OPCODE(instr);
}
private static String append( String s, String t ) {
return (s==null? t: t==null? s: s+t);
}
private static void assertTrue(boolean b) {
if ( ! b )
throw new RuntimeException("assert failed");
}
private static String[] extractControlFlow( int[] code ) {
int n = code.length;
String[] s = new String[n];
for ( int pc=0; pc<n; pc++ ) {
int i = code[pc];
// any backward jump is a loop bottom
if ( isbackwardjump(i) ) {
int jmp = LuaState.GETARG_sBx(i);
s[pc+jmp+1] = append( s[pc+jmp+1], "while (true) { if(false)break; /* WHILETOP */ " );
s[pc] = append( "} /* LOOPBOT */ ", s[pc] );
int i2 = code[pc-1];
if ( istest(i2) ) {
s[pc] = append( "break; /* UNTIL */", s[pc] );
}
// TFORLOOP test is at top in Java, not bottom
else if ( Lua.GET_OPCODE(i2) == OP_TFORLOOP ) {
int a = LuaState.GETARG_A(i2);
int c = LuaState.GETARG_C(i2);
assertTrue(c==2);
s[pc+jmp+1] = append( s[pc+jmp+1],
"\n\t\tvm.stack[base+"+(a+3)+"] = s"+(a+0)+";"+ // iterator
"\n\t\tvm.stack[base+"+(a+4)+"] = s"+(a+1)+";"+ // table
"\n\t\tvm.stack[base+"+(a+5)+"] = s"+(a+2)+";"+ // key
"\n\t\tvm.top = base+"+(a+6)+";"+
"\n\t\tvm.call(2,2);"+
"\n\t\ts"+(a+3)+" = vm.stack[base+"+(a+3)+"];"+ // next key
"\n\t\ts"+(a+4)+" = vm.stack[base+"+(a+4)+"];"+ // next value
"\n\t\tif ( s"+(a+3)+".isNil() )"+
"\n\t\t\tbreak;"+
"\n\t\ts"+(a+2)+" = s"+(a+3)+";" ); // save next key
}
}
else if ( isforwardjump(i) ) {
// forward jump to loop bottom is a break
int jmp = LuaState.GETARG_sBx(i);
if ( isloopbottom(code[pc+jmp]) ) {
s[pc] = append( s[pc], "if(true)break;" );
}
// forward jump preceded by test is "if" block
else if ( istest(code[pc-1]) ) {
s[pc] = append( s[pc], "{ /* IF */ " );
s[pc+jmp+1] = append( "} /* ENDIF */ ", s[pc+jmp+1] );
// end of block preceded by forward jump is else clause
if ( isforwardjump(code[pc+jmp]) ) {
int jmp2 = LuaState.GETARG_sBx(code[pc+jmp]);
// unless that jump is a break!
if ( ! isloopbottom(code[pc+jmp+jmp2]) ) {
s[pc+jmp+1] = append( s[pc+jmp+1], "else { /* ELSE */ " );
s[pc+jmp+jmp2+1] = append( "} /* ENDELSE */ ", s[pc+jmp+jmp2+1] );
}
}
}
}
}
// find local variables, jump points
return s;
}
private static void writeSource( PrintStream ps, String name, LPrototype p ) {
int i, a, b, c, o;
String bs, cs;
int[] code = p.code;
LValue[] k = p.k;
String[] controlflow = extractControlFlow(code);
// class header
ps.print(
"import org.luaj.vm.*;\n"+
"import org.luaj.jit.*;\n"+
"import java.io.*;\n"+
"\n"+
"public class "+name+" extends JitPrototype {\n" );
// static constants
int nk = k.length;
if ( nk > 0 ) {
ps.print( "\tprivate LValue k0" ) ;
for (int ik=1; ik<nk; ik++ )
ps.print( ",k"+ik ) ;
ps.println( ";" ) ;
ps.println(" protected void setLuaPrototype(LPrototype lp) {\n" );
ps.println(" super.setLuaPrototype(lp);\n" );
ps.println( " final LValue[] k = p.k;" ) ;
for (int ik=0; ik<nk; ik++ )
ps.println( " k"+ik+" = k["+ik+"];" ) ;
ps.println(" }" ) ;
}
// jit call
ps.println( "\tpublic void jitCall(LuaState vm, LTable env, JitClosure jcl) {" );
// parameters
int ns = p.maxstacksize;
int is = 0;
if ( p.is_vararg == 0 ) {
ps.println( "\t\tvm.checkstack("+(p.maxstacksize+1)+");" );
ps.println( "\t\tvm.settop("+(p.numparams+1)+");");
ps.println( "\t\tint base = vm.base + 1;" );
for (; is<p.numparams; is++ )
ps.println( "\t\tLValue s"+is+" = vm.stack[base+"+is+"];" );
}
for (; is<ns; is++ )
ps.println( "\t\tLValue s"+is+" = LNil.NIL;" );
ps.println("\t\tLClosure newcl;");
ps.println("\t\tByteArrayOutputStream baos;");
ps.println("\t\tLTable t;");
ps.println();
// save var args
if ( p.is_vararg != 0 ) {
ps.println( "\t\tint ncopy, ntotal;" );
ps.println( "\t\tint nvarargs = vm.top - vm.base - 1;" );
ps.println( "\t\tint base = vm.base + 1 + nvarargs;" );
}
ps.println();
// loop until a return instruction is processed,
// or the vm yields
for ( int pc=0; pc<code.length; pc++ ) {
// print the instruction
ps.print( "\n\t\t// ");
Print.printOpCode(ps, p, pc);
ps.println();
if ( controlflow[pc] != null )
ps.println( "\t\t"+controlflow[pc] );
// get instruction
i = code[pc];
// get opcode and first arg
o = (i >> POS_OP) & MAX_OP;
a = (i >> POS_A) & MAXARG_A;
switch (o) {
default:
ps.println( "\t\tunimplemented();");
break;
case LuaState.OP_MOVE: {
b = LuaState.GETARG_B(i);
ps.println( "\t\ts"+a+" = s"+b+";" );
continue;
}
case LuaState.OP_LOADK: {
b = LuaState.GETARG_Bx(i);
ps.println( "\t\ts"+a+" = k"+b+";" );
continue;
}
case LuaState.OP_LOADBOOL: {
// b = LuaState.GETARG_B(i);
// c = LuaState.GETARG_C(i);
// this.stack[base + a] = (b != 0 ? LBoolean.TRUE : LBoolean.FALSE);
// if (c != 0)
// ci.pc++; // skip next instruction (if C)
// continue;
b = LuaState.GETARG_B(i);
c = LuaState.GETARG_C(i);
ps.println( "\t\ts"+a+" = LBoolean."+(b!=0? "TRUE": "FALSE")+";" );
if ( c != 0 )
throw new java.lang.UnsupportedOperationException("can't jit compile LOADBOOL with c != 0");
break;
}
case LuaState.OP_LOADNIL: {
b = LuaState.GETARG_B(i);
ps.print("\t\t");
for ( int j=a; j<=b; j++ )
ps.print("s"+j+"=");
ps.println("LNil.NIL;");
break;
}
case LuaState.OP_GETUPVAL: {
//b = LuaState.GETARG_B(i);
//this.stack[base + a] = cl.upVals[b].getValue();
//continue;
b = LuaState.GETARG_B(i);
ps.println("\t\t\ts"+a+" = jcl.upVals["+b+"].getValue();");
break;
}
case LuaState.OP_GETGLOBAL: {
b = LuaState.GETARG_Bx(i);
ps.println("\t\ts"+a+" = vm.luaV_gettable(env, k"+b+");");
break;
}
case LuaState.OP_GETTABLE: {
b = GETARG_B(i);
cs = GETARG_RKC_jit(i);
ps.println("\t\ts"+a+" = vm.luaV_gettable(s"+b+", "+cs+");");
break;
}
case LuaState.OP_SETGLOBAL: {
b = LuaState.GETARG_Bx(i);
ps.println("\t\tvm.luaV_settable(env, k"+b+", s"+a+");");
break;
}
case LuaState.OP_SETUPVAL: {
b = LuaState.GETARG_B(i);
ps.println("\t\t\tjcl.upVals["+b+"].setValue(s"+a+");");
break;
}
case LuaState.OP_SETTABLE: {
bs = GETARG_RKB_jit(i);
cs = GETARG_RKC_jit(i);
ps.println("\t\tvm.luaV_settable(s"+a+", "+bs+", "+cs+");");
break;
}
case LuaState.OP_NEWTABLE: {
b = GETARG_B(i);
c = GETARG_C(i);
ps.println("\t\ts"+a+" = new LTable("+b+","+c+");");
break;
}
case LuaState.OP_SELF: {
bs = GETARG_RKB_jit(i);
cs = GETARG_RKC_jit(i);
ps.println("\t\ts"+a+" = vm.luaV_gettable((s"+(a+1)+"="+bs+"), "+cs+");");
break;
}
case LuaState.OP_ADD:
case LuaState.OP_SUB:
case LuaState.OP_MUL:
case LuaState.OP_DIV:
case LuaState.OP_MOD:
case LuaState.OP_POW: {
bs = GETARG_RKB_jit(i);
cs = GETARG_RKC_jit(i);
ps.println("\t\ts"+a+" = "+cs+".luaBinOpUnknown("+o+","+bs+");");
break;
}
case LuaState.OP_UNM: {
bs = GETARG_RKB_jit(i);
ps.println("\t\ts"+a+" = "+bs+".luaUnaryMinus();");
}
case LuaState.OP_NOT: {
bs = GETARG_RKB_jit(i);
ps.println("\t\ts"+a+" = ("+bs+".toJavaBoolean()? LBoolean.TRUE: LBoolean.FALSE);");
break;
}
case LuaState.OP_LEN: {
bs = GETARG_RKB_jit(i);
ps.println("\t\ts"+a+" = LInteger.valueOf("+bs+".luaLength());");
}
case LuaState.OP_CONCAT: {
b = LuaState.GETARG_B(i);
c = LuaState.GETARG_C(i);
ps.println("\t\tbaos = new ByteArrayOutputStream();");
for (int j = b; j <= c; j++)
ps.println("\t\ts"+j+".luaConcatTo( baos );");
ps.println("\t\ts"+a+" = new LString( baos.toByteArray() );");
ps.println("\t\tbaos = null;");
break;
}
case LuaState.OP_JMP: {
break;
}
case LuaState.OP_EQ:
case LuaState.OP_LT:
case LuaState.OP_LE: {
bs = GETARG_RKB_jit(i);
cs = GETARG_RKC_jit(i);
ps.println( "\t\tif ( "+(a==0?"!":"")+" "+cs+".luaBinCmpUnknown("+o+", "+bs+") )" );
break;
}
case LuaState.OP_TEST: {
c = LuaState.GETARG_C(i);
ps.println( "\t\tif ( "+(c!=0?"!":"")+" s"+a+".toJavaBoolean() )" );
break;
}
case LuaState.OP_TESTSET: {
// rkb = GETARG_RKB(k, i);
// c = LuaState.GETARG_C(i);
// if (rkb.toJavaBoolean() != (c != 0))
// ci.pc++;
// else
// this.stack[base + a] = rkb;
// continue;
bs = GETARG_RKB_jit(i);
c = LuaState.GETARG_C(i);
ps.println( "\t\tif ( "+(c!=0?"!":"")+" "+bs+".toJavaBoolean() )" );
ps.println( "\t\t\ts"+a+" = "+bs+";" );
ps.println( "\t\telse" );
break;
}
case LuaState.OP_CALL: {
//
//// ra is base of new call frame
//this.base += a;
//
//// number of args
//b = LuaState.GETARG_B(i);
//if (b != 0) // else use previous instruction set top
// top = base + b;
//
//// number of return values we need
//c = LuaState.GETARG_C(i);
//
//// make or set up the call
//this.nresults = c - 1;
//if (this.stack[base].luaStackCall(this))
// return;
//
//// adjustTop only for case when call was completed
//// and number of args > 0. If call completed but
//// c == 0, leave top to point to end of results
//if (c > 0)
// adjustTop(base + c - 1);
//
//// restore base
//base = ci.base;
//
//continue;
b = LuaState.GETARG_B(i);
c = LuaState.GETARG_C(i);
// copy call to vm stack
ps.println( "\t\tvm.stack[base+"+a+"] = s"+a+";" );
// number of args
if (b > 0) { // else use previous instruction set top
for ( int j=1; j<b; j++ )
ps.println( "\t\tvm.stack[base+"+(a+j)+"] = s"+(a+j)+";" );
ps.println( "\t\tvm.top = base+"+(a+b)+";" );
ps.println("\t\tvm.call("+(b-1)+","+(c-1)+");");
} else {
ps.println("\t\tvm.call(vm.top-base+"+(a-1)+","+(c-1)+");");
}
// copy results to local vars
if ( c > 0 )
for ( int j=0; j<c-1; j++ )
ps.println( "\t\ts"+(a+j)+" = vm.stack[base+"+(a+j)+"];" );
break;
}
/*
case LuaState.OP_TAILCALL: {
closeUpVals(base);
// copy down the frame before calling!
// number of args (including the function)
b = LuaState.GETARG_B(i);
if (b == 0)
b = top - (base + a);
// copy call + all args, discard current frame
System.arraycopy(stack, base + a, stack, ci.resultbase, b);
this.base = ci.resultbase;
this.top = base + b;
this.nresults = ci.nresults;
--cc;
// make or set up the call
try {
if (this.stack[base].luaStackCall(this)) {
return;
}
} catch (LuaErrorException e) {
// in case of lua error, we need to restore cc so that
// the debug can get the correct location where the error
// occured.
cc++;
throw e;
}
// adjustTop only for case when call was completed
// and number of args > 0. If call completed but
// c == 0, leave top to point to end of results
if (this.nresults >= 0)
adjustTop(base + nresults);
// force restore of base, etc.
return;
}
*/
case LuaState.OP_RETURN: {
//// number of return vals to return
//b = LuaState.GETARG_B(i) - 1;
//if (b == -1)
// b = top - (base + a);
//
//// close open upvals
//closeUpVals( base );
//
//// number to copy down
//System.arraycopy(stack, base + a, stack, ci.resultbase, b);
//top = ci.resultbase + b;
//
//// adjust results to what caller expected
//if (ci.nresults >= 0)
// adjustTop(ci.resultbase + ci.nresults);
//
//// pop the call stack
//--cc;
//
//// force a reload of the calling context
//return;
// number of return vals to return
if ( Lua.GET_OPCODE(code[pc-1]) == Lua.OP_RETURN )
break;
if ( p.is_vararg != 0 )
ps.println( "\t\tbase -= nvarargs;" );
else
ps.println( "\t\tbase -= 1;" );
b = LuaState.GETARG_B(i);
if (b > 0) {
for ( int j=1; j<b; j++ )
ps.println( "\t\tvm.stack[base+"+(j-1)+"] = s"+(a+j-1)+";" );
ps.println( "\t\tvm.top = base+"+(b-1)+";" );
}
ps.println( "\t\treturn;" );
break;
}
case LuaState.OP_FORPREP: {
// do the test at the top, not the bottom of the loop
b = LuaState.GETARG_sBx(i);
// set up the loop variables
String init = "s"+(a);
String limit = "s"+(a+1);
String step = "s"+(a+2);
String idx = "s"+(a+3);
String back = "back"+pc;
ps.println( "\t\tboolean "+back+"="+step+".luaBinCmpInteger(Lua.OP_LT,0);");
ps.println( "\t\tfor ( "+idx+"="+init+";\n" +
"\t\t\t"+back+"? "+idx+".luaBinCmpUnknown(Lua.OP_LE, "+limit+"): "+limit+".luaBinCmpUnknown(Lua.OP_LE, "+idx+");\n" +
"\t\t\t"+idx+"="+idx+".luaBinOpUnknown(Lua.OP_ADD,"+step+") )\n" +
"\t\t{ /* FORLOOP */");
break;
}
case LuaState.OP_FORLOOP: {
ps.println( "\t\t} /* LOOPBOT */");
break;
}
case LuaState.OP_TFORLOOP: {
break;
}
case LuaState.OP_SETLIST: {
b = LuaState.GETARG_B(i);
c = LuaState.GETARG_C(i);
if (c == 0)
c = code[++pc];
int offset = (c-1) * LFIELDS_PER_FLUSH;
if ( b == 0 ) {
ps.println("\t\tt = (LTable) s"+(a)+";");
ps.println("\t\tfor ( int j=0, nj=vm.top-base-"+(a+1)+"; j<nj; j++ )");
ps.println("\t\t\tt.put("+offset+"+j,vm.stack[base+"+a+"+j]);");
} else {
ps.println("\t\tt = (LTable) s"+(a)+";");
for (int j=1; j<=b; j++)
ps.println("\t\tt.put("+(offset+j)+",s"+(a+j)+");");
}
break;
}
/*
case LuaState.OP_CLOSE: {
closeUpVals( base + a ); // close upvals higher in the stack than position a
continue;
}
*/
case LuaState.OP_CLOSURE: {
//b = LuaState.GETARG_Bx(i);
//proto = cl.p.p[b];
//newClosure = proto.newClosure(cl.env);
//for (int j = 0; j < newClosure.upVals.length; j++, ci.pc++) {
// i = code[ci.pc];
// o = LuaState.GET_OPCODE(i);
// b = LuaState.GETARG_B(i);
// if (o == LuaState.OP_GETUPVAL) {
// newClosure.upVals[j] = cl.upVals[b];
// } else if (o == LuaState.OP_MOVE) {
// newClosure.upVals[j] = findUpVal( base + b );
// } else {
// throw new java.lang.IllegalArgumentException(
// "bad opcode: " + o);
// }
//}
//this.stack[base + a] = newClosure;
//continue;
b = LuaState.GETARG_Bx(i);
ps.println("\t\ts"+a+" = newcl = p.p["+b+"].newClosure(env);");
for (int j = 0, nj=p.p[b].nups; j < nj; j++) {
i = code[++pc];
o = LuaState.GET_OPCODE(i);
b = LuaState.GETARG_B(i);
if (o == LuaState.OP_GETUPVAL) {
ps.println("\t\tnewcl.upVals["+j+"] = newcl.upVals["+b+"];");
} else if (o == LuaState.OP_MOVE) {
ps.println("\t\tnewcl.upVals["+j+"] = vm.findUpVal(base+"+b+");");
} else {
throw new java.lang.IllegalArgumentException("bad opcode: " + o);
}
}
break;
}
case LuaState.OP_VARARG: {
//// figure out how many args to copy
//b = LuaState.GETARG_B(i) - 1;
//nvarargs = this.stack[base - 1];
//n = nvarargs.toJavaInt();
//if (b == LuaState.LUA_MULTRET) {
// b = n; // use entire varargs supplied
//}
//
//// copy args up to call stack area
//checkstack(a+b);
//for (int j = 0; j < b; j++)
// this.stack[base + a + j] = (j < n ? this.stack[base
// - n + j - 1]
// : LNil.NIL);
//top = base + a + b;
//continue;
b = LuaState.GETARG_B(i) - 1;
if ( b == LuaState.LUA_MULTRET ) {
ps.println( "\t\tncopy = ntotal = nvarargs;" );
} else {
ps.println( "\t\tncopy = Math.min(ntotal="+b+",nvarargs);" );
}
ps.println( "\t\tSystem.arraycopy(vm.stack,base-nvarargs,vm.stack,base+"+a+",ncopy);" );
ps.println( "\t\tfor (int j = ncopy; j < ntotal; j++)" );
ps.println( "\t\t\tvm.stack[base+j] = LNil.NIL;" );
ps.println( "\t\tvm.top = base+ntotal+"+(a)+";" );
break;
}
}
}
ps.print(
" }\n"+
"}\n" );
}
}

View File

@@ -1,317 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.script;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberInputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
import org.luaj.compiler.LuaC;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LDouble;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
*
* @author jim_roseborough
*/
public class LuaScriptEngine implements ScriptEngine, Compilable {
private static final String __ENGINE_VERSION__ = Lua._VERSION;
private static final String __NAME__ = "Luaj";
private static final String __SHORT_NAME__ = "Luaj";
private static final String __LANGUAGE__ = "lua";
private static final String __LANGUAGE_VERSION__ = "5.1";
private static final String __ARGV__ = "arg";
private static final String __FILENAME__ = "?";
static {
Platform.setInstance(new J2sePlatform());
LuaC.install();
}
private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory();
private ScriptContext defaultContext;
private final LuaState luaState;
public LuaScriptEngine() {
// create lua state
luaState = Platform.getInstance().newLuaState();
// set up context
ScriptContext ctx = new SimpleScriptContext();
ctx.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
setContext(ctx);
// set special values
put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
put(LANGUAGE, __LANGUAGE__);
put(ENGINE, __NAME__);
put(ENGINE_VERSION, __ENGINE_VERSION__);
put(ARGV, __ARGV__);
put(FILENAME, __FILENAME__);
put(NAME, __SHORT_NAME__);
put("THREADING", null);
}
public Object eval(String script) throws ScriptException {
return eval(new StringReader(script));
}
public Object eval(String script, ScriptContext context) throws ScriptException {
return eval(new StringReader(script), context);
}
public Object eval(String script, Bindings bindings) throws ScriptException {
return eval(new StringReader(script), bindings);
}
public Object eval(Reader reader) throws ScriptException {
return eval(reader, getContext());
}
public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
return compile(reader).eval(scriptContext);
}
public Object eval(Reader reader, Bindings bindings) throws ScriptException {
ScriptContext c = getContext();
Bindings current = c.getBindings(ScriptContext.ENGINE_SCOPE);
c.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
Object result = eval(reader);
c.setBindings(current, ScriptContext.ENGINE_SCOPE);
return result;
}
public void put(String key, Object value) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
((LuaBindings)b).put(key, value);
}
public Object get(String key) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
return ((LuaBindings)b).get(key);
}
public Bindings getBindings(int scope) {
return getContext().getBindings(scope);
}
public void setBindings(Bindings bindings, int scope) {
getContext().setBindings(bindings, scope);
}
public Bindings createBindings() {
return new LuaBindings( luaState );
}
public ScriptContext getContext() {
return defaultContext;
}
public void setContext(ScriptContext context) {
defaultContext = context;
}
public ScriptEngineFactory getFactory() {
return myFactory;
}
public CompiledScript compile(String script) throws ScriptException {
return compile(new StringReader(script));
}
public CompiledScript compile(Reader reader) throws ScriptException {
try {
InputStream ris = new Utf8Encoder(reader);
LineNumberInputStream is = new LineNumberInputStream( ris);
try {
final LPrototype p = LoadState.undump(luaState, is, "script");
return new CompiledScript() {
public Object eval(ScriptContext context) throws ScriptException {
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
LuaBindings lb = (LuaBindings) b;
LClosure c = p.newClosure( lb.env );
luaState.doCall( c, new LValue[0] );
return luaState.topointer(1);
}
public ScriptEngine getEngine() {
return LuaScriptEngine.this;
}
};
} catch ( LuaErrorException lee ) {
throw new ScriptException(lee.getMessage(), "script", is.getLineNumber() );
} finally {
is.close();
}
} catch ( Throwable t ) {
throw new ScriptException("eval threw "+t.toString());
}
}
// ------ lua bindings -----
private static final class LuaBindings extends LFunction implements Bindings {
private LTable env;
private LTable mt;
private LuaBindings( LuaState luaState ) {
mt = new LTable();
mt.put( LValue.TM_INDEX, luaState._G );
clear();
}
public void clear() {
env = new LTable();
env.luaSetMetatable(mt);
}
private Object toJava(LValue v) {
switch ( v.luaGetType() ) {
case Lua.LUA_TNIL: return null;
case Lua.LUA_TSTRING: return v.toJavaString();
case Lua.LUA_TUSERDATA: return v.toJavaInstance();
case Lua.LUA_TNUMBER: return v.isInteger()? (Object) v.toJavaBoxedInteger(): (Object) v.toJavaBoxedDouble();
default:
throw new java.lang.UnsupportedOperationException(
"LuaBindings cannot convert lua type '"+v.luaGetTypeName()+"' to Java");
}
}
private LValue toLua(Object javaValue) {
if ( javaValue instanceof Number ) {
return LDouble.numberOf(((Number)javaValue).doubleValue());
} else if ( javaValue instanceof String ) {
return LString.valueOf(javaValue.toString());
} else if ( javaValue == null ) {
return LNil.NIL;
} else {
return new LUserData(javaValue);
}
}
public boolean containsKey(Object key) {
return env.containsKey(toLua(key));
}
public Object get(Object key) {
return toJava(env.get(toLua(key)));
}
public Object put(String name, Object value) {
LValue key = toLua(name);
Object result = toJava(env.get(key));
env.put(key, toLua(value));
return result;
}
public void putAll(Map<? extends String, ? extends Object> toMerge) {
for ( Iterator it=toMerge.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Object> e = (Map.Entry<String, Object>) it.next();
put( e.getKey(), e.getValue() );
}
}
public Object remove(Object javakey) {
LValue key = toLua(javakey);
Object result = toJava(env.get(key));
env.put(key, LNil.NIL);
return result;
}
public boolean containsValue(Object value) {
throw new java.lang.UnsupportedOperationException(
"containsValue() not supported for LuaBindings");
}
public Set<java.util.Map.Entry<String, Object>> entrySet() {
throw new java.lang.UnsupportedOperationException(
"entrySet() not supported for LuaBindings");
}
public boolean isEmpty() {
throw new java.lang.UnsupportedOperationException(
"isEmpty() not supported for LuaBindings");
}
public Set<String> keySet() {
throw new java.lang.UnsupportedOperationException(
"keySet() not supported for LuaBindings");
}
public int size() {
throw new java.lang.UnsupportedOperationException(
"size() not supported for LuaBindings");
}
public Collection<Object> values() {
throw new java.lang.UnsupportedOperationException(
"values() not supported for LuaBindings");
}
}
// ------ convert char stream to byte stream for lua compiler -----
private final class Utf8Encoder extends InputStream {
private final Reader r;
private final int[] buf = new int[2];
private int n;
private Utf8Encoder(Reader r) {
this.r = r;
}
public int read() throws IOException {
if ( n > 0 )
return buf[--n];
int c = r.read();
if ( c < 0x80 )
return c;
n = 0;
if ( c < 0x800 ) {
buf[n++] = (0x80 | ( c & 0x3f));
return (0xC0 | ((c>>6) & 0x1f));
} else {
buf[n++] = (0x80 | ( c & 0x3f));
buf[n++] = (0x80 | ((c>>6) & 0x3f));
return (0xE0 | ((c>>12) & 0x0f));
}
}
}
}

View File

@@ -1,127 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.script;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
/**
*
* @author jim_roseborough
*/
public class LuaScriptEngineFactory implements ScriptEngineFactory {
private static final String FILEEXT = ".lua";
private static final String [] MIMETYPES = {
"text/plain",
"text/lua",
"application/lua"
};
private static final String [] NAMES = {
"lua",
"luaj",
};
private ScriptEngine myScriptEngine;
private List<String> extensions;
private List<String> mimeTypes;
private List<String> names;
public LuaScriptEngineFactory() {
myScriptEngine = new LuaScriptEngine();
extensions = Collections.nCopies(1, FILEEXT);
mimeTypes = Arrays.asList(MIMETYPES);
names = Arrays.asList(NAMES);
}
public String getEngineName() {
return getScriptEngine().get(ScriptEngine.ENGINE).toString();
}
public String getEngineVersion() {
return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString();
}
public List<String> getExtensions() {
return extensions;
}
public List<String> getMimeTypes() {
return mimeTypes;
}
public List<String> getNames() {
return names;
}
public String getLanguageName() {
return getScriptEngine().get(ScriptEngine.LANGUAGE).toString();
}
public String getLanguageVersion() {
return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString();
}
public Object getParameter(String key) {
return getScriptEngine().get(key).toString();
}
public String getMethodCallSyntax(String obj, String m, String... args) {
StringBuffer sb = new StringBuffer();
sb.append(obj + ":" + m + "(");
int len = args.length;
for (int i = 0; i < len; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(args[i]);
}
sb.append(")");
return sb.toString();
}
public String getOutputStatement(String toDisplay) {
return "print(" + toDisplay + ")";
}
public String getProgram(String ... statements) {
StringBuffer sb = new StringBuffer();
int len = statements.length;
for (int i = 0; i < len; i++) {
if (i > 0) {
sb.append('\n');
}
sb.append(statements[i]);
}
return sb.toString();
}
public ScriptEngine getScriptEngine() {
return myScriptEngine;
}
}

View File

@@ -1,67 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. 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.script;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineSample {
public static void main(String [] args) {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine e = sem.getEngineByExtension(".lua");
ScriptEngineFactory f = e.getFactory();
System.out.println( "Engine name: " +f.getEngineName() );
System.out.println( "Engine Version: " +f.getEngineVersion() );
System.out.println( "LanguageName: " +f.getLanguageName() );
System.out.println( "Language Version: " +f.getLanguageVersion() );
String statement = f.getOutputStatement("\"hello, world\"");
System.out.println(statement);
try {
e.eval(statement);
e.put("x", 25);
e.eval("y = math.sqrt(x)");
System.out.println( "y="+e.get("y") );
e.put("x", 2);
e.eval("y = math.sqrt(x)");
System.out.println( "y="+e.get("y") );
CompiledScript cs = ((Compilable)e).compile("y = math.sqrt(x); return y");
Bindings b = e.createBindings();
b.put("x", 3);
System.out.println( "eval: "+cs.eval(b) );
System.out.println( "y="+b.get("y") );
e.eval("\n\nbogus example\n\n");
} catch (ScriptException ex) {
ex.printStackTrace();
}
}
}

View File

@@ -1,154 +0,0 @@
package org.luaj.jit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.TestCase;
import org.luaj.compiler.LuaC;
import org.luaj.lib.BaseLib;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
* Simple test cases for lua jit basic functional test
*/
public class LuaJitBasicTest extends TestCase {
static {
Platform.setInstance(new J2sePlatform());
LuaC.install();
}
public void testPrintHelloWorld() throws IOException {
stringTest( "print( 'hello, world' )" );
}
public void testArgPassing() throws IOException {
stringTest(
"local function f(a,b)\n" +
" print('a',a,'b',b)\n" +
" return 'c','d'\n" +
"end\n" +
"print( 'f1', f(123) )\n" +
"print( 'f2', f(456,789) )\n" +
"print( 'f3', f(12,34,56) )\n" );
}
public void testForInDoEnd() throws IOException {
stringTest(
"local t = {abc=123,def=456}\n" +
"for k,v in pairs(t) do\n" +
" print( 'k,v', k, v )\n" +
"end");
}
public void testForIEqualsDoEnd() throws IOException {
stringTest(
"print 'starting'\n" +
"for i=1,5,2 do\n" +
" print( 'i', i )\n" +
"end");
}
public void testRepeatUntil() throws IOException {
stringTest(
"local i=7\n" +
"repeat\n"+
" print(i)\n"+
"until i\n");
}
public void testWhileDoEnd() throws IOException {
stringTest(
"local i=4\n" +
"while i>0 do\n"+
" print( i )\n"+
" i = i-1\n"+
"end\n");
}
public void testForIEqualsDoBreakEnd() throws IOException {
stringTest(
"print 'starting'\n" +
"for i=1,5,2 do\n" +
" print( 'i', i )\n" +
" break\n" +
"end");
}
public void testRepeatUntilBreak() throws IOException {
stringTest(
"local i=7\n" +
"repeat\n"+
" print(i)\n"+
" break\n"+
"until i\n");
}
public void testWhileDoBreak() throws IOException {
stringTest(
"local i=4\n" +
"while i>0 do\n"+
" print( i )\n"+
" i = i-1\n"+
" break\n"+
"end\n");
}
public void testIfThenEnd() throws IOException {
stringTest(
"if a then\n" +
" print(1)\n" +
"end\n" +
"print(2)\n" );
}
public void testIfThenElseEnd() throws IOException {
stringTest(
"if a then\n" +
" print(1)\n" +
"else\n" +
" print(2)\n" +
"end\n" +
"print(3)\n" );
}
public void testIfThenElseifElseEnd() throws IOException {
stringTest(
"if a then\n" +
" print(1)\n" +
"elseif b then \n" +
" print(2)\n" +
"else\n" +
" print(3)\n" +
"end\n" +
"print(4)\n" );
}
private void stringTest(String program) throws IOException {
InputStream is = new ByteArrayInputStream(program.getBytes());
LPrototype p = LuaC.compile(is, "program");
String expected = run( p );
LPrototype q = LuaJit.jitCompile( p );
assertTrue(p!=q);
String actual = run( q );
assertEquals( expected, actual );
}
private static String run(LPrototype p) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BaseLib.redirectOutput(outputStream);
LuaState vm = Platform.newLuaState();
LClosure c = p.newClosure(vm._G);
vm.pushlvalue(c);
vm.call(0, 0);
return outputStream.toString();
}
}

View File

@@ -1,92 +0,0 @@
package org.luaj.jit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.TestCase;
import org.luaj.compiler.LuaC;
import org.luaj.lib.BaseLib;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class LuaJitPerfTest extends TestCase {
static {
Platform.setInstance(new J2sePlatform());
LuaC.install();
}
//
// public void testFannkuch() throws IOException {
// timedFileTest( "fannkuch.lua" );
// }
//
// public void testMandelbrot() throws IOException {
// timedFileTest( "mandelbrot.lua" );
// }
public void testNbody() throws IOException {
timedFileTest( "nbody.lua" );
}
//
// public void testForLoop() throws IOException {
// timedTest( "for loop",
// "local sum=0\n" +
// "for i=1,10000,1 do\n" +
// " sum = sum + i\n" +
// "end");
// }
//
private void timedFileTest(String filename) throws IOException {
File file = new File("src/test/perf/"+filename);
int len = (int) file.length();
byte[] b = new byte[len];
DataInputStream dis = new DataInputStream( new FileInputStream( file ) );
dis.readFully(b);
dis.close();
timedTest( filename, new String(b) );
}
private void timedTest(String testName, String script) throws IOException {
System.out.println("---- "+testName+" ----");
InputStream is = new ByteArrayInputStream(script.getBytes());
LPrototype p = LuaC.compile(is, "script");
int plain = timeTrial( "plain", p );
LPrototype q = LuaJit.jitCompile( p );
assertTrue(p!=q);
int jit = timeTrial( "jit", q );
System.out.println("plain="+plain+" jit="+jit+" ratio="+(double)jit/(double)plain);
assertTrue( "jit faster than plain", jit > plain );
}
private static int timeTrial(String type, LPrototype p) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BaseLib.redirectOutput(outputStream);
LuaState vm = Platform.newLuaState();
LClosure c = p.newClosure(vm._G);
int globalCount = 0;
for ( int i=0; i<5; i++ ) {
int localCount = 0;
long t1 = System.currentTimeMillis() + 1000;
while ( t1 > System.currentTimeMillis() ) {
vm.pushlvalue(c);
vm.call(0, 0);
localCount++;
}
System.out.println(type+": "+(localCount));
System.out.flush();
globalCount += localCount;
}
return globalCount;
}
}

View File

@@ -1,21 +0,0 @@
package org.luaj.jit;
import java.io.IOException;
import org.luaj.jit.LuaJit;
import org.luaj.vm.LPrototype;
import org.luaj.vm.CompatibiltyTest;
import org.luaj.vm.LuaState;
/**
* Suite of standard tests, but using the LuaJit compiler
* for all loaded prototypes.
*/
public class LuaJitTest extends CompatibiltyTest {
protected LPrototype loadScript( LuaState state, String name ) throws IOException {
LPrototype p = super.loadScript(state, name);
return LuaJit.jitCompile(p);
}
}

View File

@@ -1,15 +0,0 @@
-- Clear out builtin math package
math = nil
local function autoload(table, key)
local pkg = require(key)
table[key] = pkg
return pkg
end
setmetatable(_G, { __index = autoload } )
-- local result = math.sqrt(9.0)
-- print("x=", result)
print("square root of 9.0 is ", math.sqrt(9.0))
print("square root of 4.0 is ", math.sqrt(4.0))

View File

@@ -1,280 +0,0 @@
-- unit tests for functions in BaseLib.java
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- wrap pcall to return one result
-- error message are tested elsewhere
local pc = pcall
local pcall = function(...)
local s,e = pc(...)
if s then return e end
return false, type(e)
end
-- print
print()
print(11)
print("abc",123,nil,"pqr")
-- assert
print( 'assert(true)', assert(true) )
print( 'pcall(assert,true)', pcall(assert,true) )
print( 'pcall(assert,false)', pcall(assert,false) )
print( 'pcall(assert,nil)', pcall(assert,nil) )
print( 'pcall(assert,true,"msg")', pcall(assert,true,"msg") )
print( 'pcall(assert,false,"msg")', pcall(assert,false,"msg") )
print( 'pcall(assert,nil,"msg")', pcall(assert,nil,"msg") )
print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") )
-- collectgarbage (not supported)
print( 'collectgarbage("count")', type(collectgarbage("count")))
print( 'collectgarbage("collect")', type(collectgarbage("collect")))
print( 'collectgarbage("count")', type(collectgarbage("count")))
-- dofile (not supported)
-- ipairs
print( 'pcall(ipairs)', pcall(ipairs) )
print( 'pcall(ipairs,nil)', pcall(ipairs,nil) )
print( 'pcall(ipairs,"a")', pcall(ipairs,"a") )
print( 'pcall(ipairs,1)', pcall(ipairs,1) )
for k,v in ipairs({}) do print('ipairs1',k,v)end
for k,v in ipairs({'one','two'}) do print('ipairs2',k,v)end
for k,v in ipairs({aa='aaa',bb='bbb'}) do print('ipairs3',k,v)end
for k,v in ipairs({aa='aaa',bb='bbb','one','two'}) do print('ipairs4',k,v)end
for k,v in ipairs({[30]='30',[20]='20'}) do print('ipairs5',k,v)end
-- load
-- loadfile
-- loadstring
local lst = "print(3+4); return 8"
local chunk, err = loadstring( lst )
print( 'loadstring("'..lst..'")', id(chunk), err )
print( 'loadstring("'..lst..'")()', chunk() )
-- pairs
print( 'pcall(pairs)', pcall(pairs) )
print( 'pcall(pairs,nil)', pcall(pairs,nil) )
print( 'pcall(pairs,"a")', pcall(pairs,"a") )
print( 'pcall(pairs,1)', pcall(pairs,1) )
for k,v in pairs({}) do print('pairs1',k,v)end
for k,v in pairs({'one','two'}) do print('pairs2',k,v)end
for k,v in pairs({aa='aaa',bb='bbb'}) do print('pairs3',k,v)end
for k,v in pairs({aa='aaa',bb='bbb','one','two'}) do print('pairs4',k,v)end
for k,v in pairs({[20]='30',[30]='20'}) do print('pairs5',k,v)end
-- _G
print( '_G["abc"] (before)', _G["abc"] )
abc='def'
print( '_G["abc"] (after)', _G["abc"] )
-- type
print( 'type(nil)', type(nil) )
print( 'type("a")', type("a") )
print( 'type(1)', type(1) )
print( 'type(1.5)', type(1.5) )
print( 'type(function() end)', type(function() end) )
print( 'type({})', type({}) )
print( 'type(true)', type(true) )
print( 'type(false)', type(false) )
print( 'pcall(type,type)', pcall(type,type) )
print( 'pcall(type)', pcall(type) )
print( '(function() return pcall(type) end)()', (function() return pcall(type) end)() )
local function la() return pcall(type) end
print( 'la()', la() )
function ga() return pcall(type) end
print( 'ga()', ga() )
-- getfenv, setfenv: tested in setfenv.lua
-- getmetatable, setmetatable
ta = { aa1="aaa1", aa2="aaa2" }
tb = { bb1="bbb1", bb2="bbb2" }
print( 'getmetatable(ta)', getmetatable(ta) )
print( 'getmetatable(tb)', getmetatable(tb) )
print( 'setmetatable(ta),{cc1="ccc1"}', type( setmetatable(ta,{cc1="ccc1"}) ) )
print( 'setmetatable(tb),{dd1="ddd1"}', type( setmetatable(tb,{dd1="ddd1"}) ) )
print( 'getmetatable(ta)["cc1"]', getmetatable(ta)["cc1"] )
print( 'getmetatable(tb)["dd1"]', getmetatable(tb)["dd1"] )
print( 'getmetatable(1)', getmetatable(1) )
print( 'pcall(setmetatable,1)', pcall(setmetatable,1) )
print( 'pcall(setmetatable,nil)', pcall(setmetatable,nil) )
print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") )
print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) )
-- rawget,rawset
local mt = {aa="aaa", bb="bbb"}
mt.__index = mt
mt.__newindex = mt
local s = {cc="ccc", dd="ddd", }
local t = {cc="ccc", dd="ddd"}
setmetatable(t,mt)
print( 'pcall(rawget)', pcall(rawget))
print( 'pcall(rawget,"a")', pcall(rawget,"a"))
print( 'pcall(rawget,s)', pcall(rawget,s))
print( 'pcall(rawget,t)', pcall(rawget,t))
function printtables()
function printtable(name,t)
print( ' '..name, t["aa"], t["bb"], t["cc"], t["dd"], t["ee"], t["ff"], t["gg"] )
print( ' '..name,
rawget(t,"aa"),
rawget(t,"bb"),
rawget(t,"cc"),
rawget(t,"dd"),
rawget(t,"ee"),
rawget(t,"ff"),
rawget(t,"gg") )
end
printtable( 's', s )
printtable( 't', t )
printtable( 'mt', mt )
end
printtables()
print( 'pcall(rawset,s,"aa","www")', id(rawset(s,"aa","www")))
printtables()
print( 'pcall(rawset,s,"cc","xxx")', id(rawset(s,"cc","xxx")))
printtables()
print( 'pcall(rawset,t,"bb","yyy")', id(rawset(t,"aa","yyy")))
printtables()
print( 'pcall(rawset,t,"dd","zzz")', id(rawset(s,"dd","zzz")))
printtables()
printtables()
print( 's["ee"]="ppp"' ); s["ee"]="ppp"
printtables()
print( 's["cc"]="qqq"' ); s["cc"]="qqq"
printtables()
print( 's["bb"]="rrr"' ); t["bb"]="rrr"
printtables()
print( 's["dd"]="sss"' ); t["dd"]="sss"
printtables()
print( 's["gg"]="ttt"' ); mt["gg"]="ttt"
printtables()
-- select
print( 'pcall(select)', pcall(select) )
print( 'select(1,11,22,33,44,55)', select(1,11,22,33,44,55) )
print( 'select(2,11,22,33,44,55)', select(2,11,22,33,44,55) )
print( 'select(3,11,22,33,44,55)', select(3,11,22,33,44,55) )
print( 'select(4,11,22,33,44,55)', select(4,11,22,33,44,55) )
print( 'pcall(select,5,11,22,33,44,55)', pcall(select,5,11,22,33,44,55) )
print( 'pcall(select,6,11,22,33,44,55)', pcall(select,6,11,22,33,44,55) )
print( 'pcall(select,7,11,22,33,44,55)', pcall(select,7,11,22,33,44,55) )
print( 'pcall(select,0,11,22,33,44,55)', pcall(select,0,11,22,33,44,55) )
print( 'pcall(select,-1,11,22,33,44,55)', pcall(select,-1,11,22,33,44,55) )
print( 'pcall(select,-2,11,22,33,44,55)', pcall(select,-2,11,22,33,44,55) )
print( 'pcall(select,-4,11,22,33,44,55)', pcall(select,-4,11,22,33,44,55) )
print( 'pcall(select,-5,11,22,33,44,55)', pcall(select,-5,11,22,33,44,55) )
print( 'pcall(select,-6,11,22,33,44,55)', pcall(select,-6,11,22,33,44,55) )
print( 'pcall(select,1)', pcall(select,1) )
print( 'pcall(select,select)', pcall(select,select) )
print( 'pcall(select,{})', pcall(select,{}) )
print( 'pcall(select,"2",11,22,33)', pcall(select,"2",11,22,33) )
print( 'pcall(select,"abc",11,22,33)', pcall(select,"abc",11,22,33) )
-- tonumber
print( 'pcall(tonumber)', pcall(tostring) )
print( 'pcall(tonumber,nil)', pcall(tonumber,nil) )
print( 'pcall(tonumber,"abc")', pcall(tonumber,"abc") )
print( 'pcall(tonumber,"123")', pcall(tonumber,"123") )
print( 'pcall(tonumber,"123",10)', pcall(tonumber,"123", 10) )
print( 'pcall(tonumber,"123",8)', pcall(tonumber,"123", 8) )
print( 'pcall(tonumber,"123",6)', pcall(tonumber,"123", 6) )
print( 'pcall(tonumber,"10101",4)', pcall(tonumber,"10101", 4) )
print( 'pcall(tonumber,"10101",3)', pcall(tonumber,"10101", 3) )
print( 'pcall(tonumber,"10101",2)', pcall(tonumber,"10101", 2) )
print( 'pcall(tonumber,"1a1",16)', pcall(tonumber,"1a1", 16) )
print( 'pcall(tonumber,"1a1",32)', pcall(tonumber,"1a1", 32) )
print( 'pcall(tonumber,"1a1",54)', pcall(tonumber,"1a1", 54) )
print( 'pcall(tonumber,"1a1",1)', pcall(tonumber,"1a1", 1) )
print( 'pcall(tonumber,"1a1",0)', pcall(tonumber,"1a1", 0) )
print( 'pcall(tonumber,"1a1",-1)', pcall(tonumber,"1a1", -1) )
print( 'pcall(tonumber,"1a1","32")', pcall(tonumber,"1a1", "32") )
print( 'pcall(tonumber,"123","456")', pcall(tonumber,"123","456") )
print( 'pcall(tonumber,"1a1",10)', pcall(tonumber,"1a1", 10) )
print( 'pcall(tonumber,"151",4)', pcall(tonumber,"151", 4) )
print( 'pcall(tonumber,"151",3)', pcall(tonumber,"151", 3) )
print( 'pcall(tonumber,"151",2)', pcall(tonumber,"151", 2) )
print( 'pcall(tonumber,"123",8,8)', pcall(tonumber,"123", 8, 8) )
print( 'pcall(tonumber,123)', pcall(tonumber,123) )
print( 'pcall(tonumber,true)', pcall(tonumber,true) )
print( 'pcall(tonumber,false)', pcall(tonumber,false) )
print( 'pcall(tonumber,tonumber)', pcall(tonumber,tonumber) )
print( 'pcall(tonumber,function() end)', pcall(tonumber,function() end) )
print( 'pcall(tonumber,{"one","two",a="aa",b="bb"})', pcall(tonumber,{"one","two",a="aa",b="bb"}) )
print( 'pcall(tonumber,"123.456")', pcall(tonumber,"123.456") )
print( 'pcall(tonumber," 123.456")', pcall(tonumber," 123.456") )
print( 'pcall(tonumber," 234qwer")', pcall(tonumber," 234qwer") )
print( 'pcall(tonumber,"0x20")', pcall(tonumber,"0x20") )
print( 'pcall(tonumber," 0x20")', pcall(tonumber," 0x20") )
print( 'pcall(tonumber,"0x20 ")', pcall(tonumber,"0x20 ") )
print( 'pcall(tonumber," 0x20 ")', pcall(tonumber," 0x20 ") )
print( 'pcall(tonumber,"0X20")', pcall(tonumber,"0X20") )
print( 'pcall(tonumber," 0X20")', pcall(tonumber," 0X20") )
print( 'pcall(tonumber,"0X20 ")', pcall(tonumber,"0X20 ") )
print( 'pcall(tonumber," 0X20 ")', pcall(tonumber," 0X20 ") )
print( 'pcall(tonumber,"0x20",10)', pcall(tonumber,"0x20",10) )
print( 'pcall(tonumber,"0x20",16)', pcall(tonumber,"0x20",16) )
print( 'pcall(tonumber,"0x20",8)', pcall(tonumber,"0x20",8) )
-- tostring
print( 'pcall(tostring)', pcall(tostring) )
print( 'pcall(tostring,nil)', pcall(tostring,nil) )
print( 'pcall(tostring,"abc")', pcall(tostring,"abc") )
print( 'pcall(tostring,"abc","def")', pcall(tostring,"abc","def") )
print( 'pcall(tostring,123)', pcall(tostring,123) )
print( 'pcall(tostring,true)', pcall(tostring,true) )
print( 'pcall(tostring,false)', pcall(tostring,false) )
print( 'tostring(tostring)', type(tostring(tostring)) )
print( 'tostring(function() end)', type(tostring(function() end)) )
print( 'tostring({"one","two",a="aa",b="bb"})', type(tostring({"one","two",a="aa",b="bb"})) )
-- unpack
print( 'pcall(unpack)', pcall(unpack) );
print( 'pcall(unpack,nil)', pcall(unpack,nil) );
print( 'pcall(unpack,"abc")', pcall(unpack,"abc") );
print( 'pcall(unpack,1)', pcall(unpack,1) );
print( 'unpack({"aa"})', unpack({"aa"}) );
print( 'unpack({"aa","bb"})', unpack({"aa","bb"}) );
print( 'unpack({"aa","bb","cc"})', unpack({"aa","bb","cc"}) );
local t = {"aa","bb","cc","dd","ee","ff"}
print( 'pcall(unpack,t)', pcall(unpack,t) );
print( 'pcall(unpack,t,2)', pcall(unpack,t,2) );
print( 'pcall(unpack,t,2,5)', pcall(unpack,t,2,5) );
print( 'pcall(unpack,t,2,6)', pcall(unpack,t,2,6) );
print( 'pcall(unpack,t,2,7)', pcall(unpack,t,2,7) );
print( 'pcall(unpack,t,1)', pcall(unpack,t,1) );
print( 'pcall(unpack,t,1,5)', pcall(unpack,t,1,5) );
print( 'pcall(unpack,t,1,6)', pcall(unpack,t,1,6) );
print( 'pcall(unpack,t,1,7)', pcall(unpack,t,1,7) );
print( 'pcall(unpack,t,0)', pcall(unpack,t,0) );
print( 'pcall(unpack,t,0,5)', pcall(unpack,t,0,5) );
print( 'pcall(unpack,t,0,6)', pcall(unpack,t,0,6) );
print( 'pcall(unpack,t,0,7)', pcall(unpack,t,0,7) );
print( 'pcall(unpack,t,-1)', pcall(unpack,t,-1) );
print( 'pcall(unpack,t,-1,5)', pcall(unpack,t,-1,5) );
print( 'pcall(unpack,t,-1,6)', pcall(unpack,t,-1,6) );
print( 'pcall(unpack,t,-1,7)', pcall(unpack,t,-1,7) );
print( 'pcall(unpack,t,2,4)', pcall(unpack,t,2,4) );
print( 'pcall(unpack,t,2,5)', pcall(unpack,t,2,5) );
print( 'pcall(unpack,t,2,6)', pcall(unpack,t,2,6) );
print( 'pcall(unpack,t,2,7)', pcall(unpack,t,2,7) );
print( 'pcall(unpack,t,2,8)', pcall(unpack,t,2,8) );
print( 'pcall(unpack,t,2,2)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,1)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) );
t[0] = 'zz'
t[-1] = 'yy'
t[-2] = 'xx'
print( 'pcall(unpack,t,0)', pcall(unpack,t,0) );
print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) );
print( 'pcall(unpack,t,"3")', pcall(unpack,t,"3") );
print( 'pcall(unpack,t,"a")', pcall(unpack,t,"a") );
print( 'pcall(unpack,t,function() end)', pcall(unpack,t,function() end) );
-- _VERSION
print( '_VERSION', type(_VERSION) )

View File

@@ -1,31 +0,0 @@
t = true
f = false
n = nil
s = "Hello"
z = 0
one = 1
print(t)
print(f)
print(not t)
print(not f)
print(not n)
print(not z)
print(not s)
print(not(not(t)))
print(not(not(z)))
print(not(not(n)))
print(t and f)
print(t or f)
print(f and t)
print(f or t)
print(f or one)
print(f or z)
print(f or n)
print(t and one)
print(t and z)
print(t and n)

View File

@@ -1,28 +0,0 @@
local function f(x)
-- tailcall to a builtin
return math.sin(x)
end
local function factorial(i)
local function helper(product, n)
if n <= 0 then
return product
else
-- tail call to a nested Lua function
return helper(n * product, n - 1)
end
end
return helper(1, i)
end
local result1 = factorial(5)
print(result1)
print(factorial(5))
local function truncate(x)
local s = tostring(x)
return (#s<6 and s) or string.sub(s,1,6)..'...'
end
local result2 = f(math.pi)
print(truncate(result2))
print(truncate(f(math.pi)))

View File

@@ -1,5 +0,0 @@
print("5.0"+3.1)
print(4+"7.5")
print(3.14*" 2.75")
print("-33"/"11")
print(-"-5")

View File

@@ -1,12 +0,0 @@
if 2 < 5 then
print("OK!")
else
print("Something is not right")
end
print(2 < 5)
print(2 <= 5)
print(2 == 5)
print(2 ~= 5)
print(2 > 5)
print(2 >= 5)

View File

@@ -1,8 +0,0 @@
#!/bin/bash
TESTS=`echo *.lua`
for x in $TESTS
do
echo compiling $x
luac -l -o ${x}c ${x}
lua ${x}c
done

View File

@@ -1,97 +0,0 @@
function printrunning()
if coroutine.running() == nil then
print("running is nil");
else
print("running is not nil")
end
end
function foo (a)
print("foo", a)
return coroutine.yield(2*a)
end
co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
printrunning()
print("co.status.inside",coroutine.status(co));
local co2 = coroutine.create(function()
print("co.status.inside2",coroutine.status(co));
end)
print("co.status.inside",coroutine.status(co));
coroutine.resume(co2);
return b, "end"
end)
function exercise()
printrunning()
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, 1, 10))
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, "r"))
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, "x", "y"))
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, "x", "y"))
print("co.status",coroutine.status(co));
end
exercise();
co = coroutine.create(function (a,b)
print("co-body", a, b)
-- TODO: make java and C behave the same for yielding in pcalls
-- local status,r = pcall( foo, a+1 )
foo(a+1)
print("co-body", status,r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)
exercise();
-- wrap test
local g = coroutine.wrap(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end )
print("g", g(1, 10))
print("g", g("r"))
print("g", g("x", "y"))
local s,e = pcall( g, "x", "y" )
print("g", string.match(e,'cannot resume dead coroutine') or 'badmessage: '..tostring(e))
-- varargs passing
local echo = function(msg,...)
print( msg, ...)
return ...
end
local echocr = function(...)
echo('(echocr) first args', unpack(arg,1,arg.n))
local a = arg
while true do
a = { echo( '(echoch) yield returns', coroutine.yield( unpack(a) ) ) }
end
end
local c = coroutine.create( echocr )
local step = function(...)
echo( '(main) resume returns',
coroutine.resume(c, echo('(main) sending args', ...)) )
end
step(111,222,333)
step()
step(111)
step(111,222,333)

View File

@@ -1,227 +0,0 @@
local print,tostring,_G,pcall,ipairs,isnumber = print,tostring,_G,pcall,ipairs,isnumber
local e,f,g,h,s
print( 'has debug', debug~=nil )
if not debug then error( 'no debug' ) end
print( '----- debug.getfenv, debug.setfenv' )
f = function(a)
return 'f:'..tostring(a)..'|'..tostring(b)
end
s,e,g = pcall( debug.getfenv, f )
print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
s,e,g = pcall( debug.setfenv, f, {b='def'} )
print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
s,e,g = pcall( debug.getfenv, f )
print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
print( '----- debug.getlocal, debug.setlocal' )
h = function(v,i,n)
s = 'h-'..v..'-'..i
local x1,y1 = debug.getlocal(v,i)
local x2,y2 = debug.setlocal(v,i,n)
local x3,y3 = debug.getlocal(v,i)
return s..' -> '..v..'-'..i..' '..
'get='..tostring(x1)..','..tostring(y1)..' '..
'set='..tostring(x2)..','..tostring(y2)..' '..
'get='..tostring(x3)..','..tostring(y3)..' '
end
g = function(...)
local p,q,r=7,8,9
local t = h(...)
local b = table.concat({...},',')
return t..'\tg locals='..p..','..q..','..r..' tbl={'..b..'}'
end
f = function(a,b,c)
local d,e,f = 4,5,6
local t = g(a,b,c)
return t..'\tf locals='..','..a..','..b..','..c..','..d..','..e..','..f
end
do lvl=1,1
for lcl=3,7 do
print( pcall( f, lvl, lcl, '#' ) )
end
end
do lvl=2,3
for lcl=0,7 do
print( pcall( f, lvl, lcl, '#' ) )
end
end
print( '----- debug.getupvalue, debug.setupvalue' )
local m,n,o = 101,102,103
f = function(p,q,r)
local p,q,r = 104,105,106
local g = function(s,t,u)
local v,w,x = 107,108,109
return function()
return m,n,o,p,q,r,v,w,x
end
end
return g
end
g = f()
h = g()
local callh = function()
local t = {}
for i,v in ipairs( { pcall(h) } ) do
t[i] = tostring(v)
end
return table.concat(t,',')
end
print( 'h', h() )
local funs = { f, g, h }
local names = { 'f', 'g', 'h' }
for i=1,3 do
local fun,name = funs[i],names[i]
for index=0,10 do
local s1,x1,y1 = pcall( debug.getupvalue, fun, index )
local s2,x2,y2 = pcall( debug.setupvalue, fun, index, 666000+i*111000+index )
local s3,x3,y3 = pcall( debug.getupvalue, fun, index )
print( name..' -> '..i..'-'..index..' '..
'get='..tostring(s1)..','..tostring(x1)..','..tostring(y1)..' '..
'set='..tostring(s2)..','..tostring(x2)..','..tostring(y2)..' '..
'get='..tostring(s3)..','..tostring(x3)..','..tostring(y3)..' '..
'tbl='..callh() )
end
end
print( '----- debug.setmetatable, debug.getmetatable' )
local a = {a='bbb'}
local b = {}
local mt = {__index={b='ccc'}}
print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b))
local s1,x1,y1 = pcall( debug.getmetatable, a )
local s2,x2,y2 = pcall( debug.setmetatable, a, mt )
print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b))
local s3,x3,y3 = pcall( debug.getmetatable, a )
local s4,x4,y4 = pcall( debug.getmetatable, b )
local s5,x5,y5 = pcall( debug.setmetatable, a, nil )
print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b))
local s6,x6,y6 = pcall( debug.getmetatable, a )
if not s1 then print( 's1 error', x1 ) end
if not s2 then print( 's2 error', x2 ) end
if not s3 then print( 's3 error', x3 ) end
if not s4 then print( 's4 error', x4 ) end
if not s5 then print( 's5 error', x5 ) end
if not s6 then print( 's6 error', x6 ) end
print( 'get='..tostring(s1)..','..tostring(x1==nil)..','..tostring(y1) )
print( 'set='..tostring(s2)..','..tostring(x2==a)..','..tostring(y2) )
print( 'get='..tostring(s3)..','..tostring(x3==mt)..','..tostring(y3) )
print( 'get='..tostring(s4)..','..tostring(x4==nil)..','..tostring(y4) )
print( 'set='..tostring(s5)..','..tostring(x5==a)..','..tostring(y5) )
print( 'get='..tostring(s6)..','..tostring(x6==nil)..','..tostring(y6) )
print( pcall( debug.getmetatable, 1 ) )
-- print( pcall( debug.setmetatable, 1, {} ) )
-- print( pcall( debug.setmetatable, 1, nil ) )
print( '----- debug.getinfo' )
local printfield = function(tbl, field)
local x = tbl[field]
if x == nil then return end
local typ = type(x)
if typ=='table' then
x = '{'..table.concat(x,',')..'}'
elseif typ=='function' then
x = typ
end
print( ' '..field..': '..tostring(x) )
end
local fields = { 'source', 'short_src', 'what',
'currentline', 'linedefined', 'lastlinedefined',
'nups', 'func', 'activelines' }
local printinfo = function(...)
for i,a in ipairs(arg) do
if type(a) == 'table' then
for j,field in ipairs(fields) do
printfield( a, field)
end
else
print( tostring(a) )
end
end
end
function test()
local x = 5
function f()
x = x + 1
return x
end
function g()
x = x - 1
print( '---' )
printinfo( 'debug.getinfo(1)', debug.getinfo(1) )
printinfo( 'debug.getinfo(1,"")', debug.getinfo(1, "") )
printinfo( 'debug.getinfo(1,"l")', debug.getinfo(1, "l") )
printinfo( 'debug.getinfo(1,"fL")', debug.getinfo(1, "fL") )
printinfo( 'debug.getinfo(2)', debug.getinfo(2) )
printinfo( 'debug.getinfo(2,"l")', debug.getinfo(2, "l") )
printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") )
printinfo( 'debug.getinfo(10,"")', pcall( debug.getinfo, 10, "" ) )
printinfo( 'debug.getinfo(-10,"")', pcall( debug.getinfo, -10, "" ) )
--[[
for i=1,3 do
printinfo( 'debug.traceback("msg")', debug.traceback('msg') )
printinfo( 'debug.traceback("another",'..i..')', debug.traceback('another',i) )
end
--]]
print( '---' )
return x
end
print(f())
print(g())
return f, g
end
local options = "nSlufL"
local e,f,g = pcall( test )
print( 'e,f,g', e, type(f), type(g) )
printinfo( 'debug.getinfo(f)', pcall(debug.getinfo, f) )
printinfo( 'debug.getinfo(f,"'..options..'")', pcall(debug.getinfo, f, options) )
for j=1,6 do
local opts = options:sub(j,j)
printinfo( 'debug.getinfo(f,"'..opts..'")', pcall(debug.getinfo, f, opts) )
end
printinfo( 'debug.getinfo(g)', pcall(debug.getinfo, g) )
printinfo( 'debug.getinfo(test)', pcall(debug.getinfo, test) )
print( '----- debug.sethook, debug.gethook' )
f = function(x)
g = function(y)
return math.min(x,h)
end
local a = g(x)
return a + a
end
local hook = function(...)
print( ' ... in hook', ... )
end
local tryfunc = function(hook,mask,func,arg)
local x,f,h,m
pcall( function()
debug.sethook(hook,mask)
x = func(arg)
f,h,m = debug.gethook()
end )
debug.sethook()
return x,f,h,m
end
local tryhooks = function(mask)
local s1,a1,b1,c1,d1 = pcall( tryfunc, hook, mask, f, 333 )
print( 'hook = '..mask..' -> '..
'result='..tostring(s1)..','..tostring(a1)..','..
type(b1)..','..type(c1)..','..
tostring(b1==f)..','..tostring(c1==hook)..','..
tostring(d1)..' ' )
end
--[[
tryhooks("c")
tryhooks("r")
tryhooks("l")
tryhooks("crl")
--]]

View File

@@ -1,121 +0,0 @@
-- object ids
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- test of common types of errors
local function c(f,...) return f(...) end
local function b(...) return c(...) end
local function a(...) return (pcall(b,...)) end
s = 'some string'
local t = {}
-- error message tests
print( 'a(error)', a(error) )
print( 'a(error,"msg")', a(error,"msg") )
print( 'a(error,"msg",0)', a(error,"msg",0) )
print( 'a(error,"msg",1)', a(error,"msg",1) )
print( 'a(error,"msg",2)', a(error,"msg",2) )
print( 'a(error,"msg",3)', a(error,"msg",3) )
print( 'a(error,"msg",4)', a(error,"msg",4) )
print( 'a(error,"msg",5)', a(error,"msg",5) )
print( 'a(error,"msg",6)', a(error,"msg",6) )
-- call errors
print( 'a(nil())', a(function() return n() end) )
print( 'a(t()) ', a(function() return t() end) )
print( 'a(s()) ', a(function() return s() end) )
print( 'a(true())', a(function() local b = true; return b() end) )
-- arithmetic errors
print( 'a(nil+1)', a(function() return nil+1 end) )
print( 'a(a+1) ', a(function() return a+1 end) )
print( 'a(s+1) ', a(function() return s+1 end) )
print( 'a(true+1)', a(function() local b = true; return b+1 end) )
-- table errors
print( 'a(nil.x)', a(function() return n.x end) )
print( 'a(a.x) ', a(function() return a.x end) )
print( 'a(s.x) ', a(function() return s.x end) )
print( 'a(true.x)', a(function() local b = true; return b.x end) )
print( 'a(nil.x=5)', a(function() n.x=5 end) )
print( 'a(a.x=5) ', a(function() a.x=5 end) )
print( 'a(s.x=5) ', a(function() s.x=5 end) )
print( 'a(true.x=5)', a(function() local b = true; b.x=5 end) )
-- len operator
print( 'a(#nil) ', a(function() return #n end) )
print( 'a(#t) ', a(function() return #t end) )
print( 'a(#s) ', a(function() return #s end) )
print( 'a(#a) ', a(function() return #a end) )
print( 'a(#true)', a(function() local b = true; return #b end) )
-- comparison errors
print( 'a(nil>1)', a(function() return nil>1 end) )
print( 'a(a>1) ', a(function() return a>1 end) )
print( 'a(s>1) ', a(function() return s>1 end) )
print( 'a(true>1)', a(function() local b = true; return b>1 end) )
-- unary minus errors
print( 'a(-nil)', a(function() return -n end) )
print( 'a(-a) ', a(function() return -a end) )
print( 'a(-s) ', a(function() return -s end) )
print( 'a(-true)', a(function() local b = true; return -b end) )
-- string concatenation
local function concatsuite(comparefunc)
print( '"a".."b"', comparefunc("a","b") )
print( '"a"..nil', comparefunc("a",nil) )
print( 'nil.."b"', comparefunc(nil,"b") )
print( '"a"..{}', comparefunc("a",{}) )
print( '{}.."b"', comparefunc({},"b") )
print( '"a"..2', comparefunc("a",2) )
print( '2.."b"', comparefunc(2,"b") )
print( '"a"..print', comparefunc("a",print) )
print( 'print.."b"', comparefunc(print,"b") )
print( '"a"..true', comparefunc("a",true) )
print( 'true.."b"', comparefunc(true,"b") )
print( 'nil..true', comparefunc(nil,true) )
print( '"a"..3.5', comparefunc("a",3.5) )
print( '3.5.."b"', comparefunc(3.5,"b") )
end
local function strconcat(a,b)
return (pcall( function() return a..b end) )
end
local function tblconcat(a,b)
local t={a,b}
return (pcall( function() return table.concat(t,'-') end ))
end
-- concatsuite(strconcat)
concatsuite(tblconcat)
-- pairs
print( 'a(pairs(nil))', a(function() return id(pairs(nil,{})) end) )
print( 'a(pairs(a)) ', a(function() return id(pairs(a,{})) end) )
print( 'a(pairs(s)) ', a(function() return id(pairs(s,{})) end) )
print( 'a(pairs(t)) ', a(function() return id(pairs(t,{})) end) )
print( 'a(pairs(true))', a(function() local b = true; return id(pairs(b,{})) end) )
-- setmetatable
function sm(...)
return id(setmetatable(...))
end
print( 'a(setmetatable(nil))', a(function() return sm(nil,{}) end) )
print( 'a(setmetatable(a)) ', a(function() return sm(a,{}) end) )
print( 'a(setmetatable(s)) ', a(function() return sm(s,{}) end) )
print( 'a(setmetatable(true))', a(function() local b = true; return sm(b,{}) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable={}}) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
t = {}
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable='some string'}) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(setmetatable(t,nil)) ', a(function() return sm(t,nil) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t) end) )
print( 'a(setmetatable({},"abc")) ', a(function() return sm({},'abc') end) )
-- bad args to error!
print( 'error("msg","arg")', a(function() error('some message', 'some bad arg') end) )
-- loadfile, dofile on missing files
print( 'loadfile("bogus.txt")', a(function() return loadfile("bogus.txt") end) )
print( 'dofile("bogus.txt")', a(function() return dofile("bogus.txt") end) )

View File

@@ -1,43 +0,0 @@
-- test tables with more than 50 elements
local t = { 1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
}
print ("#t=",#t,'t[1,50,51,59]', t[1], t[50], t[51], t[59])
print (table.concat(t,','))
local t2= { 0,3,4,7,9,8,12,15,23,5,
10,13,14,17,19,18,112,115,123,15,
20,33,24,27,29,28,212,215,223,25,
40,43,44,47,49,48,412,415,423,45,
50,53,54,57,59,58,512,515,523,55,
60,63,64,67,69,68,612,615,623,65,
70,73,74,77,79,78,72,715,723,75,
}
print ("#t2=",#t2,'t[1,50,51,59]', t[1], t[50], t[51], t[59])
print (table.concat(t2,','))
local t = {
[2000]='a', [2001]='b', [2002]='c', [2003]='d', [2004]='e', [2005]='f', [2006]='g', [2007]='h', [2008]='i', [2009]='j',
[3000]='a', [3001]='b', [3002]='c', [3003]='d', [3004]='e', [3005]='f', [3006]='g', [3007]='h', [3008]='i', [3009]='j',
[4000]='a', [4001]='b', [4002]='c', [4003]='d', [4004]='e', [4005]='f', [4006]='g', [4007]='h', [4008]='i', [4009]='j',
[5000]='a', [5001]='b', [5002]='c', [5003]='d', [5004]='e', [5005]='f', [5006]='g', [5007]='h', [5008]='i', [5009]='j',
[6000]='a', [6001]='b', [6002]='c', [6003]='d', [6004]='e', [6005]='f', [6006]='g', [6007]='h', [6008]='i', [6009]='j',
[7000]='a', [7001]='b', [7002]='c', [7003]='d', [7004]='e', [7005]='f', [7006]='g', [7007]='h', [7008]='i', [7009]='j',
[8000]='a', [8001]='b', [8002]='c', [8003]='d', [8004]='e', [8005]='f', [8006]='g', [8007]='h', [8008]='i', [8009]='j',
}
for i=2000,8000,1000 do
for j=0,9,1 do
print( 't['..tostring(i+j)..']', t[i+j] )
end
end

View File

@@ -1,36 +0,0 @@
-- utility to give tables and functions uniform ids for testing
ids = {}
-- return unique id for the value, independent of object id
function id(obj)
if not obj or type(obj) == 'number' or type(obj) == 'string' or type(obj) == 'boolean' then
return obj
end
local v = ids[obj]
if v then
return v
end
table.insert(ids,obj)
ids[obj] = type(obj)..'.'..tostring(#ids)
return ids[obj]
end
-- return key-value pairs sorted by keys
function spairs(unsorted)
local keys = {}
for k,v in pairs(unsorted) do
table.insert(keys,k)
end
table.sort(keys)
local lookup = {}
for i,k in ipairs(keys) do
lookup[k] = i;
end
local iterator = function(tbl,key)
local i = lookup[key]
local j,k = next(keys,i)
if not j then return nil end
return k,unsorted[k]
end
return iterator, table, nil
end

View File

@@ -1,115 +0,0 @@
-- simple io-library tests
print( io ~= nil )
print( io.open ~= nil )
print( io.stdin ~= nil )
print( io.stdout ~= nil )
print( io.stderr ~= nil )
print( 'write', io.write() )
print( 'write', io.write("This") )
print( 'write', io.write(" is a pen.\n") )
print( 'flush', io.flush() )
local f = io.open("abc.txt","w")
print( 'f', type(f) )
print( io.type(f) )
print( 'write', f:write("abcdef 12345 \t\r\n\t 678910 more\naaaaaa\rbbb\nthe rest") )
print( 'type(f)', io.type(f) )
print( 'close', f:close() )
print( 'type(f)', io.type(f) )
print( 'type("f")', io.type("f") )
local g = io.open("abc.txt","r")
local t = { g:read(3, 3, "*n", "*n", "*l", "*l", "*a") }
for i,v in ipairs(t) do
print( string.format("%q",tostring(v)), type(v))
end
local h,s = io.open("abc.txt", "a")
print( 'h', io.type(h), s )
print( 'write', h:write('\nmore text\neven more text\n') )
print( 'close', h:close() )
local j = io.open( "abc.txt", "r" )
print( 'j', io.type(j) )
print( 'seek', j:seek("set", 3) )
print( 'read', j:read(4), j:read(3) )
print( 'seek', j:seek("set", 2) )
print( 'read', j:read(4), j:read(3) )
print( 'seek', j:seek("cur", -8 ) )
print( 'read', j:read(4), j:read(3) )
print( 'seek(cur,0)', j:seek("cur",0) )
print( 'seek(cur,20)', j:seek("cur",20) )
print( 'seek(end,-5)', j:seek("end", -5) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
for l in io.lines("abc.txt") do
print( string.format('%q',l) )
end
io.input("abc.txt")
for l in io.lines() do
print( string.format('%q',l) )
end
io.input(io.open("abc.txt","r"))
for l in io.lines() do
print( string.format('%q',l) )
end
io.input("abc.txt")
io.input(io.input())
for l in io.lines() do
print( string.format('%q',l) )
end
local count = 0
io.tmpfile = function()
count = count + 1
return io.open("tmp"..count..".out","w")
end
local a = io.tmpfile()
local b = io.tmpfile()
print( io.type(a) )
print( io.type(b) )
print( "a:write", a:write('aaaaaaa') )
print( "b:write", b:write('bbbbbbb') )
print( "a:setvbuf", a:setvbuf("no") )
print( "a:setvbuf", a:setvbuf("full",1024) )
print( "a:setvbuf", a:setvbuf("line") )
print( "a:write", a:write('ccccc') )
print( "b:write", b:write('ddddd') )
print( "a:flush", a:flush() )
print( "b:flush", b:flush() )
--[[
print( "a:read", a:read(7) )
print( "b:read", b:read(7) )
print( "a:seek", a:seek("cur",-4) )
print( "b:seek", b:seek("cur",-4) )
print( "a:write", a:read(7) )
print( "b:write", b:read(7) )
--]]
local pcall = function(...) return ( pcall(...) )end
print( 'a:close', pcall( a.close, a ) )
print( 'a:write', pcall( a.write, a, 'eee') )
print( 'a:flush', pcall( a.flush, a) )
print( 'a:read', pcall( a.read, a, 5) )
print( 'a:lines', pcall( a.lines, a) )
print( 'a:seek', pcall( a.seek, a, "cur", -2) )
print( 'a:setvbuf', pcall( a.setvbuf, a, "no") )
print( 'a:close', pcall( a.close, a ) )
print( 'io.type(a)', pcall( io.type, a ) )
print( 'io.close()', pcall( io.close ) )
print( 'io.close(io.output())', pcall( io.close, io.output() ) )
io.output('abc.txt')
print( 'io.close()', pcall( io.close ) )
print( 'io.write', pcall( io.write, 'eee') )
print( 'io.flush', pcall( io.flush) )
print( 'io.close', pcall( io.close ) )
io.input('abc.txt'):close()
print( 'io.read', pcall( io.read, 5) )
print( 'io.lines', pcall( io.lines) )

View File

@@ -1,22 +0,0 @@
-- This script tests the "generic" for loop with a script iterator.
local function stuff()
local function i(o)
if o.counter > 3 then
return nil
else
local v = o.counter
o.counter = v + 1
return v
end
end
return i, { counter=1 }
end
local function testfor()
for x in stuff() do
print(x)
end
end
testfor()

View File

@@ -1,31 +0,0 @@
-- test program with more than 50 non-sequential integer elements
local t0000='a'; local t0001='b'; local t0002='c'; local t0003='d'; local t0004='e'; local t0005='f'; local t0006='g'; local t0007='h'; local t0008='i'; local t0009='j';
local t1000='a'; local t1001='b'; local t1002='c'; local t1003='d'; local t1004='e'; local t1005='f'; local t1006='g'; local t1007='h'; local t1008='i'; local t1009='j';
local t2000='a'; local t2001='b'; local t2002='c'; local t2003='d'; local t2004='e'; local t2005='f'; local t2006='g'; local t2007='h'; local t2008='i'; local t2009='j';
local t3000='a'; local t3001='b'; local t3002='c'; local t3003='d'; local t3004='e'; local t3005='f'; local t3006='g'; local t3007='h'; local t3008='i'; local t3009='j';
local t4000='a'; local t4001='b'; local t4002='c'; local t4003='d'; local t4004='e'; local t4005='f'; local t4006='g'; local t4007='h'; local t4008='i'; local t4009='j';
local t5000='a'; local t5001='b'; local t5002='c'; local t5003='d'; local t5004='e'; local t5005='f'; local t5006='g'; local t5007='h'; local t5008='i'; local t5009='j';
local t6000='a'; local t6001='b'; local t6002='c'; local t6003='d'; local t6004='e'; local t6005='f'; local t6006='g'; local t6007='h'; local t6008='i'; local t6009='j';
local t7000='a'; local t7001='b'; local t7002='c'; local t7003='d'; local t7004='e'; local t7005='f'; local t7006='g'; local t7007='h'; local t7008='i'; local t7009='j';
local t8000='a'; local t8001='b'; local t8002='c'; local t8003='d'; local t8004='e'; local t8005='f'; local t8006='g'; local t8007='h'; local t8008='i'; local t8009='j';
local t9000='a'; local t9001='b'; local t9002='c'; local t9003='d'; local t9004='e'; local t9005='f'; local t9006='g'; local t9007='h'; local t9008='i'; local t9009='j';
local t10000='a'; local t10001='b'; local t10002='c'; local t10003='d'; local t10004='e'; local t10005='f'; local t10006='g'; local t10007='h'; local t10008='i'; local t10009='j';
local t11000='a'; local t11001='b'; local t11002='c'; local t11003='d'; local t11004='e'; local t11005='f'; local t11006='g'; local t11007='h'; local t11008='i'; local t11009='j';
local t12000='a'; local t12001='b'; local t12002='c'; local t12003='d'; local t12004='e'; local t12005='f'; local t12006='g'; local t12007='h'; local t12008='i'; local t12009='j';
local t13000='a'; local t13001='b'; local t13002='c'; local t13003='d'; local t13004='e'; local t13005='f'; local t13006='g'; local t13007='h'; local t13008='i'; local t13009='j';
-- print the variables
print(t0000,'a'); print(t0001,'b'); print(t0002,'c'); print(t0003,'d'); print(t0004,'e'); print(t0005,'f'); print(t0006,'g'); print(t0007,'h'); print(t0008,'i'); print(t0009,'j');
print(t1000,'a'); print(t1001,'b'); print(t1002,'c'); print(t1003,'d'); print(t1004,'e'); print(t1005,'f'); print(t1006,'g'); print(t1007,'h'); print(t1008,'i'); print(t1009,'j');
print(t2000,'a'); print(t2001,'b'); print(t2002,'c'); print(t2003,'d'); print(t2004,'e'); print(t2005,'f'); print(t2006,'g'); print(t2007,'h'); print(t2008,'i'); print(t2009,'j');
print(t3000,'a'); print(t3001,'b'); print(t3002,'c'); print(t3003,'d'); print(t3004,'e'); print(t3005,'f'); print(t3006,'g'); print(t3007,'h'); print(t3008,'i'); print(t3009,'j');
print(t4000,'a'); print(t4001,'b'); print(t4002,'c'); print(t4003,'d'); print(t4004,'e'); print(t4005,'f'); print(t4006,'g'); print(t4007,'h'); print(t4008,'i'); print(t4009,'j');
print(t5000,'a'); print(t5001,'b'); print(t5002,'c'); print(t5003,'d'); print(t5004,'e'); print(t5005,'f'); print(t5006,'g'); print(t5007,'h'); print(t5008,'i'); print(t5009,'j');
print(t6000,'a'); print(t6001,'b'); print(t6002,'c'); print(t6003,'d'); print(t6004,'e'); print(t6005,'f'); print(t6006,'g'); print(t6007,'h'); print(t6008,'i'); print(t6009,'j');
print(t7000,'a'); print(t7001,'b'); print(t7002,'c'); print(t7003,'d'); print(t7004,'e'); print(t7005,'f'); print(t7006,'g'); print(t7007,'h'); print(t7008,'i'); print(t7009,'j');
print(t8000,'a'); print(t8001,'b'); print(t8002,'c'); print(t8003,'d'); print(t8004,'e'); print(t8005,'f'); print(t8006,'g'); print(t8007,'h'); print(t8008,'i'); print(t8009,'j');
print(t9000,'a'); print(t9001,'b'); print(t9002,'c'); print(t9003,'d'); print(t9004,'e'); print(t9005,'f'); print(t9006,'g'); print(t9007,'h'); print(t9008,'i'); print(t9009,'j');
print(t10000,'a'); print(t10001,'b'); print(t10002,'c'); print(t10003,'d'); print(t10004,'e'); print(t10005,'f'); print(t10006,'g'); print(t10007,'h'); print(t10008,'i'); print(t10009,'j');
print(t11000,'a'); print(t11001,'b'); print(t11002,'c'); print(t11003,'d'); print(t11004,'e'); print(t11005,'f'); print(t11006,'g'); print(t11007,'h'); print(t11008,'i'); print(t11009,'j');
print(t12000,'a'); print(t12001,'b'); print(t12002,'c'); print(t12003,'d'); print(t12004,'e'); print(t12005,'f'); print(t12006,'g'); print(t12007,'h'); print(t12008,'i'); print(t12009,'j');
print(t13000,'a'); print(t13001,'b'); print(t13002,'c'); print(t13003,'d'); print(t13004,'e'); print(t13005,'f'); print(t13006,'g'); print(t13007,'h'); print(t13008,'i'); print(t13009,'j');

View File

@@ -1,7 +0,0 @@
local mathClass = luajava.bindClass("java.lang.Math")
local function sqrt(x)
return mathClass:sqrt(x)
end
return { sqrt = sqrt; pi = mathClass.PI }

View File

@@ -1,87 +0,0 @@
print( math.sin( 0.0 ) )
print( math.cos( math.pi ) )
print( math.sqrt( 9.0 ) )
print( math.modf( 5.25 ) )
local aliases = {
['0']='<zero>',
['-0']='<zero>',
['nan']='<nan>',
['inf']='<pos-inf>',
['-inf']='<neg-inf>',
['1.#INF']='<pos-inf>',
['-1.#INF']='<neg-inf>',
['1.#IND']='<nan>',
['-1.#IND']='<nan>',
}
local function normalized(x)
local s = tostring(x)
return aliases[s] or s
end
-- binary ops
function binops( a, b )
local sa = tostring(a)
local sb = tostring(b)
print( sa..'+'..sb..'='..normalized(a+b) )
print( sa..'-'..sb..'='..normalized(a-b) )
print( sa..'*'..sb..'='..normalized(a*b) )
print( sa..'^'..sb..'='..normalized(a^b) )
print( sa..'/'..sb..'='..normalized(a/b) )
print( sa..'%'..sb..'='..normalized(a%b) )
return '--'
end
print( pcall( binops, 2, 0 ) )
print( pcall( binops, 2.5, 0 ) )
print( pcall( binops, -2.5, 0 ) )
print( pcall( binops, 2, 1 ) )
print( pcall( binops, 5, 2 ) )
print( pcall( binops, -5, 2 ) )
print( pcall( binops, 16, -2 ) )
print( pcall( binops, -16, -2 ) )
print( pcall( binops, 256, 0.5 ) )
print( pcall( binops, 256, 0.25 ) )
print( pcall( binops, 256, 0.625 ) )
print( pcall( binops, 256, -0.5 ) )
print( pcall( binops, 256, -0.25 ) )
print( pcall( binops, 256, -0.625 ) )
print( pcall( binops, -256, 0.5 ) )
print( pcall( binops, 0.5, 0 ) )
print( pcall( binops, 0.5, 1 ) )
print( pcall( binops, 0.5, 2 ) )
print( pcall( binops, 0.5, -1 ) )
print( pcall( binops, 0.5, -2 ) )
print( pcall( binops, 2.25, 0 ) )
print( pcall( binops, 2.25, 2 ) )
print( pcall( binops, 2.25, 0.5 ) )
print( pcall( binops, 2.25, 2.5 ) )
print( pcall( binops, -2, 0 ) )
-- random tests
print("Random tests")
local function testrandom(string,lo,hi)
local c,e = loadstring('return '..string)
for i=1,5 do
local s,e = pcall(c)
print( string, s and type(e) or e, (e>=lo) and (e<=hi) )
end
end
testrandom('math.random()',0,1)
testrandom('math.random(5,10)',5,10)
testrandom('math.random(30)',0,30)
testrandom('math.random(-4,-2)',-4,-2)
local t = {}
print( math.randomseed(20) )
for i=1,20 do
t[i] = math.random()
end
print( '-- comparing new numbers')
for i=1,20 do
print( t[i] == math.random(), t[i] == t[0] )
end
print( '-- resetting seed')
print( math.randomseed(20) )
for i=1,20 do
print( t[i] == math.random() )
end

View File

@@ -1,48 +0,0 @@
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- The purpose of this test case is to demonstrate that
-- basic metatable operations on non-table types work.
-- i.e. that s.sub(s,...) could be used in place of string.sub(s,...)
local s = "hello"
print(s:sub(2,4))
local t = {}
function op(name,...)
local a,b = pcall( setmetatable, t, ... )
print( name, id(t), id(getmetatable(t)), id(a), a and id(b) or type(b) )
end
op('set{} ',{})
op('set-nil',nil)
op('set{} ',{})
op('set')
op('set{} ',{})
op('set{} ',{})
op('set{}{}',{},{})
op('set-nil',nil)
op('set{__}',{__metatable={}})
op('set{} ',{})
op('set-nil',nil)
t = {}
op('set{} ',{})
op('set-nil',nil)
op('set{__}',{__metatable='abc'})
op('set{} ',{})
op('set-nil',nil)
local i = 1234
local t = setmetatable( {}, {
__mode="v",
__index=function(t,k)
local v = i
i = i + 1
rawset(t,k,v)
return v
end,
} )
local l = { 'a', 'b', 'a', 'b', 'c', 'a', 'b', 'c', 'd' }
for i,key in ipairs(l) do
print( 't.'..key, t[key] )
end

View File

@@ -1,90 +0,0 @@
-- unit tests for module() function
local ids = {}
local function id(obj)
if not obj or type(obj) == 'number' or type(obj) == 'string' then
return obj
end
local v = ids[obj]
if v then
return v
end
table.insert(ids,obj)
ids[obj] = type(obj)..'.'..tostring(#ids)
return ids[obj]
end
-- module tests
local pr = print
local pkg = package
local g = _G
local md = module
local rq = require
local sa = package.seeall
local gfe = getfenv
local gmt = getmetatable
local function envs()
return id(gfe(0)), id(gfe(1)), id(gfe(2)),
id(gmt(gfe(0))), id(gmt(gfe(1))), id(gmt(gfe(2)))
end
local function trymodule(name)
pr( '_G['..name..']', id(g[name]) )
pr( 'pkg.loaded['..name..']', id(pkg.loaded[name]) )
pr( 'envs', envs() )
md(name)
pr( 'envs', envs() )
pr( 'status,result', status, result )
pr( '_G['..name..']', id(g[name]) )
local t = pkg.loaded[name]
pr( 't=pkg.loaded['..name..']', id(t) )
pr( 't._M, t._NAME, t._PACKAGE', id(t._M), id(t._NAME), id(t._PACKAGE) )
pr( 'rq('..name..')', id( rq(name) ) )
pr( 'print', id(print) )
pr( 'seeall(t)', sa(t) )
pr( 'print, _G['..name..']', id(print), id(g[name]) )
end
trymodule('abc.def.ghi')
trymodule('abc.def.ghi')
trymodule('abc.def')
trymodule('abc.def.lmn')
trymodule('abc.def')
trymodule('abc')
package.loaded['opq.rst'] = {}
trymodule('opq.rst')
trymodule('opq.rst')
uvw = { xyz="x1y1z1" }
--print( "uvw", id(uvw) )
--print( "uvw.xyz", id(uvw.xyz) )
--print( "uvw.abc", id(uvw.abc) )
print( pcall( trymodule, 'uvw.xyz' ) )
print( pcall( trymodule, 'uvw' ) )
print( pcall( trymodule, 'uvw.abc' ) )
print( "uvw", id(uvw) )
print( "uvw.xyz", id(uvw.xyz) )
print( "uvw.abc", id(uvw.abc) )
function f()
module( 'fff', package.seeall )
a = 'aaa'
print( a )
end
f()
f()
print( a )
print( getfenv(f)['a'] )
print( a )
-- do metatables work with package.loaded and require?
print( 'setting metatable for package.loaded' )
print( 'package.loaded.mypreload', package.loaded.mypreload )
print( 'setmetatable')
pcall( setmetatable, package.loaded, { __index={mypreload=12345}})
print( 'package.loaded.mypreload', package.loaded.mypreload )
print( "require, 'mypreload'", pcall( require, 'mypreload' ) )
print( 'package.loaded.mypreload', package.loaded.mypreload )
print( 'resetting metatable for package.loaded' )
print( 'setmetatable')
pcall( setmetatable, package.loaded, nil )
print( "require, 'mypreload'", (pcall( require, 'mypreload' )) )
print( 'package.loaded.mypreload', package.loaded.mypreload )

View File

@@ -1,37 +0,0 @@
-- call with arg 'true' to turn on error messages
local messages = select(1,...)
function mpcall(...)
if messages then return pcall(...)
else return (pcall(...)) end
end
-- unit tests for the next() function
function checkvalues(tag, tbl)
local values = {}
local index,value = next(tbl,nil)
while index do
table.insert( values, tostring(index).."="..tostring(value) )
index,value = next(tbl,index)
end
table.sort( values )
print( tag, "values: {"..table.concat(values,",").."}" )
end
function donexts(tag,tbl,count)
checkvalues(tag,tbl)
print( tag, '--- -1', 'pcall( next, tbl,-1 )', mpcall( next, tbl,-1 ) )
print( tag, '--- 0', 'pcall( next, tbl,0 )', mpcall( next, tbl,0 ) )
print( tag, '---"a"', 'pcall( next, tbl,"a" )', mpcall( next, tbl,"a" ) )
print( tag, '--- 10', 'pcall( next, tbl, 10 )', mpcall( next, tbl, 10 ) )
end
donexts( 'next1', {}, 2 )
donexts( 'next2', {'one', 'two', 'three' }, 5 )
donexts( 'next3', { aa='aaa', bb='bbb', cc='ccc', [20]='20', [30]='30'}, 7 )
donexts( 'next4', {'one', 'two', 'three', aa='aaa', bb='bbb', cc='ccc', [20]='20', [30]='30'}, 9 )
donexts( 'next5', {'one', 'two', 'three', [-1]='minus-one', [0]='zero' }, 7 )
print( 'pcall(next)', mpcall(next) )
print( 'pcall(next,nil)', mpcall(next,nil) )
print( 'pcall(next,"a")', mpcall(next,"a") )
print( 'pcall(next,1)', mpcall(next,1) )

View File

@@ -1,36 +0,0 @@
-- simple os-library tests
-- these can't really be compared to C meaningfully,
-- because they are so highly os-dependent.
local lib = "org.luaj.lib.j2se.J2seOsLib"
-- local lib = "org.luaj.lib.OsLib"
print( 'require "'..lib..'"', pcall( require, lib ) )
print( 'os', os ~= nil )
print( 'os.clock()', pcall( os.clock ) )
print( 'os.date()', pcall( os.date ) )
print( 'os.difftime(123000, 21250)', pcall( os.difftime, 123000, 21250 ) )
print( 'os.execute("hostname")', pcall( os.execute, 'hostname' ) )
print( 'os.execute("")', pcall( os.execute, '' ) )
print( 'os.getenv()', pcall( os.getenv ) )
print( 'os.getenv("bogus.key")', pcall( os.getenv, 'bogus.key' ) )
print( 'os.getenv("java.runtime.version")', pcall( os.getenv, 'java.runtime.version' ) )
local s,p = pcall( os.tmpname )
local s,q = pcall( os.tmpname )
print( 'os.tmpname()', s, p )
print( 'os.tmpname()', s, q )
print( 'os.remove(p)', pcall( os.remove, p ) )
print( 'os.rename(p,q)', pcall( os.rename, p, q ) )
local s,f = pcall( io.open, p,"w" )
print( 'io.open', s, f )
print( 'write', pcall( f.write, f, "abcdef 12345" ) )
print( 'close', pcall( f.close, f ) )
print( 'os.rename(p,q)', pcall( os.rename, p, q ) )
print( 'os.remove(q)', pcall( os.remove, q ) )
print( 'os.remove(q)', pcall( os.remove, q ) )
print( 'os.setlocale()', pcall( os.setlocale ) )
print( 'os.setlocale("jp")', pcall( os.setlocale, "jp" ) )
print( 'os.setlocale("us","monetary")', pcall( os.setlocale, "us", "monetary" ) )
print( 'os.setlocale(nil,"all")', pcall( os.setlocale, nil, "all" ) )
print( 'os.setlocale("c")', pcall( os.setlocale, "c" ) )
print( 'os.exit(123)' )
-- print( pcall( os.exit, -123 ) )
print( 'failed to exit' )

View File

@@ -1,75 +0,0 @@
-- sample lua function that returns values in reverse order
local function lc(a,b,c)
return c,b,a
end
-- sample lua function that throws a lua error
local function le(a,b,c)
error( 'sample error', 0 )
end
-- function that does a plain call to the underlying function
local function cp(f,a,b,c)
global = f(a,b,c)
return global
end
-- function that does a tail call to the underlying function
local function ct(f,a,b,c)
return f(a,b,c)
end
-- wrap pcall to be more useful in testing
local pc = pcall
local pcall = function(...)
local s,c = pc(...)
return s, type(c)
end
-- lua calls
print( 'lc(22,33,44)', lc(22,33,44) )
print( 'pcall(lc,22,33,44)', pcall(lc,22,33,44) )
print( 'pcall(le,22,33,44)', pcall(le,22,33,44) )
print( 'cp(lc,22,33,44)', cp(lc,22,33,44) )
print( 'pcall(cp,lc,22,33,44)', pcall(cp,lc,22,33,44) )
print( 'pcall(cp,le,22,33,44)', pcall(cp,le,22,33,44) )
print( 'ct(lc,22,33,44)', ct(lc,22,33,44) )
print( 'pcall(ct,lc,22,33,44)', pcall(ct,lc,22,33,44) )
print( 'pcall(ct,le,22,33,44)', pcall(ct,le,22,33,44) )
print( "assert(true,'a','b','c')", assert( true, 'a', 'b', 'c' ) )
print( "pcall(assert,true,'a','b','c')", pcall(assert, true, 'a', 'b', 'c' ) )
print( "pcall(assert,false,'a','b','c')", pcall(assert, false, 'a', 'b', 'c' ) )
-- more error, pcall tests
print( 'pcall(error)', pcall(error) )
print( 'pcall(error,"msg")', pcall(error,"msg") )
print( 'pcall(error,"msg",1)', pcall(error,"msg",1) )
print( 'pcall(error,"msg",2)', pcall(error,"msg",2) )
local function le(level)
error("msg",level)
end
function ge(level)
error("msg",level)
end
for i = 0,4 do
print( 'pcall(le,i)', i, pcall(le,i) )
print( 'pcall(ge,i)', i, pcall(ge,i) )
end
-- xpcall tests
local function goodfunction() return 'from good function' end
local function badfunction() error( 'from bad function') end
local function goodhandler(msg) return '-->'..msg..'<--' end
local function badhandler(msg) error( 'from bad handler' ) end
print( 'xpcall(error,goodhandler)', ( xpcall(error,goodhandler) ) )
print( 'xpcall(goodfunction,goodhandler)', ( xpcall(goodfunction,goodhandler) ) )
print( 'xpcall(badfunction,goodhandler)', ( xpcall(badfunction,goodhandler) ) )
print( 'xpcall(goodfunction,badhandler)', ( xpcall(goodfunction,badhandler) ) )
print( 'xpcall(badfunction,badhandler)', ( xpcall(badfunction,badhandler) ) )
print( 'xpcall(goodfunction,nil)', ( xpcall(goodfunction,nil) ) )
print( 'xpcall(badfunction,nil)', ( xpcall(badfunction,nil) ) )
print( 'xpcall(goodfunction)', ( pcall( function() return xpcall(goodfunction) end ) ) )
print( 'xpcall(badfunction)', ( pcall( function() return xpcall(badfunction) end ) ) )

View File

@@ -1,26 +0,0 @@
-- print uses tostring under-the-hood!
local function f()
print()
print('abc')
print(123)
print(true)
print('abc',123,true)
end
local function g()
local fenv = {tostring=function(x)
return '*'..type(x)..'*'
end}
package.seeall(fenv)
f()
print('setfenv', pcall(setfenv, 0, fenv), {}, f )
f()
end
local s,c = pcall( coroutine.create, g )
print('create', s, s and type(c) or c)
print('resume', pcall( coroutine.resume, c ) )
f()

View File

@@ -1,16 +0,0 @@
-- helper file for require() tests
require 'ids'
print( 'in subsample (before module statement)' )
print( 'env', id(getfenv()), '_G', id(_G), '_NAME', _NAME, '_M', id(_M), '_PACKAGE', _PACKAGE )
module( 'req.subsample', package.seeall )
print( 'in subsample (after module statement)' )
print( 'env', id(getfenv()), '_G', id(_G), '_NAME', _NAME, '_M', id(_M), '_PACKAGE', _PACKAGE )
function h()
print 'in subsample.h'
print( 'env', id(getfenv()), '_G', id(_G), '_NAME', _NAME, '_M', id(_M), '_PACKAGE', _PACKAGE )
end
print 'loading subsample.lua'
h()
return 'return value from subsample', 'second return value from subsample'

View File

@@ -1,101 +0,0 @@
-- unit tests for require() function
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- tests on require
package.path='?.lua;src/test/res/?.lua'
function f( name )
print( module( 'testmod', package.seeall ) )
print( 'before', id(sample), id(bogus), id(_G[name]) );
local status,result = pcall( require, name )
if status then
print( 'pcall(require,"'..name..'")', status, id(result) )
print( 'after', id(sample), id(bogus), id(_G[name]) );
else
print( 'pcall(require,"'..name..'")', status )
end
end
f('sample')
print( 'main', id(sample), id(bogus), id(custom), id(req) );
f('sample')
print( 'main', id(sample), id(bogus), id(custom), id(req) );
f('bogus')
print( 'main', id(sample), id(bogus), id(custom), id(req) );
f( 'req.subsample' )
print( 'main', id(sample), id(bogus), id(custom), id(req) );
-- custom loader chain
local pl = package.loaders
for i=1,3 do
print( i,id(package.loaders[i]) )
end
function loader1( ... )
print ('in loader1', ...)
return "loader1 didn't find anything"
end
function loader2( name, ... )
print ('in loader2', ...)
if name ~= 'custom' then
message = "name is not 'custom'"
print ('loader2 is returning', message )
return message
end
table = {}
result = function()
print( 'in loader function, returning', id(table) )
return table
end
print ('loader2 is returning', id(result) )
return result
end
function loader3( ... )
print ('in loader3', ...)
return nil
end
package.loaders = { loader1, loader2, loader3 }
f( 'bogus' )
print( 'main', id(sample), id(bogus), id(custom), id(src) );
f( 'custom' )
print( 'main', id(sample), id(bogus), id(custom), id(src) );
-- good, and bad lua samples
function g(name)
print( name, pcall(f,name) )
end
package.loaders = { function(...)
print( 'in success loader', ... )
return function(...)
print( 'in success chunk', ... )
end
end }
pcall( g, 'require-sample-succeed' )
package.loaders = { function(...)
print( 'in loader-error loader', ... )
error( 'sample error thrown by loader-error loader')
return function(...)
print( 'in loader-error chunk', ... )
end
end }
pcall( g, 'require-sample-loader-error' )
package.loaders = { function(...)
print( 'in chunk-error loader', ... )
return function(...)
error( 'sample error thrown by chunk-error function')
print( 'in chunk-error chunk', ... )
end
end }
pcall( g, 'require-sample-chunk-error' )
-- good, and bad java samples
--[[ (needs to be moved to different test suite)
package.loaders = pl
function g(name)
print( name, pcall(f,name) )
print( 'main', id(org) );
end
pcall( g, 'org.luaj.vm.require.RequireSampleClassCastExcep')
pcall( g, 'org.luaj.vm.require.RequireSampleLoadLuaError')
pcall( g, 'org.luaj.vm.require.RequireSampleLoadRuntimeExcep')
pcall( g, 'org.luaj.vm.require.RequireSampleSuccess')
pcall( g, 'org.luaj.vm.require.RequireSampleSuccess')
--]]

View File

@@ -1,7 +0,0 @@
-- helper file for require() tests
module( 'sample', package.seeall )
function h()
print 'in sample.h'
end
print 'loading sample.lua'

View File

@@ -1,31 +0,0 @@
-- Parts of this test are commented out because it looks like
-- there is a problem with our argument passing, particularly in the
-- presence of the VARARG instruction.
--[[ local function f(...)
print("arg count:", select('#', ...))
end
local function g(...)
local a, b, c = select(2, ...)
print(a, b, c)
end
]]--
print((select(1, "a", "b", "c")))
print( select(1, "a", "b", "c"))
print((select(2, "a", "b", "c")))
print( select(2, "a", "b", "c"))
print((select(3, "a", "b", "c")))
print( select(3, "a", "b", "c"))
print((select(4, "a", "b", "c")))
print( select(4, "a", "b", "c"))
print( select("#") )
print( select("#", "a") )
print( select("#", "a", "b") )
-- f("hello", "world")
-- g(1, 2, 3, 4, 5, 6, 7)

View File

@@ -1,61 +0,0 @@
-- object ids
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
local id = id
local setfenv = setfenv
local print = print
local pcall = pcall
local create = coroutine.create
local resume = coroutine.resume
local seeall = package.seeall
-- unit tests for getfenv, setfenv
local function f3(level,value)
if value then
local t = {abc=value}
seeall(t)
setfenv( level, t )
end
return abc
end
local function f2(...)
local r = f3(...)
return abc,r
end
local function f1(...)
local r,s = f2(...)
print( ' ....... f1 returning ',abc,r,s )
return abc,r,s
end
local function survey(msg)
print('-------',msg)
print( ' _G,f1,f2,f3', id(_G),id(f1),id(f2),id(f3) )
print( ' envs._G,f1,f2,f3', id(getfenv()),id(getfenv(f1)),id(getfenv(f2)),id(getfenv(f3)) )
print( ' vals._G,f1,f2,f3', abc,getfenv(f1).abc, getfenv(f2).abc, getfenv(f3).abc )
print( ' pcall(f1)', pcall(f1) )
end
survey( 'before')
setfenv(f1,{abc='ghi'})
setfenv(f2,{abc='jkl'})
setfenv(f3,{abc='mno'})
survey( 'after')
print( 'abc,f1(1,"pqr")', abc,f1(1,"pqr") )
print( 'abc,f1(2,"stu")', abc,f1(2,"stu") )
print( 'abc,f1(3,"vwx")', abc,f1(3,"vwx") )
survey( 'via f1()' )
local c = create( function()
survey( 'coroutine-thread-before')
print( 'f1(3,"abc")', f1(3,"567") )
survey( 'coroutine-thread-1')
print( 'f1(2,"abc")', f1(2,"456") )
survey( 'coroutine-thread-2')
print( 'f1(1,"abc")', f1(1,"345") )
survey( 'coroutine-thread-3')
print( 'f1(0,"abc")', f1(0,"234") )
survey( 'coroutine-thread-after')
end )
print( 'resume', resume(c) )
survey( 'post-resume')

View File

@@ -1,27 +0,0 @@
-- This file attemps to test that the setlist instruction works
local list = { 1, 2, 3 }
-- for now, can't just do:
-- for x, y in pairs( list ) do
-- since our tables don't iterate over keys in the same order
-- as regular Lua.
print( #list )
for i = 1, 3 do
print("list[", i, "]=", list[i])
end
local function printList( l )
for i = 1, #l do
print(i, "->", l[i] )
end
end
printList( { "a", "b", "c" } )
local function foo()
return "d", "e", "f", "g"
end
printList( { foo() } )

View File

@@ -1,14 +0,0 @@
-- The purpose of this test case is to check
-- that certain simple metatable operations work properly
t = { b='bbb' }
t.__index = t
u = {}
setmetatable( u, t )
u.c = 'ccc'
print( 't.a', t.a )
print( 'u.a', u.a )
print( 't.b', t.b )
print( 'u.b', u.b )
print( 't.c', t.c )
print( 'u.c', u.c )

View File

@@ -1,27 +0,0 @@
-- concat
print( '-- sort tests' )
local function tryall(cmp)
local function try(t)
print( table.concat(t,'-') )
if pcall( table.sort, t, cmp ) then
print( table.concat(t,'-') )
else
print( 'sort failed' )
end
end
try{ 2, 4, 6, 8, 1, 3, 5, 7 }
try{ 333, 222, 111 }
try{ "www", "xxx", "yyy", "aaa", "bbb", "ccc" }
try{ 21, 23, "25", 27, 22, "24", 26, 28 }
end
local function comparator(a,b)
return tonumber(a)<tonumber(b)
end
tryall()
tryall(comparator)

Some files were not shown because too many files have changed in this diff Show More