Remove obsolete v 1.0 source files (still available in 1.0 branch).
This commit is contained in:
@@ -105,7 +105,9 @@
|
||||
<mkdir dir="build/luaj-${version}/src"/>
|
||||
<mkdir dir="build/luaj-${version}/lib"/>
|
||||
<copy todir="build/luaj-${version}/src">
|
||||
<fileset dir="src"/>
|
||||
<fileset dir="src">
|
||||
<exclude name="src/test/**"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="build/luaj-${version}/test">
|
||||
<fileset dir="test"/>
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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 < 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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]);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
org.luaj.script.LuaScriptEngineFactory
|
||||
@@ -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 );
|
||||
|
||||
}
|
||||
@@ -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" );
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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))
|
||||
@@ -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) )
|
||||
@@ -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)
|
||||
@@ -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)))
|
||||
@@ -1,5 +0,0 @@
|
||||
print("5.0"+3.1)
|
||||
print(4+"7.5")
|
||||
print(3.14*" 2.75")
|
||||
print("-33"/"11")
|
||||
print(-"-5")
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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")
|
||||
--]]
|
||||
|
||||
|
||||
@@ -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) )
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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) )
|
||||
|
||||
@@ -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()
|
||||
@@ -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');
|
||||
@@ -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 }
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 )
|
||||
@@ -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) )
|
||||
|
||||
@@ -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' )
|
||||
@@ -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 ) ) )
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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')
|
||||
--]]
|
||||
@@ -1,7 +0,0 @@
|
||||
-- helper file for require() tests
|
||||
module( 'sample', package.seeall )
|
||||
function h()
|
||||
print 'in sample.h'
|
||||
end
|
||||
print 'loading sample.lua'
|
||||
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
@@ -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() } )
|
||||
@@ -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 )
|
||||
@@ -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
Reference in New Issue
Block a user