Move static variables used by libraries into explicit Globals object for better thread safety.
This commit is contained in:
93
src/core/org/luaj/vm2/Globals.java
Normal file
93
src/core/org/luaj/vm2/Globals.java
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Luaj.org. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LoadState.LuaCompiler;
|
||||||
|
import org.luaj.vm2.lib.BaseLib;
|
||||||
|
import org.luaj.vm2.lib.DebugLib;
|
||||||
|
import org.luaj.vm2.lib.ResourceFinder;
|
||||||
|
import org.luaj.vm2.lib.jme.JmePlatform;
|
||||||
|
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global environment used by luaj.
|
||||||
|
* <p>
|
||||||
|
* Contains the global variables referenced by lua libraries such as stdin and stdout,
|
||||||
|
* the resrouce finder which is used tolook up files in a platform independent way,
|
||||||
|
* the installed lua compiler, the math library in use, debugging calls stack, and so on.
|
||||||
|
* <p>
|
||||||
|
* In a multithreded server environment, each server thread should create one Globals instance,
|
||||||
|
* which will be logically distance and not interfere with each other, but share certain
|
||||||
|
* static immutable resources such as class data and string data.
|
||||||
|
* <p>
|
||||||
|
* Typically, this is constructed indirectly by a call to
|
||||||
|
* {@link JsePlatform.standardGlobasl()} or {@link JmePlatform.standardGlobals()},
|
||||||
|
* and then used to load lua scripts for execution as in the following example.
|
||||||
|
* <pre> {@code
|
||||||
|
* Globals _G = JsePlatform.standardGlobals();
|
||||||
|
* _G.compiler.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call();
|
||||||
|
* } </pre>
|
||||||
|
* @see LuaCompiler
|
||||||
|
* @see JsePlatform
|
||||||
|
* @see JmePlatform
|
||||||
|
* @see LuaValue
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Globals extends LuaTable {
|
||||||
|
|
||||||
|
public InputStream STDIN = null;
|
||||||
|
public PrintStream STDOUT = System.out;
|
||||||
|
public PrintStream STDERR = System.err;
|
||||||
|
|
||||||
|
public ResourceFinder FINDER;
|
||||||
|
|
||||||
|
public LuaCompiler compiler = null;
|
||||||
|
|
||||||
|
public LuaThread.CallStack callstack = new LuaThread.CallStack();
|
||||||
|
|
||||||
|
public BaseLib baselib;
|
||||||
|
|
||||||
|
public LuaValue errorfunc;
|
||||||
|
|
||||||
|
public LuaThread running_thread = new LuaThread(this);
|
||||||
|
|
||||||
|
public DebugLib debuglib;
|
||||||
|
|
||||||
|
public Globals checkglobals() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varargs loadFile(String filename) {
|
||||||
|
return baselib.loadFile(filename, "bt", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varargs yield(Varargs args) {
|
||||||
|
if (running_thread == null || running_thread.isMainThread())
|
||||||
|
throw new LuaError("cannot yield main thread");
|
||||||
|
final LuaThread.State s = running_thread.state;
|
||||||
|
return s.lua_yield(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,8 +21,6 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
import org.luaj.vm2.LoadState.LuaCompiler;
|
|
||||||
import org.luaj.vm2.compiler.LuaC;
|
|
||||||
import org.luaj.vm2.lib.DebugLib;
|
import org.luaj.vm2.lib.DebugLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,14 +90,7 @@ public class LuaClosure extends LuaFunction {
|
|||||||
|
|
||||||
public UpValue[] upValues;
|
public UpValue[] upValues;
|
||||||
|
|
||||||
/** Create a closure around a Prototype with the default global environment.
|
final Globals globals;
|
||||||
* If the prototype has upvalues, the environment will be written into the first upvalue.
|
|
||||||
* @param p the Prototype to construct this Closure for.
|
|
||||||
* @param env the environment to associate with the closure.
|
|
||||||
*/
|
|
||||||
public LuaClosure(Prototype p) {
|
|
||||||
this(p, LuaValue._G);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a closure around a Prototype with a specific environment.
|
/** Create a closure around a Prototype with a specific environment.
|
||||||
* If the prototype has upvalues, the environment will be written into the first upvalue.
|
* If the prototype has upvalues, the environment will be written into the first upvalue.
|
||||||
@@ -114,6 +105,7 @@ public class LuaClosure extends LuaFunction {
|
|||||||
this.upValues = new UpValue[p.upvalues.length];
|
this.upValues = new UpValue[p.upvalues.length];
|
||||||
this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
|
this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
|
||||||
}
|
}
|
||||||
|
globals = env instanceof Globals? (Globals) env: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isclosure() {
|
public boolean isclosure() {
|
||||||
@@ -184,7 +176,6 @@ public class LuaClosure extends LuaFunction {
|
|||||||
return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE);
|
return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
|
protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
|
||||||
// loop through instructions
|
// loop through instructions
|
||||||
int i,a,b,c,pc=0,top=0;
|
int i,a,b,c,pc=0,top=0;
|
||||||
@@ -194,18 +185,17 @@ public class LuaClosure extends LuaFunction {
|
|||||||
LuaValue[] k = p.k;
|
LuaValue[] k = p.k;
|
||||||
|
|
||||||
// upvalues are only possible when closures create closures
|
// upvalues are only possible when closures create closures
|
||||||
UpValue[] openups = p.p.length>0? new UpValue[stack.length]: null;
|
UpValue[] openups = p.p.length>0? new UpValue[p.p.length]: null;
|
||||||
|
|
||||||
// debug wants args to this function
|
// debug wants args to this function
|
||||||
if (DebugLib.DEBUG_ENABLED)
|
if (globals != null)
|
||||||
DebugLib.debugSetupCall(varargs, stack);
|
globals.callstack.onCall( this, varargs, stack );
|
||||||
|
|
||||||
// process instructions
|
// process instructions
|
||||||
LuaThread.CallStack cs = LuaThread.onCall( this );
|
|
||||||
try {
|
try {
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
if (DebugLib.DEBUG_ENABLED)
|
if (DebugLib.DEBUG_ENABLED && globals != null)
|
||||||
DebugLib.debugBytecode(pc, v, top);
|
globals.callstack.onInstruction( pc, v, top );
|
||||||
|
|
||||||
// pull out instruction
|
// pull out instruction
|
||||||
i = code[pc++];
|
i = code[pc++];
|
||||||
@@ -473,7 +463,7 @@ public class LuaClosure extends LuaFunction {
|
|||||||
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
|
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
|
||||||
{
|
{
|
||||||
Prototype newp = p.p[i>>>14];
|
Prototype newp = p.p[i>>>14];
|
||||||
LuaClosure ncl = new LuaClosure(newp, null);
|
LuaClosure ncl = new LuaClosure(newp, globals);
|
||||||
Upvaldesc[] uv = newp.upvalues;
|
Upvaldesc[] uv = newp.upvalues;
|
||||||
for ( int j=0, nup=uv.length; j<nup; ++j ) {
|
for ( int j=0, nup=uv.length; j<nup; ++j ) {
|
||||||
if (uv[j].instack) /* upvalue refes to local variable? */
|
if (uv[j].instack) /* upvalue refes to local variable? */
|
||||||
@@ -504,11 +494,16 @@ public class LuaClosure extends LuaFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch ( LuaError le ) {
|
} catch ( LuaError le ) {
|
||||||
|
if (le.traceback == null)
|
||||||
|
processErrorHooks(le, p, pc);
|
||||||
throw le;
|
throw le;
|
||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
throw new LuaError(e);
|
LuaError le = new LuaError(e);
|
||||||
|
processErrorHooks(le, p, pc);
|
||||||
|
throw le;
|
||||||
} finally {
|
} finally {
|
||||||
cs.onReturn();
|
if (globals != null)
|
||||||
|
globals.callstack.onReturn();
|
||||||
if ( openups != null )
|
if ( openups != null )
|
||||||
for ( int u=openups.length; --u>=0; )
|
for ( int u=openups.length; --u>=0; )
|
||||||
if ( openups[u] != null )
|
if ( openups[u] != null )
|
||||||
@@ -516,6 +511,32 @@ public class LuaClosure extends LuaFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the error hook if there is one
|
||||||
|
* @param msg the message to use in error hook processing.
|
||||||
|
* */
|
||||||
|
String errorHook(String msg) {
|
||||||
|
if (globals == null || globals.errorfunc == null)
|
||||||
|
return msg;
|
||||||
|
LuaValue errfunc = globals.errorfunc;
|
||||||
|
globals.errorfunc = null;
|
||||||
|
try {
|
||||||
|
return errfunc.call( LuaValue.valueOf(msg) ).tojstring();
|
||||||
|
} catch ( Throwable t ) {
|
||||||
|
return "error in error handling";
|
||||||
|
} finally {
|
||||||
|
globals.errorfunc = errfunc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processErrorHooks(LuaError le, Prototype p, int pc) {
|
||||||
|
le.fileline = (p.source != null? p.source.tojstring(): "?") + ":"
|
||||||
|
+ (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?");
|
||||||
|
le.traceback = errorHook(le.getMessage());
|
||||||
|
if (DebugLib.DEBUG_ENABLED && globals != null && globals.debuglib != null)
|
||||||
|
le.traceback += globals.callstack.traceback(le.level);
|
||||||
|
}
|
||||||
|
|
||||||
private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) {
|
private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) {
|
||||||
final int n = openups.length;
|
final int n = openups.length;
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
@@ -535,4 +556,22 @@ public class LuaClosure extends LuaFunction {
|
|||||||
protected void setUpvalue(int i, LuaValue v) {
|
protected void setUpvalue(int i, LuaValue v) {
|
||||||
upValues[i].setValue(v);
|
upValues[i].setValue(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add file and line info to a message at a particular level
|
||||||
|
* @param message the String message to use
|
||||||
|
* @param level where to supply line info from in call stack
|
||||||
|
* */
|
||||||
|
private String getFileLineMessage( Exception e, int pc ) {
|
||||||
|
String msg = e.getMessage();
|
||||||
|
if ( msg == null ) return null;
|
||||||
|
if ( globals == null ) return msg;
|
||||||
|
LuaFunction f = globals.callstack.getFunction(1);
|
||||||
|
if ( ! (f instanceof LuaClosure) ) return msg;
|
||||||
|
LuaClosure c = (LuaClosure) f;
|
||||||
|
LuaString file = c.p.source != null ? c.p.source: valueOf("?");
|
||||||
|
String line = c.p.lineinfo != null && pc < c.p.lineinfo.length? String.valueOf(c.p.lineinfo[pc]): "?";
|
||||||
|
return file.tojstring() + ": " + line;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,29 +38,18 @@ import org.luaj.vm2.lib.DebugLib;
|
|||||||
public class LuaError extends RuntimeException {
|
public class LuaError extends RuntimeException {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private String traceback;
|
protected int level;
|
||||||
|
|
||||||
/**
|
protected String fileline;
|
||||||
* Run the error hook if there is one
|
|
||||||
* @param msg the message to use in error hook processing.
|
|
||||||
* */
|
|
||||||
private static String errorHook(String msg) {
|
|
||||||
LuaThread thread = LuaThread.getRunning();
|
|
||||||
if ( thread.err != null ) {
|
|
||||||
LuaValue errfunc = thread.err;
|
|
||||||
thread.err = null;
|
|
||||||
try {
|
|
||||||
return errfunc.call( LuaValue.valueOf(msg) ).tojstring();
|
|
||||||
} catch ( Throwable t ) {
|
|
||||||
return "error in error handling";
|
|
||||||
} finally {
|
|
||||||
thread.err = errfunc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Throwable cause;
|
protected String traceback;
|
||||||
|
|
||||||
|
protected Throwable cause;
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return (fileline != null? fileline + " ": "")
|
||||||
|
+ (traceback != null? traceback: super.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
/** Construct LuaError when a program exception occurs.
|
/** Construct LuaError when a program exception occurs.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -68,9 +57,9 @@ public class LuaError extends RuntimeException {
|
|||||||
* @param cause the Throwable that caused the error, if known.
|
* @param cause the Throwable that caused the error, if known.
|
||||||
*/
|
*/
|
||||||
public LuaError(Throwable cause) {
|
public LuaError(Throwable cause) {
|
||||||
super( errorHook( addFileLine( "vm error: "+cause ) ) );
|
super( "vm error: "+cause );
|
||||||
this.cause = cause;
|
this.cause = cause;
|
||||||
this.traceback = DebugLib.traceback(1);
|
this.level = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,8 +68,8 @@ public class LuaError extends RuntimeException {
|
|||||||
* @param message message to supply
|
* @param message message to supply
|
||||||
*/
|
*/
|
||||||
public LuaError(String message) {
|
public LuaError(String message) {
|
||||||
super( errorHook( addFileLine( message ) ) );
|
super( message );
|
||||||
this.traceback = DebugLib.traceback(1);
|
this.level = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,37 +78,10 @@ public class LuaError extends RuntimeException {
|
|||||||
* @param level where to supply line info from in call stack
|
* @param level where to supply line info from in call stack
|
||||||
*/
|
*/
|
||||||
public LuaError(String message, int level) {
|
public LuaError(String message, int level) {
|
||||||
super( errorHook( addFileLine( message, level ) ) );
|
super( message );
|
||||||
this.traceback = DebugLib.traceback(1);
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add file and line info to a message at a particular level
|
|
||||||
* @param message the String message to use
|
|
||||||
* @param level where to supply line info from in call stack
|
|
||||||
* */
|
|
||||||
private static String addFileLine( String message, int level ) {
|
|
||||||
if ( message == null ) return null;
|
|
||||||
if ( level == 0 ) return message;
|
|
||||||
String fileline = DebugLib.fileline(level-1);
|
|
||||||
return fileline!=null? fileline+": "+message: message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add file and line info for the nearest enclosing closure
|
|
||||||
* @param message the String message to use
|
|
||||||
* */
|
|
||||||
private static String addFileLine( String message ) {
|
|
||||||
if ( message == null ) return null;
|
|
||||||
String fileline = DebugLib.fileline();
|
|
||||||
return fileline!=null? fileline+": "+message: message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Print the message and stack trace */
|
|
||||||
public void printStackTrace() {
|
|
||||||
System.out.println( toString() );
|
|
||||||
if ( traceback != null )
|
|
||||||
System.out.println( traceback );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the cause, if any.
|
* Get the cause, if any.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ package org.luaj.vm2;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaThread.CallFrame;
|
||||||
import org.luaj.vm2.lib.DebugLib;
|
import org.luaj.vm2.lib.DebugLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,37 +85,39 @@ public class LuaThread extends LuaValue {
|
|||||||
|
|
||||||
public final State state;
|
public final State state;
|
||||||
|
|
||||||
/** Field to hold state of error condition during debug hook function calls. */
|
|
||||||
public LuaValue err;
|
|
||||||
|
|
||||||
final CallStack callstack = new CallStack();
|
final CallStack callstack = new CallStack();
|
||||||
|
|
||||||
public static final int MAX_CALLSTACK = 256;
|
public static final int MAX_CALLSTACK = 256;
|
||||||
|
|
||||||
private static final LuaThread main_thread = new LuaThread();
|
|
||||||
|
|
||||||
// state of running thread including call stack
|
|
||||||
private static LuaThread running_thread = main_thread;
|
|
||||||
|
|
||||||
/** Interval to check for LuaThread dereferencing. */
|
/** Interval to check for LuaThread dereferencing. */
|
||||||
public static int GC_INTERVAL = 30000;
|
public static int GC_INTERVAL = 30000;
|
||||||
|
|
||||||
/** Thread-local used by DebugLib to store debugging state. */
|
/** Thread-local used by DebugLib to store debugging state. */
|
||||||
public Object debugState;
|
public Object debugState;
|
||||||
|
|
||||||
|
public LuaValue hookfunc;
|
||||||
|
public boolean hookline;
|
||||||
|
public boolean hookcall;
|
||||||
|
public boolean hookrtrn;
|
||||||
|
public int hookcount;
|
||||||
|
|
||||||
|
public final Globals globals;
|
||||||
|
|
||||||
/** Private constructor for main thread only */
|
/** Private constructor for main thread only */
|
||||||
private LuaThread() {
|
public LuaThread(Globals globals) {
|
||||||
state = new State(this, null);
|
state = new State(globals, this, null);
|
||||||
state.status = STATUS_RUNNING;
|
state.status = STATUS_RUNNING;
|
||||||
|
this.globals = globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a LuaThread around a function and environment
|
* Create a LuaThread around a function and environment
|
||||||
* @param func The function to execute
|
* @param func The function to execute
|
||||||
*/
|
*/
|
||||||
public LuaThread(LuaValue func) {
|
public LuaThread(Globals globals, LuaValue func) {
|
||||||
LuaValue.assert_(func != null, "function cannot be null");
|
LuaValue.assert_(func != null, "function cannot be null");
|
||||||
state = new State(this, func);
|
state = new State(globals, this, func);
|
||||||
|
this.globals = globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int type() {
|
public int type() {
|
||||||
@@ -145,71 +148,20 @@ public class LuaThread extends LuaValue {
|
|||||||
return STATUS_NAMES[state.status];
|
return STATUS_NAMES[state.status];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public boolean isMainThread() {
|
||||||
* Get the currently running thread.
|
return this.state.function == null;
|
||||||
* @return {@link LuaThread} that is currenly running
|
|
||||||
*/
|
|
||||||
public static LuaThread getRunning() {
|
|
||||||
return running_thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
|
|
||||||
* @param function Function being called
|
|
||||||
* @return CallStack which is used to signal the return or a tail-call recursion
|
|
||||||
* @see DebugLib
|
|
||||||
*/
|
|
||||||
public static final CallStack onCall(LuaFunction function) {
|
|
||||||
CallStack cs = running_thread.callstack;
|
|
||||||
cs.onCall(function);
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the function called as a specific location on the stack.
|
|
||||||
* @param level 1 for the function calling this one, 2 for the next one.
|
|
||||||
* @return LuaFunction on the call stack, or null if outside of range of active stack
|
|
||||||
*/
|
|
||||||
public static final LuaFunction getCallstackFunction(int level) {
|
|
||||||
return running_thread.callstack.getFunction(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace the error function of the currently running thread.
|
|
||||||
* @param errfunc the new error function to use.
|
|
||||||
* @return the previous error function.
|
|
||||||
*/
|
|
||||||
public static LuaValue setErrorFunc(LuaValue errfunc) {
|
|
||||||
LuaValue prev = running_thread.err;
|
|
||||||
running_thread.err = errfunc;
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Yield the current thread with arguments
|
|
||||||
*
|
|
||||||
* @param args The arguments to send as return values to {@link #resume(Varargs)}
|
|
||||||
* @return {@link Varargs} provided as arguments to {@link #resume(Varargs)}
|
|
||||||
*/
|
|
||||||
public static Varargs yield(Varargs args) {
|
|
||||||
State s = running_thread.state;
|
|
||||||
if (s.function == null)
|
|
||||||
throw new LuaError("cannot yield main thread");
|
|
||||||
return s.lua_yield(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Start or resume this thread
|
|
||||||
*
|
|
||||||
* @param args The arguments to send as return values to {@link #yield(Varargs)}
|
|
||||||
* @return {@link Varargs} provided as arguments to {@link #yield(Varargs)}
|
|
||||||
*/
|
|
||||||
public Varargs resume(Varargs args) {
|
public Varargs resume(Varargs args) {
|
||||||
if (this.state.status > STATUS_SUSPENDED)
|
final LuaThread.State s = this.state;
|
||||||
|
if (s.status > LuaThread.STATUS_SUSPENDED)
|
||||||
return LuaValue.varargsOf(LuaValue.FALSE,
|
return LuaValue.varargsOf(LuaValue.FALSE,
|
||||||
LuaValue.valueOf("cannot resume "+LuaThread.STATUS_NAMES[this.state.status]+" coroutine"));
|
LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine"));
|
||||||
return state.lua_resume(this, args);
|
return s.lua_resume(this, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class State implements Runnable {
|
public static class State implements Runnable {
|
||||||
|
private final Globals globals;
|
||||||
final WeakReference lua_thread;
|
final WeakReference lua_thread;
|
||||||
public final LuaValue function;
|
public final LuaValue function;
|
||||||
Varargs args = LuaValue.NONE;
|
Varargs args = LuaValue.NONE;
|
||||||
@@ -217,7 +169,8 @@ public class LuaThread extends LuaValue {
|
|||||||
String error = null;
|
String error = null;
|
||||||
public int status = LuaThread.STATUS_INITIAL;
|
public int status = LuaThread.STATUS_INITIAL;
|
||||||
|
|
||||||
State(LuaThread lua_thread, LuaValue function) {
|
State(Globals globals, LuaThread lua_thread, LuaValue function) {
|
||||||
|
this.globals = globals;
|
||||||
this.lua_thread = new WeakReference(lua_thread);
|
this.lua_thread = new WeakReference(lua_thread);
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
@@ -236,9 +189,9 @@ public class LuaThread extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) {
|
public synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) {
|
||||||
LuaThread previous_thread = LuaThread.running_thread;
|
LuaThread previous_thread = globals.running_thread;
|
||||||
try {
|
try {
|
||||||
LuaThread.running_thread = new_thread;
|
globals.running_thread = new_thread;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
if (this.status == STATUS_INITIAL) {
|
if (this.status == STATUS_INITIAL) {
|
||||||
this.status = STATUS_RUNNING;
|
this.status = STATUS_RUNNING;
|
||||||
@@ -246,6 +199,7 @@ public class LuaThread extends LuaValue {
|
|||||||
} else {
|
} else {
|
||||||
this.notify();
|
this.notify();
|
||||||
}
|
}
|
||||||
|
if (previous_thread != null)
|
||||||
previous_thread.state.status = STATUS_NORMAL;
|
previous_thread.state.status = STATUS_NORMAL;
|
||||||
this.status = STATUS_RUNNING;
|
this.status = STATUS_RUNNING;
|
||||||
this.wait();
|
this.wait();
|
||||||
@@ -255,11 +209,12 @@ public class LuaThread extends LuaValue {
|
|||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
throw new OrphanedThread();
|
throw new OrphanedThread();
|
||||||
} finally {
|
} finally {
|
||||||
running_thread = previous_thread;
|
|
||||||
running_thread.state.status =STATUS_RUNNING;
|
|
||||||
this.args = LuaValue.NONE;
|
this.args = LuaValue.NONE;
|
||||||
this.result = LuaValue.NONE;
|
this.result = LuaValue.NONE;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
globals.running_thread = previous_thread;
|
||||||
|
if (previous_thread != null)
|
||||||
|
globals.running_thread.state.status =STATUS_RUNNING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,17 +242,30 @@ public class LuaThread extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class CallStack {
|
public static class CallStack {
|
||||||
final LuaFunction[] functions = new LuaFunction[MAX_CALLSTACK];
|
final CallFrame[] frame = new CallFrame[MAX_CALLSTACK];
|
||||||
int calls = 0;
|
int calls = 0;
|
||||||
|
|
||||||
|
CallStack() {
|
||||||
|
for (int i = 0; i < MAX_CALLSTACK; ++i)
|
||||||
|
frame[i] = new CallFrame();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to indicate the start of a call
|
* Method to indicate the start of a call
|
||||||
|
* @param stack
|
||||||
|
* @param varargs
|
||||||
* @see DebugLib
|
* @see DebugLib
|
||||||
*/
|
*/
|
||||||
final void onCall(LuaFunction function) {
|
public final void onCall(LuaFunction function) {
|
||||||
functions[calls++] = function;
|
frame[calls++].set(function);
|
||||||
if (DebugLib.DEBUG_ENABLED)
|
// if (DebugLib.DEBUG_ENABLED)
|
||||||
DebugLib.debugOnCall(running_thread, calls, function);
|
// DebugLib.debugOnCall(globals.running_thread, calls, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) {
|
||||||
|
frame[calls++].set(function, varargs, stack);
|
||||||
|
// if (DebugLib.DEBUG_ENABLED)
|
||||||
|
// DebugLib.debugOnCall(globals.running_thread, calls, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -305,9 +273,13 @@ public class LuaThread extends LuaValue {
|
|||||||
* @see DebugLib
|
* @see DebugLib
|
||||||
*/
|
*/
|
||||||
public final void onReturn() {
|
public final void onReturn() {
|
||||||
functions[--calls] = null;
|
frame[--calls].reset();
|
||||||
if (DebugLib.DEBUG_ENABLED)
|
// if (DebugLib.DEBUG_ENABLED)
|
||||||
DebugLib.debugOnReturn(running_thread, calls);
|
// DebugLib.debugOnReturn(running_thread, calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void onInstruction(int pc, Varargs v, int top) {
|
||||||
|
frame[calls-1].instr(pc, v, top);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -324,12 +296,103 @@ public class LuaThread extends LuaValue {
|
|||||||
* @param level # of levels back from the top of the stack.
|
* @param level # of levels back from the top of the stack.
|
||||||
* @return LuaFunction, or null if beyond the stack limits.
|
* @return LuaFunction, or null if beyond the stack limits.
|
||||||
*/
|
*/
|
||||||
LuaFunction getFunction(int level) {
|
public LuaFunction getFunction(int level) {
|
||||||
return level>0 && level<=calls? functions[calls-level]: null;
|
return level>0 && level<=calls? frame[calls-level].f: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the traceback starting at a specific level.
|
||||||
|
* @param level
|
||||||
|
* @return String containing the traceback.
|
||||||
|
*/
|
||||||
|
public String traceback(int level) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append( "stack traceback:" );
|
||||||
|
for (LuaFunction f = null; (f = getFunction(level)) != null; ++level) {
|
||||||
|
sb.append( "\n\t" );
|
||||||
|
sb.append( f.tostring() );
|
||||||
|
sb.append( "main chunk" );
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallFrame getCallFrame(int level) {
|
||||||
|
if (level < 1 || level >= calls)
|
||||||
|
return null;
|
||||||
|
return frame[calls-level];
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallFrame findCallFrame(LuaValue func) {
|
||||||
|
for (int i = 1; i <= calls; ++i)
|
||||||
|
if (frame[calls-i].f == func)
|
||||||
|
return frame[i];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CallFrame {
|
||||||
|
public LuaFunction f;
|
||||||
|
int pc, top;
|
||||||
|
Varargs v;
|
||||||
|
LuaValue[] stack;
|
||||||
|
public void set(LuaClosure function, Varargs varargs, LuaValue[] stack) {
|
||||||
|
this.f = function;
|
||||||
|
this.v = varargs;
|
||||||
|
this.stack = stack;
|
||||||
|
}
|
||||||
|
public void print() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
public void set(LuaFunction function) {
|
||||||
|
this.f = function;
|
||||||
|
}
|
||||||
|
public void reset() {
|
||||||
|
this.f = null;
|
||||||
|
this.v = null;
|
||||||
|
this.stack = null;
|
||||||
|
}
|
||||||
|
public void instr(int pc, Varargs v, int top) {
|
||||||
|
this.pc = pc;
|
||||||
|
this.v = v;
|
||||||
|
this.top = top;
|
||||||
|
if (DebugLib.DEBUG_ENABLED && DebugLib.TRACE & f.isclosure())
|
||||||
|
Print.printState(f.checkclosure(), pc, stack, top, v);
|
||||||
|
}
|
||||||
|
public int getLine() {
|
||||||
|
if (!f.isclosure())
|
||||||
|
return 0;
|
||||||
|
LuaClosure c = (LuaClosure) f;
|
||||||
|
Prototype p = c.p;
|
||||||
|
if (p.lineinfo == null || pc < 0 || pc >= p.lineinfo[pc])
|
||||||
|
return 0;
|
||||||
|
return p.lineinfo[pc];
|
||||||
|
}
|
||||||
|
public Varargs getLocal(int i) {
|
||||||
|
if (!f.isclosure())
|
||||||
|
return NONE;
|
||||||
|
LuaClosure c = (LuaClosure) f;
|
||||||
|
Prototype p = c.p;
|
||||||
|
if (i < 1 || i > stack.length)
|
||||||
|
if (p.locvars != null && p.locvars.length >= i)
|
||||||
|
return varargsOf(stack[i-1], p.locvars[i-1].varname);
|
||||||
|
else
|
||||||
|
return stack[i-1];
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
public Varargs setLocal(int i, LuaValue value) {
|
||||||
|
if (!f.isclosure())
|
||||||
|
return NONE;
|
||||||
|
LuaClosure c = (LuaClosure) f;
|
||||||
|
Prototype p = c.p;
|
||||||
|
if (i < 1 || i > stack.length)
|
||||||
|
return NONE;
|
||||||
|
stack[i] = value;
|
||||||
|
if (p.locvars != null && p.locvars.length >= i)
|
||||||
|
return p.locvars[i-1].varname;
|
||||||
|
return NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMainThread() {
|
|
||||||
return this.state.function == null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ package org.luaj.vm2;
|
|||||||
|
|
||||||
public class LuaUserdata extends LuaValue {
|
public class LuaUserdata extends LuaValue {
|
||||||
|
|
||||||
public final Object m_instance;
|
public Object m_instance;
|
||||||
public LuaValue m_metatable;
|
public LuaValue m_metatable;
|
||||||
|
|
||||||
public LuaUserdata(Object obj) {
|
public LuaUserdata(Object obj) {
|
||||||
|
|||||||
@@ -109,11 +109,6 @@ package org.luaj.vm2;
|
|||||||
*/
|
*/
|
||||||
abstract
|
abstract
|
||||||
public class LuaValue extends Varargs {
|
public class LuaValue extends Varargs {
|
||||||
/** The default global environment. This must be set before lua can be used.
|
|
||||||
* Typically, it is set as a side effect of calling one of
|
|
||||||
* JsePlatform.standardGlobals() or similar functions.
|
|
||||||
*/
|
|
||||||
public static LuaValue _G;
|
|
||||||
|
|
||||||
/** Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only */
|
/** Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only */
|
||||||
public static final int TINT = (-2);
|
public static final int TINT = (-2);
|
||||||
@@ -878,6 +873,15 @@ public class LuaValue extends Varargs {
|
|||||||
*/
|
*/
|
||||||
public LuaValue checkfunction() { argerror("function"); return null; }
|
public LuaValue checkfunction() { argerror("function"); return null; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Check that the value is a Globals instance, or throw {@link LuaError} if not
|
||||||
|
* <p>
|
||||||
|
* {@link Globals} are a special {@link LuaTable} that establish the default global environment.
|
||||||
|
* @return {@code this} if if an instance fof {@Globals}
|
||||||
|
* @throws LuaError if not a {@link Globals} instance.
|
||||||
|
*/
|
||||||
|
public Globals checkglobals() { argerror("globals"); return null; }
|
||||||
|
|
||||||
/** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric
|
/** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric
|
||||||
* <p>
|
* <p>
|
||||||
* Values that are {@link LuaNumber} will be cast to int and may lose precision.
|
* Values that are {@link LuaNumber} will be cast to int and may lose precision.
|
||||||
@@ -1354,13 +1358,14 @@ public class LuaValue extends Varargs {
|
|||||||
public Varargs inext(LuaValue index) { return typerror("table"); }
|
public Varargs inext(LuaValue index) { return typerror("table"); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a library instance by setting its environment to the global environment {@code LuaValue._G}
|
* Load a library instance by setting its environment to the calling object,
|
||||||
* and calling it, which should iniitalize the library instance and
|
* and calling it, which should iniitalize the library instance and
|
||||||
* install itself into this instance.
|
* install itself into this instance. The calling object should be the
|
||||||
|
* {@link Globals} environment to associate wtih the library.
|
||||||
* @param library The callable {@link LuaValue} to load into {@code this}
|
* @param library The callable {@link LuaValue} to load into {@code this}
|
||||||
* @return {@link LuaValue._G} containing the result of the initialization call.
|
* @return {@link LuaValue._G} containing the result of the initialization call.
|
||||||
*/
|
*/
|
||||||
public LuaValue load(LuaValue library) { return load(library, _G); }
|
public LuaValue load(LuaValue library) { return load(library, this); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a library instance by setting its environment to {@code env}
|
* Load a library instance by setting its environment to {@code env}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LoadState;
|
import org.luaj.vm2.LoadState;
|
||||||
import org.luaj.vm2.Lua;
|
import org.luaj.vm2.Lua;
|
||||||
import org.luaj.vm2.LuaError;
|
import org.luaj.vm2.LuaError;
|
||||||
@@ -73,36 +74,21 @@ import org.luaj.vm2.Varargs;
|
|||||||
*/
|
*/
|
||||||
public class BaseLib extends OneArgFunction implements ResourceFinder {
|
public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||||
|
|
||||||
public static BaseLib instance;
|
Globals globals;
|
||||||
|
|
||||||
public InputStream STDIN = null;
|
|
||||||
public PrintStream STDOUT = System.out;
|
|
||||||
public PrintStream STDERR = System.err;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton file opener for this Java ClassLoader realm.
|
|
||||||
*
|
|
||||||
* Unless set or changed elsewhere, will be set by the BaseLib that is created.
|
|
||||||
*/
|
|
||||||
public static ResourceFinder FINDER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a base libarary instance.
|
|
||||||
*/
|
|
||||||
public BaseLib() {
|
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LuaValue call(LuaValue env) {
|
public LuaValue call(LuaValue env) {
|
||||||
|
globals = env.checkglobals();
|
||||||
|
globals.FINDER = this;
|
||||||
|
globals.baselib = this;
|
||||||
env.set( "_G", env );
|
env.set( "_G", env );
|
||||||
env.set( "_VERSION", Lua._VERSION );
|
env.set( "_VERSION", Lua._VERSION );
|
||||||
env.set("assert", new _assert());
|
env.set("assert", new _assert());
|
||||||
env.set("collectgarbage", new collectgarbage());
|
env.set("collectgarbage", new collectgarbage());
|
||||||
env.set("dofile", new dofile(this));
|
env.set("dofile", new dofile());
|
||||||
env.set("error", new error());
|
env.set("error", new error());
|
||||||
env.set("getmetatable", new getmetatable());
|
env.set("getmetatable", new getmetatable());
|
||||||
env.set("load", new load());
|
env.set("load", new load());
|
||||||
env.set("loadfile", new loadfile(this));
|
env.set("loadfile", new loadfile());
|
||||||
env.set("pcall", new pcall());
|
env.set("pcall", new pcall());
|
||||||
env.set("print", new print(this));
|
env.set("print", new print(this));
|
||||||
env.set("rawequal", new rawequal());
|
env.set("rawequal", new rawequal());
|
||||||
@@ -121,9 +107,6 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
env.set("pairs", new pairs(next));
|
env.set("pairs", new pairs(next));
|
||||||
env.set("ipairs", new ipairs());
|
env.set("ipairs", new ipairs());
|
||||||
|
|
||||||
// set the default resource finder if not set already
|
|
||||||
if ( FINDER == null )
|
|
||||||
FINDER = this;
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,8 +115,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
* Tries to open the file as a resource, which can work for JSE and JME.
|
* Tries to open the file as a resource, which can work for JSE and JME.
|
||||||
*/
|
*/
|
||||||
public InputStream findResource(String filename) {
|
public InputStream findResource(String filename) {
|
||||||
Class c = getClass();
|
return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/"+filename);
|
||||||
return c.getResourceAsStream(filename.startsWith("/")? filename: "/"+filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -168,17 +150,13 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "dofile", // ( filename ) -> result1, ...
|
// "dofile", // ( filename ) -> result1, ...
|
||||||
static final class dofile extends VarArgFunction {
|
final class dofile extends VarArgFunction {
|
||||||
final BaseLib baselib;
|
|
||||||
dofile(BaseLib baselib) {
|
|
||||||
this.baselib = baselib;
|
|
||||||
}
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
||||||
String filename = args.isstring(1)? args.tojstring(1): null;
|
String filename = args.isstring(1)? args.tojstring(1): null;
|
||||||
Varargs v = filename == null?
|
Varargs v = filename == null?
|
||||||
BaseLib.loadStream( baselib.STDIN, "=stdin", "bt",LuaValue._G ):
|
loadStream( globals.STDIN, "=stdin", "bt", globals ):
|
||||||
BaseLib.loadFile( args.checkjstring(1), "bt",LuaValue._G );
|
loadFile( args.checkjstring(1), "bt", globals );
|
||||||
return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
|
return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,63 +179,59 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
|
// "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
|
||||||
static final class load extends VarArgFunction {
|
final class load extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue ld = args.arg1();
|
LuaValue ld = args.arg1();
|
||||||
args.argcheck(ld.isstring() || ld.isfunction(), 1, "ld must be string or function");
|
args.argcheck(ld.isstring() || ld.isfunction(), 1, "ld must be string or function");
|
||||||
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
||||||
String mode = args.optjstring(3, "bt");
|
String mode = args.optjstring(3, "bt");
|
||||||
LuaValue env = args.optvalue(4,LuaValue._G);
|
LuaValue env = args.optvalue(4, globals);
|
||||||
return BaseLib.loadStream(ld.isstring()? ld.strvalue().toInputStream():
|
return loadStream(ld.isstring()? ld.strvalue().toInputStream():
|
||||||
new StringInputStream(ld.checkfunction()), source, mode, env);
|
new StringInputStream(ld.checkfunction()), source, mode, env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg
|
// "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg
|
||||||
static final class loadfile extends VarArgFunction {
|
final class loadfile extends VarArgFunction {
|
||||||
final BaseLib baselib;
|
|
||||||
loadfile(BaseLib baselib) {
|
|
||||||
this.baselib = baselib;
|
|
||||||
}
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
||||||
String filename = args.isstring(1)? args.tojstring(1): null;
|
String filename = args.isstring(1)? args.tojstring(1): null;
|
||||||
String mode = args.optjstring(2, "bt");
|
String mode = args.optjstring(2, "bt");
|
||||||
LuaValue env = args.optvalue(3,LuaValue._G);
|
LuaValue env = args.optvalue(3, globals);
|
||||||
return filename == null?
|
return filename == null?
|
||||||
BaseLib.loadStream( baselib.STDIN, "=stdin", mode, env ):
|
loadStream( globals.STDIN, "=stdin", mode, env ):
|
||||||
BaseLib.loadFile( filename, mode, env );
|
loadFile( filename, mode, env );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "pcall", // (f, arg1, ...) -> status, result1, ...
|
// "pcall", // (f, arg1, ...) -> status, result1, ...
|
||||||
static final class pcall extends VarArgFunction {
|
final class pcall extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue func = args.checkvalue(1);
|
LuaValue func = args.checkvalue(1);
|
||||||
LuaThread.CallStack cs = LuaThread.onCall(this);
|
globals.callstack.onCall(this);
|
||||||
try {
|
try {
|
||||||
return pcall(func,args.subargs(2),null);
|
return pcall(func,args.subargs(2),null);
|
||||||
} finally {
|
} finally {
|
||||||
cs.onReturn();
|
globals.callstack.onReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "print", // (...) -> void
|
// "print", // (...) -> void
|
||||||
static final class print extends VarArgFunction {
|
final class print extends VarArgFunction {
|
||||||
final BaseLib baselib;
|
final BaseLib baselib;
|
||||||
print(BaseLib baselib) {
|
print(BaseLib baselib) {
|
||||||
this.baselib = baselib;
|
this.baselib = baselib;
|
||||||
}
|
}
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue tostring =LuaValue._G.get("tostring");
|
LuaValue tostring = globals.get("tostring");
|
||||||
for ( int i=1, n=args.narg(); i<=n; i++ ) {
|
for ( int i=1, n=args.narg(); i<=n; i++ ) {
|
||||||
if ( i>1 ) baselib.STDOUT.write( '\t' );
|
if ( i>1 ) globals.STDOUT.write( '\t' );
|
||||||
LuaString s = tostring.call( args.arg(i) ).strvalue();
|
LuaString s = tostring.call( args.arg(i) ).strvalue();
|
||||||
int z = s.indexOf((byte)0, 0);
|
int z = s.indexOf((byte)0, 0);
|
||||||
baselib.STDOUT.write( s.m_bytes, s.m_offset, z>=0? z: s.m_length );
|
globals.STDOUT.write( s.m_bytes, s.m_offset, z>=0? z: s.m_length );
|
||||||
}
|
}
|
||||||
baselib.STDOUT.println();
|
globals.STDOUT.println();
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -374,13 +348,13 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "xpcall", // (f, err) -> result1, ...
|
// "xpcall", // (f, err) -> result1, ...
|
||||||
static final class xpcall extends VarArgFunction {
|
final class xpcall extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaThread.CallStack cs = LuaThread.onCall(this);
|
globals.callstack.onCall(this);
|
||||||
try {
|
try {
|
||||||
return pcall(args.arg1(),NONE,args.checkvalue(2));
|
return pcall(args.arg1(),NONE,args.checkvalue(2));
|
||||||
} finally {
|
} finally {
|
||||||
cs.onReturn();
|
globals.callstack.onReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,18 +392,19 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Varargs pcall(LuaValue func, Varargs args, LuaValue errfunc) {
|
public Varargs pcall(LuaValue func, Varargs args, LuaValue errorfunc) {
|
||||||
LuaValue olderr = LuaThread.setErrorFunc(errfunc);
|
|
||||||
try {
|
try {
|
||||||
Varargs result = varargsOf(LuaValue.TRUE, func.invoke(args));
|
LuaValue olderr = globals.errorfunc;
|
||||||
LuaThread.setErrorFunc(olderr);
|
globals.errorfunc = errorfunc;
|
||||||
return result;
|
try {
|
||||||
|
return varargsOf(LuaValue.TRUE, func.invoke(args));
|
||||||
|
} finally {
|
||||||
|
globals.errorfunc = olderr;
|
||||||
|
}
|
||||||
} catch ( LuaError le ) {
|
} catch ( LuaError le ) {
|
||||||
LuaThread.setErrorFunc(olderr);
|
|
||||||
String m = le.getMessage();
|
String m = le.getMessage();
|
||||||
return varargsOf(FALSE, m!=null? valueOf(m): NIL);
|
return varargsOf(FALSE, m!=null? valueOf(m): NIL);
|
||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
LuaThread.setErrorFunc(olderr);
|
|
||||||
String m = e.getMessage();
|
String m = e.getMessage();
|
||||||
return varargsOf(FALSE, valueOf(m!=null? m: e.toString()));
|
return varargsOf(FALSE, valueOf(m!=null? m: e.toString()));
|
||||||
}
|
}
|
||||||
@@ -441,8 +416,8 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
* @param mode
|
* @param mode
|
||||||
* @return Varargs containing chunk, or NIL,error-text on error
|
* @return Varargs containing chunk, or NIL,error-text on error
|
||||||
*/
|
*/
|
||||||
public static Varargs loadFile(String filename, String mode, LuaValue env) {
|
public Varargs loadFile(String filename, String mode, LuaValue env) {
|
||||||
InputStream is = FINDER.findResource(filename);
|
InputStream is = globals.FINDER.findResource(filename);
|
||||||
if ( is == null )
|
if ( is == null )
|
||||||
return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory"));
|
return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory"));
|
||||||
try {
|
try {
|
||||||
@@ -456,7 +431,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) {
|
public Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) {
|
||||||
try {
|
try {
|
||||||
if ( is == null )
|
if ( is == null )
|
||||||
return varargsOf(NIL, valueOf("not found: "+chunkname));
|
return varargsOf(NIL, valueOf("not found: "+chunkname));
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class Bit32Lib extends OneArgFunction {
|
|||||||
"arshift", "lrotate", "lshift", "rrotate", "rshift"
|
"arshift", "lrotate", "lshift", "rrotate", "rshift"
|
||||||
});
|
});
|
||||||
env.set("bit32", t);
|
env.set("bit32", t);
|
||||||
PackageLib.instance.LOADED.set("bit32", t);
|
env.get("package").get("loaded").set("bit32", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.lib;
|
package org.luaj.vm2.lib;
|
||||||
|
|
||||||
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LuaError;
|
import org.luaj.vm2.LuaError;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
import org.luaj.vm2.LuaThread;
|
||||||
@@ -61,7 +62,10 @@ public class CoroutineLib extends OneArgFunction {
|
|||||||
|
|
||||||
static int coroutine_count = 0;
|
static int coroutine_count = 0;
|
||||||
|
|
||||||
|
Globals globals;
|
||||||
|
|
||||||
public LuaValue call(LuaValue env) {
|
public LuaValue call(LuaValue env) {
|
||||||
|
globals = env.checkglobals();
|
||||||
LuaTable coroutine = new LuaTable();
|
LuaTable coroutine = new LuaTable();
|
||||||
coroutine.set("create", new create());
|
coroutine.set("create", new create());
|
||||||
coroutine.set("resume", new resume());
|
coroutine.set("resume", new resume());
|
||||||
@@ -70,27 +74,26 @@ public class CoroutineLib extends OneArgFunction {
|
|||||||
coroutine.set("yield", new yield());
|
coroutine.set("yield", new yield());
|
||||||
coroutine.set("wrap", new wrap());
|
coroutine.set("wrap", new wrap());
|
||||||
env.set("coroutine", coroutine);
|
env.set("coroutine", coroutine);
|
||||||
env.get("package").get("loaded").set("coroutine", TRUE);
|
env.get("package").get("loaded").set("coroutine", coroutine);
|
||||||
return coroutine;
|
return coroutine;
|
||||||
}
|
}
|
||||||
|
|
||||||
final class create extends LibFunction {
|
final class create extends LibFunction {
|
||||||
public LuaValue call(LuaValue f) {
|
public LuaValue call(LuaValue f) {
|
||||||
return new LuaThread(f.checkfunction());
|
return new LuaThread(globals, f.checkfunction());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class resume extends VarArgFunction {
|
final class resume extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
if (!(args.arg1() instanceof LuaThread)) argerror(1, "thread");
|
final LuaThread t = args.checkthread(1);
|
||||||
final LuaThread t = (LuaThread) args.arg1();
|
return t.resume( args.subargs(2) );
|
||||||
return resume( t, args.subargs(2) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class running extends VarArgFunction {
|
final class running extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
final LuaThread r = LuaThread.getRunning();
|
final LuaThread r = globals.running_thread;
|
||||||
return varargsOf(r, valueOf(r.isMainThread()));
|
return varargsOf(r, valueOf(r.isMainThread()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,14 +107,14 @@ public class CoroutineLib extends OneArgFunction {
|
|||||||
|
|
||||||
final class yield extends VarArgFunction {
|
final class yield extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
return yield( args );
|
return globals.yield( args );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class wrap extends LibFunction {
|
final class wrap extends LibFunction {
|
||||||
public LuaValue call(LuaValue f) {
|
public LuaValue call(LuaValue f) {
|
||||||
final LuaValue func = f.checkfunction();
|
final LuaValue func = f.checkfunction();
|
||||||
final LuaThread thread = new LuaThread(func);
|
final LuaThread thread = new LuaThread(globals, func);
|
||||||
return new wrapper(thread);
|
return new wrapper(thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +125,7 @@ public class CoroutineLib extends OneArgFunction {
|
|||||||
this.luathread = luathread;
|
this.luathread = luathread;
|
||||||
}
|
}
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
final Varargs result = resume(luathread, args);
|
final Varargs result = luathread.resume(args);
|
||||||
if ( result.arg1().toboolean() ) {
|
if ( result.arg1().toboolean() ) {
|
||||||
return result.subargs(2);
|
return result.subargs(2);
|
||||||
} else {
|
} else {
|
||||||
@@ -130,19 +133,4 @@ public class CoroutineLib extends OneArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Varargs yield(Varargs args) {
|
|
||||||
final LuaThread.State s = LuaThread.getRunning().state;
|
|
||||||
if (s.function == null)
|
|
||||||
throw new LuaError("cannot yield main thread");
|
|
||||||
return s.lua_yield(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
Varargs resume(LuaThread t, Varargs args) {
|
|
||||||
final LuaThread.State s = t.state;
|
|
||||||
if (s.status > LuaThread.STATUS_SUSPENDED)
|
|
||||||
return LuaValue.varargsOf(LuaValue.FALSE,
|
|
||||||
LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine"));
|
|
||||||
return s.lua_resume(t, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package org.luaj.vm2.lib;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.Lua;
|
import org.luaj.vm2.Lua;
|
||||||
import org.luaj.vm2.LuaBoolean;
|
import org.luaj.vm2.LuaBoolean;
|
||||||
import org.luaj.vm2.LuaClosure;
|
import org.luaj.vm2.LuaClosure;
|
||||||
@@ -33,6 +34,7 @@ import org.luaj.vm2.LuaNumber;
|
|||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
import org.luaj.vm2.LuaThread;
|
||||||
|
import org.luaj.vm2.LuaUserdata;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Print;
|
import org.luaj.vm2.Print;
|
||||||
import org.luaj.vm2.Prototype;
|
import org.luaj.vm2.Prototype;
|
||||||
@@ -66,7 +68,7 @@ import org.luaj.vm2.Varargs;
|
|||||||
* @see JmePlatform
|
* @see JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.9">http://www.lua.org/manual/5.1/manual.html#5.9</a>
|
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.9">http://www.lua.org/manual/5.1/manual.html#5.9</a>
|
||||||
*/
|
*/
|
||||||
public class DebugLib extends VarArgFunction {
|
public class DebugLib extends OneArgFunction {
|
||||||
public static final boolean CALLS = (null != System.getProperty("CALLS"));
|
public static final boolean CALLS = (null != System.getProperty("CALLS"));
|
||||||
public static final boolean TRACE = (null != System.getProperty("TRACE"));
|
public static final boolean TRACE = (null != System.getProperty("TRACE"));
|
||||||
|
|
||||||
@@ -74,38 +76,6 @@ public class DebugLib extends VarArgFunction {
|
|||||||
// remove it in production builds
|
// remove it in production builds
|
||||||
public static boolean DEBUG_ENABLED;
|
public static boolean DEBUG_ENABLED;
|
||||||
|
|
||||||
static final String[] NAMES = {
|
|
||||||
"debug",
|
|
||||||
"gethook",
|
|
||||||
"getinfo",
|
|
||||||
"getlocal",
|
|
||||||
"getmetatable",
|
|
||||||
"getregistry",
|
|
||||||
"getupvalue",
|
|
||||||
"sethook",
|
|
||||||
"setlocal",
|
|
||||||
"setmetatable",
|
|
||||||
"setupvalue",
|
|
||||||
"traceback",
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int INIT = 0;
|
|
||||||
private static final int DEBUG = 1;
|
|
||||||
private static final int GETHOOK = 2;
|
|
||||||
private static final int GETINFO = 3;
|
|
||||||
private static final int GETLOCAL = 4;
|
|
||||||
private static final int GETMETATABLE = 5;
|
|
||||||
private static final int GETREGISTRY = 6;
|
|
||||||
private static final int GETUPVALUE = 7;
|
|
||||||
private static final int SETHOOK = 8;
|
|
||||||
private static final int SETLOCAL = 9;
|
|
||||||
private static final int SETMETATABLE = 10;
|
|
||||||
private static final int SETUPVALUE = 11;
|
|
||||||
private static final int TRACEBACK = 12;
|
|
||||||
|
|
||||||
/* maximum stack for a Lua function */
|
|
||||||
private static final int MAXSTACK = 250;
|
|
||||||
|
|
||||||
private static final LuaString LUA = valueOf("Lua");
|
private static final LuaString LUA = valueOf("Lua");
|
||||||
private static final LuaString JAVA = valueOf("Java");
|
private static final LuaString JAVA = valueOf("Java");
|
||||||
private static final LuaString QMARK = valueOf("?");
|
private static final LuaString QMARK = valueOf("?");
|
||||||
@@ -133,291 +103,104 @@ public class DebugLib extends VarArgFunction {
|
|||||||
private static final LuaString CURRENTLINE = valueOf("currentline");
|
private static final LuaString CURRENTLINE = valueOf("currentline");
|
||||||
private static final LuaString ACTIVELINES = valueOf("activelines");
|
private static final LuaString ACTIVELINES = valueOf("activelines");
|
||||||
|
|
||||||
public DebugLib() {
|
Globals globals;
|
||||||
}
|
|
||||||
|
|
||||||
private LuaTable init(LuaValue env) {
|
public LuaTable call(LuaValue env) {
|
||||||
|
globals = env.checkglobals();
|
||||||
|
globals.debuglib = this;
|
||||||
DEBUG_ENABLED = true;
|
DEBUG_ENABLED = true;
|
||||||
LuaTable t = new LuaTable();
|
LuaTable debug = new LuaTable();
|
||||||
bind(t, DebugLib.class, NAMES, DEBUG);
|
env.set("debug", new debug());
|
||||||
env.set("debug", t);
|
env.set("gethook", new gethook());
|
||||||
PackageLib.instance.LOADED.set("debug", t);
|
env.set("sethook", new sethook());
|
||||||
return t;
|
env.get("package").get("loaded").set("debug", debug);
|
||||||
|
return debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
// debug.debug()
|
||||||
switch ( opcode ) {
|
static final class debug extends ZeroArgFunction {
|
||||||
case INIT: return init(args.arg1());
|
public LuaValue call() {
|
||||||
case DEBUG: return _debug(args);
|
|
||||||
case GETHOOK: return _gethook(args);
|
|
||||||
case GETINFO: return _getinfo(args,this);
|
|
||||||
case GETLOCAL: return _getlocal(args);
|
|
||||||
case GETMETATABLE: return _getmetatable(args);
|
|
||||||
case GETREGISTRY: return _getregistry(args);
|
|
||||||
case GETUPVALUE: return _getupvalue(args);
|
|
||||||
case SETHOOK: return _sethook(args);
|
|
||||||
case SETLOCAL: return _setlocal(args);
|
|
||||||
case SETMETATABLE: return _setmetatable(args);
|
|
||||||
case SETUPVALUE: return _setupvalue(args);
|
|
||||||
case TRACEBACK: return _traceback(args);
|
|
||||||
default: return NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------ Debug Info management --------------------------
|
|
||||||
//
|
|
||||||
// when DEBUG_ENABLED is set to true, these functions will be called
|
|
||||||
// by Closure instances as they process bytecodes.
|
|
||||||
//
|
|
||||||
// Each thread will get a DebugState attached to it by the debug library
|
|
||||||
// which will track function calls, hook functions, etc.
|
|
||||||
//
|
|
||||||
static class DebugInfo {
|
|
||||||
LuaValue func;
|
|
||||||
LuaClosure closure;
|
|
||||||
LuaValue[] stack;
|
|
||||||
Varargs varargs, extras;
|
|
||||||
int pc, top;
|
|
||||||
|
|
||||||
private DebugInfo() {
|
|
||||||
func = NIL;
|
|
||||||
}
|
|
||||||
private DebugInfo(LuaValue func) {
|
|
||||||
pc = -1;
|
|
||||||
setfunction( func );
|
|
||||||
}
|
|
||||||
void setargs(Varargs varargs, LuaValue[] stack) {
|
|
||||||
this.varargs = varargs;
|
|
||||||
this.stack = stack;
|
|
||||||
}
|
|
||||||
void setfunction( LuaValue func ) {
|
|
||||||
this.func = func;
|
|
||||||
this.closure = (func instanceof LuaClosure? (LuaClosure) func: null);
|
|
||||||
}
|
|
||||||
void clear() {
|
|
||||||
func = NIL;
|
|
||||||
closure = null;
|
|
||||||
stack = null;
|
|
||||||
varargs = extras = null;
|
|
||||||
pc = top = 0;
|
|
||||||
}
|
|
||||||
public void bytecode(int pc, Varargs extras, int top) {
|
|
||||||
this.pc = pc;
|
|
||||||
this.top = top;
|
|
||||||
this.extras = extras;
|
|
||||||
}
|
|
||||||
public int currentline() {
|
|
||||||
if ( closure == null ) return -1;
|
|
||||||
int[] li = closure.p.lineinfo;
|
|
||||||
return li==null || pc<0 || pc>=li.length? -1: li[pc];
|
|
||||||
}
|
|
||||||
public LuaString[] getfunckind() {
|
|
||||||
if ( closure == null || pc<0 ) return null;
|
|
||||||
int stackpos = (closure.p.code[pc] >> 6) & 0xff;
|
|
||||||
return getobjname(this, pc, stackpos);
|
|
||||||
}
|
|
||||||
public String sourceline() {
|
|
||||||
if ( closure == null ) return func.tojstring();
|
|
||||||
String s = closure.p.source.tojstring();
|
|
||||||
int line = currentline();
|
|
||||||
return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line;
|
|
||||||
}
|
|
||||||
public String tracename() {
|
|
||||||
// if ( func != null )
|
|
||||||
// return func.tojstring();
|
|
||||||
LuaString[] kind = getfunckind();
|
|
||||||
if ( kind == null )
|
|
||||||
return "function ?";
|
|
||||||
return "function "+kind[0].tojstring();
|
|
||||||
}
|
|
||||||
public LuaString getlocalname(int index) {
|
|
||||||
if ( closure == null ) return null;
|
|
||||||
return closure.p.getlocalname(index, pc);
|
|
||||||
}
|
|
||||||
public String tojstring() {
|
|
||||||
return tracename()+" "+sourceline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** DebugState is associated with a Thread */
|
|
||||||
static class DebugState {
|
|
||||||
private final WeakReference thread_ref;
|
|
||||||
private int debugCalls = 0;
|
|
||||||
private DebugInfo[] debugInfo = new DebugInfo[LuaThread.MAX_CALLSTACK+1];
|
|
||||||
private LuaValue hookfunc;
|
|
||||||
private boolean hookcall,hookline,hookrtrn,inhook;
|
|
||||||
private int hookcount,hookcodes;
|
|
||||||
private int line;
|
|
||||||
DebugState(LuaThread thread) {
|
|
||||||
this.thread_ref = new WeakReference(thread);
|
|
||||||
}
|
|
||||||
public DebugInfo nextInfo() {
|
|
||||||
DebugInfo di = debugInfo[debugCalls];
|
|
||||||
if ( di == null )
|
|
||||||
debugInfo[debugCalls] = di = new DebugInfo();
|
|
||||||
return di;
|
|
||||||
}
|
|
||||||
public DebugInfo pushInfo( int calls ) {
|
|
||||||
while ( debugCalls < calls ) {
|
|
||||||
nextInfo();
|
|
||||||
++debugCalls;
|
|
||||||
}
|
|
||||||
return debugInfo[debugCalls-1];
|
|
||||||
}
|
|
||||||
public void popInfo(int calls) {
|
|
||||||
while ( debugCalls > calls )
|
|
||||||
debugInfo[--debugCalls].clear();
|
|
||||||
}
|
|
||||||
void callHookFunc(DebugState ds, LuaString type, LuaValue arg) {
|
|
||||||
if ( inhook || hookfunc == null )
|
|
||||||
return;
|
|
||||||
inhook = true;
|
|
||||||
try {
|
|
||||||
int n = debugCalls;
|
|
||||||
ds.nextInfo().setargs( arg, null );
|
|
||||||
ds.pushInfo(n+1).setfunction(hookfunc);
|
|
||||||
try {
|
|
||||||
hookfunc.call(type,arg);
|
|
||||||
} finally {
|
|
||||||
ds.popInfo(n);
|
|
||||||
}
|
|
||||||
} catch ( Exception e ) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
inhook = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void sethook(LuaValue func, boolean call, boolean line, boolean rtrn, int count) {
|
|
||||||
this.hookcount = count;
|
|
||||||
this.hookcall = call;
|
|
||||||
this.hookline = line;
|
|
||||||
this.hookrtrn = rtrn;
|
|
||||||
this.hookfunc = func;
|
|
||||||
}
|
|
||||||
DebugInfo getDebugInfo() {
|
|
||||||
try {
|
|
||||||
return debugInfo[debugCalls-1];
|
|
||||||
} catch ( Exception e ) {
|
|
||||||
if ( debugCalls <= 0 )
|
|
||||||
return debugInfo[debugCalls++] = new DebugInfo();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DebugInfo getDebugInfo(int level) {
|
|
||||||
return level < 0 || level >= debugCalls? null: debugInfo[debugCalls-level-1];
|
|
||||||
}
|
|
||||||
public DebugInfo findDebugInfo(LuaValue func) {
|
|
||||||
for ( int i=debugCalls; --i>=0; ) {
|
|
||||||
if ( debugInfo[i].func == func ) {
|
|
||||||
return debugInfo[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new DebugInfo(func);
|
|
||||||
}
|
|
||||||
public String tojstring() {
|
|
||||||
LuaThread thread = (LuaThread) thread_ref.get();
|
|
||||||
return thread != null? DebugLib.traceback(thread, 0): "orphaned thread";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static DebugState getDebugState( LuaThread thread ) {
|
|
||||||
if ( thread.debugState == null )
|
|
||||||
thread.debugState = new DebugState(thread);
|
|
||||||
return (DebugState) thread.debugState;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DebugState getDebugState() {
|
|
||||||
return getDebugState( LuaThread.getRunning() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called by Closures to set up stack and arguments to next call */
|
|
||||||
public static void debugSetupCall(Varargs args, LuaValue[] stack) {
|
|
||||||
DebugState ds = getDebugState();
|
|
||||||
if ( ds.inhook )
|
|
||||||
return;
|
|
||||||
ds.nextInfo().setargs( args, stack );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called by Closures and recursing java functions on entry
|
|
||||||
* @param thread the thread for the call
|
|
||||||
* @param calls the number of calls in the call stack
|
|
||||||
* @param func the function called
|
|
||||||
*/
|
|
||||||
public static void debugOnCall(LuaThread thread, int calls, LuaFunction func) {
|
|
||||||
DebugState ds = getDebugState();
|
|
||||||
if ( ds.inhook )
|
|
||||||
return;
|
|
||||||
DebugInfo di = ds.pushInfo(calls);
|
|
||||||
di.setfunction( func );
|
|
||||||
if(CALLS)System.out.println("calling "+func);
|
|
||||||
if ( ds.hookcall )
|
|
||||||
ds.callHookFunc( ds, CALL, LuaValue.NIL );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called by Closures and recursing java functions on return
|
|
||||||
* @param thread the thread for the call
|
|
||||||
* @param calls the number of calls in the call stack
|
|
||||||
*/
|
|
||||||
public static void debugOnReturn(LuaThread thread, int calls) {
|
|
||||||
DebugState ds = getDebugState(thread);
|
|
||||||
if ( ds.inhook )
|
|
||||||
return;
|
|
||||||
if(CALLS)System.out.println("returning");
|
|
||||||
try {
|
|
||||||
if ( ds.hookrtrn )
|
|
||||||
ds.callHookFunc( ds, RETURN, LuaValue.NIL );
|
|
||||||
} finally {
|
|
||||||
getDebugState().popInfo(calls);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called by Closures on bytecode execution */
|
|
||||||
public static void debugBytecode( int pc, Varargs extras, int top ) {
|
|
||||||
DebugState ds = getDebugState();
|
|
||||||
if ( ds.inhook )
|
|
||||||
return;
|
|
||||||
DebugInfo di = ds.getDebugInfo();
|
|
||||||
if(TRACE)Print.printState(di.closure, pc, di.stack, top, di.varargs);
|
|
||||||
di.bytecode( pc, extras, top );
|
|
||||||
if ( ds.hookcount > 0 ) {
|
|
||||||
if ( ++ds.hookcodes >= ds.hookcount ) {
|
|
||||||
ds.hookcodes = 0;
|
|
||||||
ds.callHookFunc( ds, COUNT, LuaValue.NIL );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ds.hookline ) {
|
|
||||||
int newline = di.currentline();
|
|
||||||
if ( newline != ds.line ) {
|
|
||||||
int c = di.closure.p.code[pc];
|
|
||||||
if ( (c&0x3f) != Lua.OP_JMP || ((c>>>14)-0x1ffff) >= 0 ) {
|
|
||||||
ds.line = newline;
|
|
||||||
ds.callHookFunc( ds, LINE, LuaValue.valueOf(newline) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------- library function implementations -----------------
|
|
||||||
|
|
||||||
// j2se subclass may wish to override and provide actual console here.
|
|
||||||
// j2me platform has not System.in to provide console.
|
|
||||||
static Varargs _debug(Varargs args) {
|
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Varargs _gethook(Varargs args) {
|
|
||||||
int a=1;
|
|
||||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
|
||||||
DebugState ds = getDebugState(thread);
|
|
||||||
return varargsOf(
|
|
||||||
ds.hookfunc,
|
|
||||||
valueOf((ds.hookcall?"c":"")+(ds.hookline?"l":"")+(ds.hookrtrn?"r":"")),
|
|
||||||
valueOf(ds.hookcount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Varargs _sethook(Varargs args) {
|
// debug.gethook ([thread])
|
||||||
|
final class gethook extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
LuaThread t = args.optthread(1, globals.running_thread);
|
||||||
|
return varargsOf(
|
||||||
|
t.hookfunc,
|
||||||
|
valueOf((t.hookcall?"c":"")+(t.hookline?"l":"")+(t.hookrtrn?"r":"")),
|
||||||
|
valueOf(t.hookcount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.getinfo ([thread,] f [, what])
|
||||||
|
final class getinfo extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
int a=1;
|
int a=1;
|
||||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||||
|
LuaValue func = args.optfunction(a++, null);
|
||||||
|
String what = args.optjstring(a++,"");
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.getlocal ([thread,] f, local)
|
||||||
|
final class getlocal extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
int a=1;
|
||||||
|
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||||
|
LuaValue func = args.optfunction(a++, null);
|
||||||
|
LuaValue local = args.checkvalue(a++);
|
||||||
|
return thread.globals.callstack.findCallFrame(func).getLocal(local.toint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.getmetatable (value)
|
||||||
|
final class getmetatable extends LibFunction {
|
||||||
|
public LuaValue call(LuaValue v) {
|
||||||
|
LuaValue mt = v.getmetatable();
|
||||||
|
return mt != null? mt: NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.getregistry ()
|
||||||
|
final class getregistry extends ZeroArgFunction {
|
||||||
|
public LuaValue call() {
|
||||||
|
return globals;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.getupvalue (f, up)
|
||||||
|
static final class getupvalue extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
LuaValue func = args.checkfunction(1);
|
||||||
|
int up = args.checkint(2);
|
||||||
|
if ( func instanceof LuaClosure ) {
|
||||||
|
LuaClosure c = (LuaClosure) func;
|
||||||
|
LuaString name = findupvalue(c, up);
|
||||||
|
if ( name != null ) {
|
||||||
|
return varargsOf(name, c.upValues[up-1].getValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.getuservalue (u)
|
||||||
|
static final class getuservalue extends LibFunction {
|
||||||
|
public LuaValue call(LuaValue u) {
|
||||||
|
return u.isuserdata()? u: NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// debug.sethook ([thread,] hook, mask [, count])
|
||||||
|
final class sethook extends VarArgFunction {
|
||||||
|
public Varargs call(Varargs args) {
|
||||||
|
int a=1;
|
||||||
|
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||||
LuaValue func = args.optfunction(a++, null);
|
LuaValue func = args.optfunction(a++, null);
|
||||||
String str = args.optjstring(a++,"");
|
String str = args.optjstring(a++,"");
|
||||||
int count = args.optint(a++,0);
|
int count = args.optint(a++,0);
|
||||||
@@ -428,139 +211,30 @@ public class DebugLib extends VarArgFunction {
|
|||||||
case 'l': line=true; break;
|
case 'l': line=true; break;
|
||||||
case 'r': rtrn=true; break;
|
case 'r': rtrn=true; break;
|
||||||
}
|
}
|
||||||
getDebugState(thread).sethook(func, call, line, rtrn, count);
|
thread.hookfunc = func;
|
||||||
|
thread.hookcall = call;
|
||||||
|
thread.hookline = line;
|
||||||
|
thread.hookcount = count;
|
||||||
|
thread.hookrtrn = rtrn;
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected static Varargs _getinfo(Varargs args, LuaValue level0func) {
|
// debug.setlocal ([thread,] level, local, value)
|
||||||
|
final class setlocal extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
int a=1;
|
int a=1;
|
||||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||||
LuaValue func = args.arg(a++);
|
LuaValue func = args.optfunction(a++, null);
|
||||||
String what = args.optjstring(a++, "nSluf");
|
LuaValue local = args.checkvalue(a++);
|
||||||
|
LuaValue value = args.checkvalue(a++);
|
||||||
// find the stack info
|
return thread.globals.callstack.findCallFrame(func).setLocal(local.toint(), value);
|
||||||
DebugState ds = getDebugState( thread );
|
|
||||||
DebugInfo di = null;
|
|
||||||
if ( func.isnumber() ) {
|
|
||||||
int level = func.checkint();
|
|
||||||
di = level>0?
|
|
||||||
ds.getDebugInfo(level-1):
|
|
||||||
new DebugInfo( level0func );
|
|
||||||
} else {
|
|
||||||
di = ds.findDebugInfo( func.checkfunction() );
|
|
||||||
}
|
|
||||||
if ( di == null )
|
|
||||||
return NIL;
|
|
||||||
|
|
||||||
// start a table
|
|
||||||
LuaTable info = new LuaTable();
|
|
||||||
LuaClosure c = di.closure;
|
|
||||||
for (int i = 0, j = what.length(); i < j; i++) {
|
|
||||||
switch (what.charAt(i)) {
|
|
||||||
case 'S': {
|
|
||||||
if ( c != null ) {
|
|
||||||
Prototype p = c.p;
|
|
||||||
info.set(WHAT, LUA);
|
|
||||||
info.set(SOURCE, p.source);
|
|
||||||
info.set(SHORT_SRC, valueOf(sourceshort(p)));
|
|
||||||
info.set(LINEDEFINED, valueOf(p.linedefined));
|
|
||||||
info.set(LASTLINEDEFINED, valueOf(p.lastlinedefined));
|
|
||||||
} else {
|
|
||||||
String shortName = di.func.tojstring();
|
|
||||||
LuaString name = LuaString.valueOf("[Java] "+shortName);
|
|
||||||
info.set(WHAT, JAVA);
|
|
||||||
info.set(SOURCE, name);
|
|
||||||
info.set(SHORT_SRC, valueOf(shortName));
|
|
||||||
info.set(LINEDEFINED, LuaValue.MINUSONE);
|
|
||||||
info.set(LASTLINEDEFINED, LuaValue.MINUSONE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'l': {
|
|
||||||
int line = di.currentline();
|
|
||||||
info.set( CURRENTLINE, valueOf(line) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'u': {
|
|
||||||
info.set(NUPS, valueOf(c!=null? c.p.upvalues.length: 0));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'n': {
|
|
||||||
LuaString[] kind = di.getfunckind();
|
|
||||||
info.set(NAME, kind!=null? kind[0]: QMARK);
|
|
||||||
info.set(NAMEWHAT, kind!=null? kind[1]: EMPTYSTRING);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'f': {
|
|
||||||
info.set( FUNC, di.func );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'L': {
|
|
||||||
LuaTable lines = new LuaTable();
|
|
||||||
info.set(ACTIVELINES, lines);
|
|
||||||
// if ( di.luainfo != null ) {
|
|
||||||
// int line = di.luainfo.currentline();
|
|
||||||
// if ( line >= 0 )
|
|
||||||
// lines.set(1, IntValue.valueOf(line));
|
|
||||||
// }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String sourceshort(Prototype p) {
|
|
||||||
String name = p.source.tojstring();
|
|
||||||
if ( name.startsWith("@") || name.startsWith("=") )
|
|
||||||
name = name.substring(1);
|
|
||||||
else if ( name.startsWith("\033") )
|
|
||||||
name = "binary string";
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Varargs _getlocal(Varargs args) {
|
|
||||||
int a=1;
|
|
||||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
|
||||||
int level = args.checkint(a++);
|
|
||||||
int local = args.checkint(a++);
|
|
||||||
|
|
||||||
DebugState ds = getDebugState(thread);
|
|
||||||
DebugInfo di = ds.getDebugInfo(level-1);
|
|
||||||
LuaString name = (di!=null? di.getlocalname(local): null);
|
|
||||||
if ( name != null ) {
|
|
||||||
LuaValue value = di.stack[local-1];
|
|
||||||
return varargsOf( name, value );
|
|
||||||
} else {
|
|
||||||
return NIL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Varargs _setlocal(Varargs args) {
|
// debug.setmetatable (value, table)
|
||||||
int a=1;
|
final class setmetatable extends VarArgFunction {
|
||||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
public Varargs invoke(Varargs args) {
|
||||||
int level = args.checkint(a++);
|
|
||||||
int local = args.checkint(a++);
|
|
||||||
LuaValue value = args.arg(a++);
|
|
||||||
|
|
||||||
DebugState ds = getDebugState(thread);
|
|
||||||
DebugInfo di = ds.getDebugInfo(level-1);
|
|
||||||
LuaString name = (di!=null? di.getlocalname(local): null);
|
|
||||||
if ( name != null ) {
|
|
||||||
di.stack[local-1] = value;
|
|
||||||
return name;
|
|
||||||
} else {
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LuaValue _getmetatable(Varargs args) {
|
|
||||||
LuaValue object = args.arg(1);
|
|
||||||
LuaValue mt = object.getmetatable();
|
|
||||||
return mt!=null? mt: NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Varargs _setmetatable(Varargs args) {
|
|
||||||
LuaValue object = args.arg(1);
|
LuaValue object = args.arg(1);
|
||||||
try {
|
try {
|
||||||
LuaValue mt = args.opttable(2, null);
|
LuaValue mt = args.opttable(2, null);
|
||||||
@@ -578,35 +252,11 @@ public class DebugLib extends VarArgFunction {
|
|||||||
return varargsOf(FALSE, valueOf(e.toString()));
|
return varargsOf(FALSE, valueOf(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Varargs _getregistry(Varargs args) {
|
|
||||||
return new LuaTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static LuaString findupvalue(LuaClosure c, int up) {
|
// debug.setupvalue (f, up, value)
|
||||||
if ( c.upValues != null && up > 0 && up <= c.upValues.length ) {
|
final class setupvalue extends VarArgFunction {
|
||||||
if ( c.p.upvalues != null && up <= c.p.upvalues.length )
|
public Varargs invoke(Varargs args) {
|
||||||
return c.p.upvalues[up-1].name;
|
|
||||||
else
|
|
||||||
return LuaString.valueOf( "."+up );
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Varargs _getupvalue(Varargs args) {
|
|
||||||
LuaValue func = args.checkfunction(1);
|
|
||||||
int up = args.checkint(2);
|
|
||||||
if ( func instanceof LuaClosure ) {
|
|
||||||
LuaClosure c = (LuaClosure) func;
|
|
||||||
LuaString name = findupvalue(c, up);
|
|
||||||
if ( name != null ) {
|
|
||||||
return varargsOf(name, c.upValues[up-1].getValue() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LuaValue _setupvalue(Varargs args) {
|
|
||||||
LuaValue func = args.checkfunction(1);
|
LuaValue func = args.checkfunction(1);
|
||||||
int up = args.checkint(2);
|
int up = args.checkint(2);
|
||||||
LuaValue value = args.arg(3);
|
LuaValue value = args.arg(3);
|
||||||
@@ -620,78 +270,155 @@ public class DebugLib extends VarArgFunction {
|
|||||||
}
|
}
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static LuaValue _traceback(Varargs args) {
|
// debug.setuservalue (udata, value)
|
||||||
|
final class setuservalue extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
Object o = args.checkuserdata(1);
|
||||||
|
LuaValue v = args.checkvalue(2);
|
||||||
|
LuaUserdata u = (LuaUserdata)args.arg1();
|
||||||
|
u.m_instance = v.checkuserdata();
|
||||||
|
u.m_metatable = v.getmetatable();
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug.traceback ([thread,] [message [, level]])
|
||||||
|
final class traceback extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
int a=1;
|
int a=1;
|
||||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||||
String message = args.optjstring(a++, null);
|
String message = args.optjstring(a++, null);
|
||||||
int level = args.optint(a++,1);
|
int level = args.optint(a++,1);
|
||||||
String tb = DebugLib.traceback(thread, level-1);
|
String tb = globals.callstack.traceback(level-1);
|
||||||
return valueOf(message!=null? message+"\n"+tb: tb);
|
return valueOf(message!=null? message+"\n"+tb: tb);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =================== public utilities ====================
|
// debug.upvalueid (f, n)
|
||||||
|
final class upvalueid extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
LuaValue func = args.checkfunction(1);
|
||||||
|
int up = args.checkint(2);
|
||||||
|
if ( func instanceof LuaClosure ) {
|
||||||
|
LuaClosure c = (LuaClosure) func;
|
||||||
|
if ( c.upValues != null && up > 0 && up <= c.upValues.length ) {
|
||||||
|
return userdataOf(c.upValues[up-1].hashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// debug.upvaluejoin (f1, n1, f2, n2)
|
||||||
* Get a traceback as a string for the current thread
|
final class upvaluejoin extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
LuaValue f1 = args.checkfunction(1);
|
||||||
|
int n1 = args.checkint(2);
|
||||||
|
LuaValue f2 = args.checkfunction(3);
|
||||||
|
int n2 = args.checkint(4);
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LuaString findupvalue(LuaClosure c, int up) {
|
||||||
|
if ( c.upValues != null && up > 0 && up <= c.upValues.length ) {
|
||||||
|
if ( c.p.upvalues != null && up <= c.p.upvalues.length )
|
||||||
|
return c.p.upvalues[up-1].name;
|
||||||
|
else
|
||||||
|
return LuaString.valueOf( "."+up );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------- library function implementations -----------------
|
||||||
|
protected Varargs _getinfo(Varargs args, LuaValue level0func) {
|
||||||
|
int a=1;
|
||||||
|
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||||
|
LuaValue func = args.arg(a++);
|
||||||
|
String what = args.optjstring(a++, "nSluf");
|
||||||
|
LuaThread.CallStack callstack = thread.globals.callstack;
|
||||||
|
|
||||||
|
// find the stack info
|
||||||
|
LuaThread.CallFrame frame;
|
||||||
|
if ( func.isnumber() ) {
|
||||||
|
frame = callstack.getCallFrame(func.toint());
|
||||||
|
} else {
|
||||||
|
frame = callstack.findCallFrame(func);
|
||||||
|
}
|
||||||
|
if (frame == null)
|
||||||
|
return NIL;
|
||||||
|
|
||||||
|
// start a table
|
||||||
|
LuaTable info = new LuaTable();
|
||||||
|
LuaClosure c = frame.f.isclosure()? (LuaClosure) frame.f: null;
|
||||||
|
for (int i = 0, j = what.length(); i < j; i++) {
|
||||||
|
switch (what.charAt(i)) {
|
||||||
|
case 'S': {
|
||||||
|
if ( c != null ) {
|
||||||
|
Prototype p = c.p;
|
||||||
|
info.set(WHAT, LUA);
|
||||||
|
info.set(SOURCE, p.source);
|
||||||
|
info.set(SHORT_SRC, valueOf(sourceshort(p)));
|
||||||
|
info.set(LINEDEFINED, valueOf(p.linedefined));
|
||||||
|
info.set(LASTLINEDEFINED, valueOf(p.lastlinedefined));
|
||||||
|
} else {
|
||||||
|
String shortName = frame.f.tojstring();
|
||||||
|
LuaString name = LuaString.valueOf("[Java] "+shortName);
|
||||||
|
info.set(WHAT, JAVA);
|
||||||
|
info.set(SOURCE, name);
|
||||||
|
info.set(SHORT_SRC, valueOf(shortName));
|
||||||
|
info.set(LINEDEFINED, LuaValue.MINUSONE);
|
||||||
|
info.set(LASTLINEDEFINED, LuaValue.MINUSONE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l': {
|
||||||
|
int line = frame.getLine();
|
||||||
|
info.set( CURRENTLINE, valueOf(line) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': {
|
||||||
|
info.set(NUPS, valueOf(c!=null? c.p.upvalues.length: 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'n': {
|
||||||
|
LuaString[] kind = getfunckind(frame.f);
|
||||||
|
info.set(NAME, kind!=null? kind[0]: QMARK);
|
||||||
|
info.set(NAMEWHAT, kind!=null? kind[1]: EMPTYSTRING);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f': {
|
||||||
|
info.set( FUNC, frame.f );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case 'L': {
|
||||||
|
LuaTable lines = new LuaTable();
|
||||||
|
info.set(ACTIVELINES, lines);
|
||||||
|
if ( c !+ null && c.luainfo != null ) {
|
||||||
|
int line = c.luainfo.currentline();
|
||||||
|
if ( line >= 0 )
|
||||||
|
lines.set(1, IntValue.valueOf(line));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
public static String traceback(int level) {
|
|
||||||
return traceback(LuaThread.getRunning(), level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a traceback for a particular thread.
|
|
||||||
* @param thread LuaThread to provide stack trace for
|
|
||||||
* @param level 0-based level to start reporting on
|
|
||||||
* @return String containing the stack trace.
|
|
||||||
*/
|
|
||||||
public static String traceback(LuaThread thread, int level) {
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
DebugState ds = getDebugState(thread);
|
|
||||||
sb.append( "stack traceback:" );
|
|
||||||
DebugInfo di = ds.getDebugInfo(level);
|
|
||||||
if ( di != null ) {
|
|
||||||
sb.append( "\n\t" );
|
|
||||||
sb.append( di.sourceline() );
|
|
||||||
sb.append( " in " );
|
|
||||||
while ( (di = ds.getDebugInfo(++level)) != null ) {
|
|
||||||
sb.append( di.tracename() );
|
|
||||||
sb.append( "\n\t" );
|
|
||||||
sb.append( di.sourceline() );
|
|
||||||
sb.append( " in " );
|
|
||||||
}
|
}
|
||||||
sb.append( "main chunk" );
|
return info;
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public static String sourceshort(Prototype p) {
|
||||||
* Get file and line for the nearest calling closure.
|
String name = p.source.tojstring();
|
||||||
* @return String identifying the file and line of the nearest lua closure,
|
if ( name.startsWith("@") || name.startsWith("=") )
|
||||||
* or the function name of the Java call if no closure is being called.
|
name = name.substring(1);
|
||||||
*/
|
else if ( name.startsWith("\033") )
|
||||||
public static String fileline() {
|
name = "binary string";
|
||||||
DebugState ds = getDebugState(LuaThread.getRunning());
|
return name;
|
||||||
DebugInfo di;
|
|
||||||
for ( int i=0, n=ds.debugCalls; i<n; i++ ) {
|
|
||||||
di = ds.getDebugInfo(i);
|
|
||||||
if ( di != null && di.func.isclosure() )
|
|
||||||
return di.sourceline();
|
|
||||||
}
|
|
||||||
return fileline(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get file and line for a particular level, even if it is a java function.
|
|
||||||
*
|
|
||||||
* @param level 0-based index of level to get
|
|
||||||
* @return String containing file and line info if available
|
|
||||||
*/
|
|
||||||
public static String fileline(int level) {
|
|
||||||
DebugState ds = getDebugState(LuaThread.getRunning());
|
|
||||||
DebugInfo di = ds.getDebugInfo(level);
|
|
||||||
return di!=null? di.sourceline(): null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// =======================================================
|
// =======================================================
|
||||||
@@ -700,114 +427,10 @@ public class DebugLib extends VarArgFunction {
|
|||||||
if (!x) throw new RuntimeException("lua_assert failed");
|
if (!x) throw new RuntimeException("lua_assert failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LuaString[] getfunckind(LuaFunction f) {
|
||||||
// return StrValue[] { name, namewhat } if found, null if not
|
return null;
|
||||||
static LuaString[] getobjname(DebugInfo di, int lastpc, int reg) {
|
|
||||||
if (di.closure == null)
|
|
||||||
return null; /* Not a Lua function? */
|
|
||||||
|
|
||||||
Prototype p = di.closure.p;
|
|
||||||
int pc = di.pc; // currentpc(L, ci);
|
|
||||||
LuaString name = p.getlocalname(reg + 1, pc);
|
|
||||||
if (name != null) /* is a local? */
|
|
||||||
return new LuaString[] { name, LOCAL };
|
|
||||||
|
|
||||||
/* else try symbolic execution */
|
|
||||||
pc = findsetreg(p, lastpc, reg);
|
|
||||||
if (pc != -1) { /* could find instruction? */
|
|
||||||
int i = p.code[pc];
|
|
||||||
switch (Lua.GET_OPCODE(i)) {
|
|
||||||
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(di, pc, b); /* get name for `b' */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Lua.OP_GETTABUP:
|
|
||||||
case Lua.OP_GETTABLE: {
|
|
||||||
int k = Lua.GETARG_C(i); /* key index */
|
|
||||||
int t = Lua.GETARG_Bx(i); /* table index */
|
|
||||||
LuaString vn = (Lua.GET_OPCODE(i) == Lua.OP_GETTABLE) /* name of indexed variable */
|
|
||||||
? p.getlocalname(t + 1, pc)
|
|
||||||
: (t < p.upvalues.length ? p.upvalues[t].name : QMARK);
|
|
||||||
name = kname(p, k);
|
|
||||||
return new LuaString[] { name, vn.eq_b(ENV)? GLOBAL: FIELD };
|
|
||||||
}
|
|
||||||
case Lua.OP_GETUPVAL: {
|
|
||||||
int u = Lua.GETARG_B(i); /* upvalue index */
|
|
||||||
name = u < p.upvalues.length ? p.upvalues[u].name : QMARK;
|
|
||||||
return new LuaString[] { name, UPVALUE };
|
|
||||||
}
|
|
||||||
case Lua.OP_LOADK:
|
|
||||||
case Lua.OP_LOADKX: {
|
|
||||||
int b = (Lua.GET_OPCODE(i) == Lua.OP_LOADK) ? Lua.GETARG_Bx(i)
|
|
||||||
: Lua.GETARG_Ax(p.code[pc + 1]);
|
|
||||||
if (p.k[b].isstring()) {
|
|
||||||
name = p.k[b].strvalue();
|
|
||||||
return new LuaString[] { name, CONSTANT };
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Lua.OP_SELF: {
|
|
||||||
int k = Lua.GETARG_C(i); /* key index */
|
|
||||||
name = kname(p, k);
|
|
||||||
return new LuaString[] { name, METHOD };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null; /* no useful name found */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static LuaString kname(Prototype p, int c) {
|
|
||||||
if (Lua.ISK(c) && p.k[Lua.INDEXK(c)].isstring())
|
|
||||||
return p.k[Lua.INDEXK(c)].strvalue();
|
|
||||||
else
|
|
||||||
return QMARK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean checkreg(Prototype pt,int reg) {
|
|
||||||
return (reg < pt.maxstacksize);
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean precheck(Prototype pt) {
|
|
||||||
if (!(pt.maxstacksize <= MAXSTACK)) return false;
|
|
||||||
lua_assert(pt.numparams <= pt.maxstacksize);
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean checkopenop(Prototype 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 (Prototype pt, int r, enum OpArgMask mode) {
|
|
||||||
static boolean checkArgMode (Prototype 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** try to find last instruction before 'lastpc' that modified register 'reg'
|
** try to find last instruction before 'lastpc' that modified register 'reg'
|
||||||
@@ -856,4 +479,5 @@ public class DebugLib extends VarArgFunction {
|
|||||||
return setreg;
|
return setreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
@@ -212,10 +213,10 @@ public class IoLib extends OneArgFunction {
|
|||||||
|
|
||||||
LuaTable filemethods;
|
LuaTable filemethods;
|
||||||
|
|
||||||
public IoLib() {
|
protected Globals globals;
|
||||||
}
|
|
||||||
|
|
||||||
public LuaValue call(LuaValue env) {
|
public LuaValue call(LuaValue env) {
|
||||||
|
globals = env.checkglobals();
|
||||||
|
|
||||||
// io lib functions
|
// io lib functions
|
||||||
LuaTable t = new LuaTable();
|
LuaTable t = new LuaTable();
|
||||||
@@ -237,7 +238,7 @@ public class IoLib extends OneArgFunction {
|
|||||||
|
|
||||||
// return the table
|
// return the table
|
||||||
env.set("io", t);
|
env.set("io", t);
|
||||||
PackageLib.instance.LOADED.set("io", t);
|
env.get("package").get("loaded").set("io", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class MathLib extends OneArgFunction {
|
|||||||
math.set("sqrt", new sqrt());
|
math.set("sqrt", new sqrt());
|
||||||
math.set("tan", new tan());
|
math.set("tan", new tan());
|
||||||
env.set("math", math);
|
env.set("math", math);
|
||||||
PackageLib.instance.LOADED.set("math", math);
|
env.get("package").get("loaded").set("math", math);
|
||||||
return math;
|
return math;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class OsLib extends VarArgFunction {
|
|||||||
LuaTable t = new LuaTable();
|
LuaTable t = new LuaTable();
|
||||||
bind(t, this.getClass(), NAMES, CLOCK);
|
bind(t, this.getClass(), NAMES, CLOCK);
|
||||||
env.set("os", t);
|
env.set("os", t);
|
||||||
PackageLib.instance.LOADED.set("os", t);
|
env.get("package").get("loaded").set("os", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,10 @@
|
|||||||
package org.luaj.vm2.lib;
|
package org.luaj.vm2.lib;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.luaj.vm2.LuaFunction;
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
@@ -67,14 +65,11 @@ public class PackageLib extends OneArgFunction {
|
|||||||
|
|
||||||
public static String DEFAULT_LUA_PATH = "?.lua";
|
public static String DEFAULT_LUA_PATH = "?.lua";
|
||||||
|
|
||||||
public InputStream STDIN = null;
|
Globals globals;
|
||||||
public PrintStream STDOUT = System.out;
|
|
||||||
public LuaTable LOADED;
|
public LuaTable LOADED;
|
||||||
public LuaTable PACKAGE;
|
public LuaTable PACKAGE;
|
||||||
|
|
||||||
/** Most recent instance of PackageLib */
|
|
||||||
public static PackageLib instance;
|
|
||||||
|
|
||||||
/** Loader that loads from preload table if found there */
|
/** Loader that loads from preload table if found there */
|
||||||
public LuaValue preload_searcher;
|
public LuaValue preload_searcher;
|
||||||
|
|
||||||
@@ -101,11 +96,10 @@ public class PackageLib extends OneArgFunction {
|
|||||||
|
|
||||||
private static final String FILE_SEP = System.getProperty("file.separator");
|
private static final String FILE_SEP = System.getProperty("file.separator");
|
||||||
|
|
||||||
public PackageLib() {
|
public PackageLib() {}
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LuaValue call(LuaValue env) {
|
public LuaValue call(LuaValue env) {
|
||||||
|
globals = env.checkglobals();
|
||||||
env.set("require", new PkgLib1("require",OP_REQUIRE,this));
|
env.set("require", new PkgLib1("require",OP_REQUIRE,this));
|
||||||
env.set( "package", PACKAGE=tableOf( new LuaValue[] {
|
env.set( "package", PACKAGE=tableOf( new LuaValue[] {
|
||||||
_LOADED, LOADED=tableOf(),
|
_LOADED, LOADED=tableOf(),
|
||||||
@@ -284,7 +278,7 @@ public class PackageLib extends OneArgFunction {
|
|||||||
LuaString filename = v.arg1().strvalue();
|
LuaString filename = v.arg1().strvalue();
|
||||||
|
|
||||||
// Try to load the file.
|
// Try to load the file.
|
||||||
v = BaseLib.loadFile(filename.tojstring(), "bt", LuaValue._G);
|
v = globals.loadFile(filename.tojstring());
|
||||||
if ( v.arg1().isfunction() )
|
if ( v.arg1().isfunction() )
|
||||||
return LuaValue.varargsOf(v.arg1(), filename);
|
return LuaValue.varargsOf(v.arg1(), filename);
|
||||||
|
|
||||||
@@ -316,7 +310,7 @@ public class PackageLib extends OneArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try opening the file
|
// try opening the file
|
||||||
InputStream is = BaseLib.FINDER.findResource(filename);
|
InputStream is = globals.FINDER.findResource(filename);
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
try { is.close(); } catch ( java.io.IOException ioe ) {}
|
try { is.close(); } catch ( java.io.IOException ioe ) {}
|
||||||
return valueOf(filename);
|
return valueOf(filename);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class StringLib extends OneArgFunction {
|
|||||||
instance = t;
|
instance = t;
|
||||||
if ( LuaString.s_metatable == null )
|
if ( LuaString.s_metatable == null )
|
||||||
LuaString.s_metatable = tableOf( new LuaValue[] { INDEX, t } );
|
LuaString.s_metatable = tableOf( new LuaValue[] { INDEX, t } );
|
||||||
PackageLib.instance.LOADED.set("string", t);
|
env.get("package").get("loaded").set("string", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,16 +67,12 @@ import org.luaj.vm2.lib.LibFunction;
|
|||||||
*/
|
*/
|
||||||
public class JmeIoLib extends IoLib {
|
public class JmeIoLib extends IoLib {
|
||||||
|
|
||||||
public JmeIoLib() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected File wrapStdin() throws IOException {
|
protected File wrapStdin() throws IOException {
|
||||||
return new FileImpl(BaseLib.instance.STDIN);
|
return new FileImpl(globals.STDIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File wrapStdout() throws IOException {
|
protected File wrapStdout() throws IOException {
|
||||||
return new FileImpl(BaseLib.instance.STDOUT);
|
return new FileImpl(globals.STDOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
package org.luaj.vm2.lib.jme;
|
package org.luaj.vm2.lib.jme;
|
||||||
|
|
||||||
import org.luaj.vm2.compiler.LuaC;
|
import org.luaj.vm2.compiler.LuaC;
|
||||||
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LoadState;
|
import org.luaj.vm2.LoadState;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
import org.luaj.vm2.LuaThread;
|
||||||
@@ -53,7 +54,7 @@ import org.luaj.vm2.lib.TableLib;
|
|||||||
* <p>
|
* <p>
|
||||||
* A simple example of initializing globals and using them from Java is:
|
* A simple example of initializing globals and using them from Java is:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* LuaValue _G = JmePlatform.standardGlobals();
|
* Globals _G = JmePlatform.standardGlobals();
|
||||||
* _G.get("print").call(LuaValue.valueOf("hello, world"));
|
* _G.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* } </pre>
|
||||||
* <p>
|
* <p>
|
||||||
@@ -71,6 +72,7 @@ import org.luaj.vm2.lib.TableLib;
|
|||||||
* <p>
|
* <p>
|
||||||
* The standard globals will contain all standard libraries in their JME flavors:
|
* The standard globals will contain all standard libraries in their JME flavors:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
* <li>{@link Globals}</li>
|
||||||
* <li>{@link BaseLib}</li>
|
* <li>{@link BaseLib}</li>
|
||||||
* <li>{@link PackageLib}</li>
|
* <li>{@link PackageLib}</li>
|
||||||
* <li>{@link Bit32Lib}</li>
|
* <li>{@link Bit32Lib}</li>
|
||||||
@@ -101,9 +103,8 @@ public class JmePlatform {
|
|||||||
* @see JsePlatform
|
* @see JsePlatform
|
||||||
* @see JmePlatform
|
* @see JmePlatform
|
||||||
*/
|
*/
|
||||||
public static LuaTable standardGlobals() {
|
public static Globals standardGlobals() {
|
||||||
LuaTable _G = new LuaTable();
|
Globals _G = new Globals();
|
||||||
LuaValue._G = _G;
|
|
||||||
_G.load(new BaseLib());
|
_G.load(new BaseLib());
|
||||||
_G.load(new PackageLib());
|
_G.load(new PackageLib());
|
||||||
_G.load(new Bit32Lib());
|
_G.load(new Bit32Lib());
|
||||||
@@ -114,6 +115,7 @@ public class JmePlatform {
|
|||||||
_G.load(new CoroutineLib());
|
_G.load(new CoroutineLib());
|
||||||
_G.load(new JmeIoLib());
|
_G.load(new JmeIoLib());
|
||||||
LuaC.install();
|
LuaC.install();
|
||||||
|
_G.compiler = LuaC.instance;
|
||||||
return _G;
|
return _G;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +127,8 @@ public class JmePlatform {
|
|||||||
* @see JmePlatform
|
* @see JmePlatform
|
||||||
* @see DebugLib
|
* @see DebugLib
|
||||||
*/
|
*/
|
||||||
public static LuaTable debugGlobals() {
|
public static Globals debugGlobals() {
|
||||||
LuaTable _G = standardGlobals();
|
Globals _G = standardGlobals();
|
||||||
_G.load(new DebugLib());
|
_G.load(new DebugLib());
|
||||||
return _G;
|
return _G;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,11 +67,14 @@ import org.luaj.vm2.lib.ResourceFinder;
|
|||||||
|
|
||||||
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
||||||
|
|
||||||
/** Construct a JSE base library instance */
|
/** Extend the library loading to set the default value for {@link Globals.STDIN} */
|
||||||
public JseBaseLib() {
|
public LuaValue call(LuaValue env) {
|
||||||
STDIN = System.in;
|
super.call(env);
|
||||||
|
env.checkglobals().STDIN = System.in;
|
||||||
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to open a file in the current working directory,
|
* Try to open a file in the current working directory,
|
||||||
* or fall back to base opener if not found.
|
* or fall back to base opener if not found.
|
||||||
|
|||||||
@@ -67,16 +67,12 @@ import org.luaj.vm2.lib.LibFunction;
|
|||||||
*/
|
*/
|
||||||
public class JseIoLib extends IoLib {
|
public class JseIoLib extends IoLib {
|
||||||
|
|
||||||
public JseIoLib() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected File wrapStdin() throws IOException {
|
protected File wrapStdin() throws IOException {
|
||||||
return new FileImpl(BaseLib.instance.STDIN);
|
return new FileImpl(globals.STDIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File wrapStdout() throws IOException {
|
protected File wrapStdout() throws IOException {
|
||||||
return new FileImpl(BaseLib.instance.STDOUT);
|
return new FileImpl(globals.STDOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
||||||
|
|||||||
@@ -21,14 +21,16 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.lib.jse;
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
import org.luaj.vm2.compiler.LuaC;
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
import org.luaj.vm2.LuaThread;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
|
import org.luaj.vm2.compiler.LuaC;
|
||||||
import org.luaj.vm2.lib.Bit32Lib;
|
import org.luaj.vm2.lib.Bit32Lib;
|
||||||
import org.luaj.vm2.lib.CoroutineLib;
|
import org.luaj.vm2.lib.CoroutineLib;
|
||||||
import org.luaj.vm2.lib.DebugLib;
|
import org.luaj.vm2.lib.DebugLib;
|
||||||
import org.luaj.vm2.lib.PackageLib;
|
import org.luaj.vm2.lib.PackageLib;
|
||||||
|
import org.luaj.vm2.lib.ResourceFinder;
|
||||||
import org.luaj.vm2.lib.StringLib;
|
import org.luaj.vm2.lib.StringLib;
|
||||||
import org.luaj.vm2.lib.TableLib;
|
import org.luaj.vm2.lib.TableLib;
|
||||||
|
|
||||||
@@ -40,13 +42,13 @@ import org.luaj.vm2.lib.TableLib;
|
|||||||
* <p>
|
* <p>
|
||||||
* A simple example of initializing globals and using them from Java is:
|
* A simple example of initializing globals and using them from Java is:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* LuaValue _G = JsePlatform.standardGlobals();
|
* Globals _G = JsePlatform.standardGlobals();
|
||||||
* _G.get("print").call(LuaValue.valueOf("hello, world"));
|
* _G.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* } </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* Once globals are created, a simple way to load and run a script is:
|
* Once globals are created, a simple way to load and run a script is:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
|
* _G.load( new FileInputStream("main.lua"), "main.lua" ).call();
|
||||||
* } </pre>
|
* } </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* although {@code require} could also be used:
|
* although {@code require} could also be used:
|
||||||
@@ -58,6 +60,7 @@ import org.luaj.vm2.lib.TableLib;
|
|||||||
* <p>
|
* <p>
|
||||||
* The standard globals will contain all standard libraries plus {@code luajava}:
|
* The standard globals will contain all standard libraries plus {@code luajava}:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
* <li>{@link Globals}</li>
|
||||||
* <li>{@link JseBaseLib}</li>
|
* <li>{@link JseBaseLib}</li>
|
||||||
* <li>{@link PackageLib}</li>
|
* <li>{@link PackageLib}</li>
|
||||||
* <li>{@link Bit32Lib}</li>
|
* <li>{@link Bit32Lib}</li>
|
||||||
@@ -87,9 +90,8 @@ public class JsePlatform {
|
|||||||
* @see JsePlatform
|
* @see JsePlatform
|
||||||
* @see JmePlatform
|
* @see JmePlatform
|
||||||
*/
|
*/
|
||||||
public static LuaTable standardGlobals() {
|
public static Globals standardGlobals() {
|
||||||
LuaTable _G = new LuaTable();
|
Globals _G = new Globals();
|
||||||
LuaValue._G = _G;
|
|
||||||
_G.load(new JseBaseLib());
|
_G.load(new JseBaseLib());
|
||||||
_G.load(new PackageLib());
|
_G.load(new PackageLib());
|
||||||
_G.load(new Bit32Lib());
|
_G.load(new Bit32Lib());
|
||||||
@@ -101,6 +103,7 @@ public class JsePlatform {
|
|||||||
_G.load(new JseOsLib());
|
_G.load(new JseOsLib());
|
||||||
_G.load(new LuajavaLib());
|
_G.load(new LuajavaLib());
|
||||||
LuaC.install();
|
LuaC.install();
|
||||||
|
_G.compiler = LuaC.instance;
|
||||||
return _G;
|
return _G;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +115,8 @@ public class JsePlatform {
|
|||||||
* @see JmePlatform
|
* @see JmePlatform
|
||||||
* @see DebugLib
|
* @see DebugLib
|
||||||
*/
|
*/
|
||||||
public static LuaTable debugGlobals() {
|
public static Globals debugGlobals() {
|
||||||
LuaTable _G = standardGlobals();
|
Globals _G = standardGlobals();
|
||||||
_G.load(new DebugLib());
|
_G.load(new DebugLib());
|
||||||
return _G;
|
return _G;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
LuaTable t = new LuaTable();
|
LuaTable t = new LuaTable();
|
||||||
bind( t, LuajavaLib.class, NAMES, BINDCLASS );
|
bind( t, LuajavaLib.class, NAMES, BINDCLASS );
|
||||||
env.set("luajava", t);
|
env.set("luajava", t);
|
||||||
PackageLib.instance.LOADED.set("luajava", t);
|
env.get("package").get("loaded").set("luajava", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
case BINDCLASS: {
|
case BINDCLASS: {
|
||||||
|
|||||||
@@ -35,18 +35,14 @@ public class JavaLoader extends ClassLoader {
|
|||||||
public JavaLoader() {
|
public JavaLoader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaFunction load( Prototype p, String classname, String filename ) {
|
public LuaFunction load( Prototype p, String classname, String filename, LuaValue env ) {
|
||||||
JavaGen jg = new JavaGen( p, classname, filename );
|
JavaGen jg = new JavaGen( p, classname, filename );
|
||||||
return load( jg );
|
return load( jg, env );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaFunction load( JavaGen jg ) {
|
public LuaFunction load( JavaGen jg, LuaValue env ) {
|
||||||
include( jg );
|
include( jg );
|
||||||
return load( jg.classname );
|
return load( jg.classname, env );
|
||||||
}
|
|
||||||
|
|
||||||
public LuaFunction load(String classname) {
|
|
||||||
return load(classname, LuaValue._G);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaFunction load(String classname, LuaValue env) {
|
public LuaFunction load(String classname, LuaValue env) {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class LuaJC implements LuaCompiler {
|
|||||||
String classname = toStandardJavaClassName( name );
|
String classname = toStandardJavaClassName( name );
|
||||||
String luaname = toStandardLuaFileName( name );
|
String luaname = toStandardLuaFileName( name );
|
||||||
JavaLoader loader = new JavaLoader();
|
JavaLoader loader = new JavaLoader();
|
||||||
return loader.load(p, classname, luaname);
|
return loader.load(p, classname, luaname, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toStandardJavaClassName( String luachunkname ) {
|
private static String toStandardJavaClassName( String luachunkname ) {
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ package org.luaj.vm2;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.luaj.vm2.compiler.LuaC;
|
|
||||||
import org.luaj.vm2.lib.BaseLib;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test argument type check errors
|
* Test argument type check errors
|
||||||
@@ -47,7 +44,7 @@ public class ErrorsTest extends ScriptDrivenTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testBaseLibArgs() {
|
public void testBaseLibArgs() {
|
||||||
BaseLib.instance.STDIN = new InputStream() {
|
globals.STDIN = new InputStream() {
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,15 +64,15 @@ public class FragmentsTest extends TestSuite {
|
|||||||
public void runFragment( Varargs expected, String script ) {
|
public void runFragment( Varargs expected, String script ) {
|
||||||
try {
|
try {
|
||||||
String name = getName();
|
String name = getName();
|
||||||
org.luaj.vm2.lib.jse.JsePlatform.debugGlobals();
|
Globals _G = org.luaj.vm2.lib.jse.JsePlatform.debugGlobals();
|
||||||
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
|
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
|
||||||
LuaValue chunk ;
|
LuaValue chunk ;
|
||||||
switch ( TEST_TYPE ) {
|
switch ( TEST_TYPE ) {
|
||||||
case TEST_TYPE_LUAJC:
|
case TEST_TYPE_LUAJC:
|
||||||
chunk = LuaJC.getInstance().load(is,name,LuaValue._G);
|
chunk = LuaJC.getInstance().load(is,name,_G);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
chunk = LuaC.instance.load( is, name, LuaValue._G );
|
chunk = LuaC.instance.load( is, name, _G );
|
||||||
Print.print(((LuaClosure)chunk).p);
|
Print.print(((LuaClosure)chunk).p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class LuaOperationsTest extends TestCase {
|
|||||||
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
|
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
|
||||||
private final LuaTable table = LuaValue.listOf( new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") } );
|
private final LuaTable table = LuaValue.listOf( new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") } );
|
||||||
private final LuaValue somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
private final LuaValue somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
||||||
private final LuaThread thread = new LuaThread(somefunc);
|
private final LuaThread thread = new LuaThread(new Globals(), somefunc);
|
||||||
private final Prototype proto = new Prototype(1);
|
private final Prototype proto = new Prototype(1);
|
||||||
private final LuaClosure someclosure = new LuaClosure(proto,table);
|
private final LuaClosure someclosure = new LuaClosure(proto,table);
|
||||||
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
|
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
|
||||||
@@ -146,7 +146,7 @@ public class LuaOperationsTest extends TestCase {
|
|||||||
// set up suitable environments for execution
|
// set up suitable environments for execution
|
||||||
LuaValue aaa = LuaValue.valueOf("aaa");
|
LuaValue aaa = LuaValue.valueOf("aaa");
|
||||||
LuaValue eee = LuaValue.valueOf("eee");
|
LuaValue eee = LuaValue.valueOf("eee");
|
||||||
LuaTable _G = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals();
|
final Globals _G = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals();
|
||||||
LuaTable newenv = LuaValue.tableOf( new LuaValue[] {
|
LuaTable newenv = LuaValue.tableOf( new LuaValue[] {
|
||||||
LuaValue.valueOf("a"), LuaValue.valueOf("aaa"),
|
LuaValue.valueOf("a"), LuaValue.valueOf("aaa"),
|
||||||
LuaValue.valueOf("b"), LuaValue.valueOf("bbb"), } );
|
LuaValue.valueOf("b"), LuaValue.valueOf("bbb"), } );
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ public class MetatableTest extends TestCase {
|
|||||||
private final LuaValue string = LuaValue.valueOf(samplestring);
|
private final LuaValue string = LuaValue.valueOf(samplestring);
|
||||||
private final LuaTable table = LuaValue.tableOf();
|
private final LuaTable table = LuaValue.tableOf();
|
||||||
private final LuaFunction function = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
private final LuaFunction function = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
||||||
private final LuaThread thread = new LuaThread(function);
|
private final LuaThread thread = new LuaThread(new Globals(), function);
|
||||||
private final LuaClosure closure = new LuaClosure(new Prototype());
|
private final LuaClosure closure = new LuaClosure(new Prototype(), new LuaTable());
|
||||||
private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject);
|
private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject);
|
||||||
private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata,table);
|
private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata,table);
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.luaj.vm2.lib.jse.JsePlatform;
|
|||||||
|
|
||||||
public class OrphanedThreadTest extends TestCase {
|
public class OrphanedThreadTest extends TestCase {
|
||||||
|
|
||||||
|
Globals globals;
|
||||||
LuaThread luathread;
|
LuaThread luathread;
|
||||||
WeakReference luathr_ref;
|
WeakReference luathr_ref;
|
||||||
LuaValue function;
|
LuaValue function;
|
||||||
@@ -113,7 +114,8 @@ public class OrphanedThreadTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doTest(LuaValue status2, LuaValue value2) throws Exception {
|
private void doTest(LuaValue status2, LuaValue value2) throws Exception {
|
||||||
luathread = new LuaThread(function);
|
globals = JsePlatform.standardGlobals();
|
||||||
|
luathread = new LuaThread(globals, function);
|
||||||
luathr_ref = new WeakReference(luathread);
|
luathr_ref = new WeakReference(luathread);
|
||||||
func_ref = new WeakReference(function);
|
func_ref = new WeakReference(function);
|
||||||
assertNotNull(luathr_ref.get());
|
assertNotNull(luathr_ref.get());
|
||||||
@@ -142,40 +144,40 @@ public class OrphanedThreadTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class NormalFunction extends OneArgFunction {
|
class NormalFunction extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
System.out.println("in normal.1, arg is "+arg);
|
System.out.println("in normal.1, arg is "+arg);
|
||||||
arg = LuaThread.yield(ONE).arg1();
|
arg = globals.yield(ONE).arg1();
|
||||||
System.out.println("in normal.2, arg is "+arg);
|
System.out.println("in normal.2, arg is "+arg);
|
||||||
arg = LuaThread.yield(ZERO).arg1();
|
arg = globals.yield(ZERO).arg1();
|
||||||
System.out.println("in normal.3, arg is "+arg);
|
System.out.println("in normal.3, arg is "+arg);
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EarlyCompletionFunction extends OneArgFunction {
|
class EarlyCompletionFunction extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
System.out.println("in early.1, arg is "+arg);
|
System.out.println("in early.1, arg is "+arg);
|
||||||
arg = LuaThread.yield(ONE).arg1();
|
arg = globals.yield(ONE).arg1();
|
||||||
System.out.println("in early.2, arg is "+arg);
|
System.out.println("in early.2, arg is "+arg);
|
||||||
return ZERO;
|
return ZERO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AbnormalFunction extends OneArgFunction {
|
class AbnormalFunction extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
System.out.println("in abnormal.1, arg is "+arg);
|
System.out.println("in abnormal.1, arg is "+arg);
|
||||||
arg = LuaThread.yield(ONE).arg1();
|
arg = globals.yield(ONE).arg1();
|
||||||
System.out.println("in abnormal.2, arg is "+arg);
|
System.out.println("in abnormal.2, arg is "+arg);
|
||||||
error("abnormal condition");
|
error("abnormal condition");
|
||||||
return ZERO;
|
return ZERO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ClosureFunction extends OneArgFunction {
|
class ClosureFunction extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
System.out.println("in abnormal.1, arg is "+arg);
|
System.out.println("in abnormal.1, arg is "+arg);
|
||||||
arg = LuaThread.yield(ONE).arg1();
|
arg = globals.yield(ONE).arg1();
|
||||||
System.out.println("in abnormal.2, arg is "+arg);
|
System.out.println("in abnormal.2, arg is "+arg);
|
||||||
error("abnormal condition");
|
error("abnormal condition");
|
||||||
return ZERO;
|
return ZERO;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
|
|||||||
|
|
||||||
private final PlatformType platform;
|
private final PlatformType platform;
|
||||||
private final String subdir;
|
private final String subdir;
|
||||||
private LuaTable _G;
|
protected Globals globals;
|
||||||
|
|
||||||
static final String zipdir = "test/lua/";
|
static final String zipdir = "test/lua/";
|
||||||
static final String zipfile = "luaj3.0-tests.zip";
|
static final String zipfile = "luaj3.0-tests.zip";
|
||||||
@@ -63,10 +63,10 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
|
|||||||
default:
|
default:
|
||||||
case JSE:
|
case JSE:
|
||||||
case LUAJIT:
|
case LUAJIT:
|
||||||
_G = org.luaj.vm2.lib.jse.JsePlatform.debugGlobals();
|
globals = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals();
|
||||||
break;
|
break;
|
||||||
case JME:
|
case JME:
|
||||||
_G = org.luaj.vm2.lib.jme.JmePlatform.debugGlobals();
|
globals = org.luaj.vm2.lib.jme.JmePlatform.standardGlobals();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
|
|||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
initGlobals();
|
initGlobals();
|
||||||
BaseLib.FINDER = this;
|
globals.FINDER = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceFinder implementation.
|
// ResourceFinder implementation.
|
||||||
@@ -147,13 +147,13 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
|
|||||||
try {
|
try {
|
||||||
// override print()
|
// override print()
|
||||||
final ByteArrayOutputStream output = new ByteArrayOutputStream();
|
final ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
final PrintStream oldps = BaseLib.instance.STDOUT;
|
final PrintStream oldps = globals.STDOUT;
|
||||||
final PrintStream ps = new PrintStream( output );
|
final PrintStream ps = new PrintStream( output );
|
||||||
BaseLib.instance.STDOUT = ps;
|
globals.STDOUT = ps;
|
||||||
|
|
||||||
// run the script
|
// run the script
|
||||||
try {
|
try {
|
||||||
LuaValue chunk = loadScript(testName, _G);
|
LuaValue chunk = loadScript(testName, globals);
|
||||||
chunk.call(LuaValue.valueOf(platform.toString()));
|
chunk.call(LuaValue.valueOf(platform.toString()));
|
||||||
|
|
||||||
ps.flush();
|
ps.flush();
|
||||||
@@ -164,7 +164,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
|
|||||||
|
|
||||||
assertEquals(expectedOutput, actualOutput);
|
assertEquals(expectedOutput, actualOutput);
|
||||||
} finally {
|
} finally {
|
||||||
BaseLib.instance.STDOUT = oldps;
|
globals.STDOUT = oldps;
|
||||||
ps.close();
|
ps.close();
|
||||||
}
|
}
|
||||||
} catch ( IOException ioe ) {
|
} catch ( IOException ioe ) {
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ public class TypeTest extends TestCase {
|
|||||||
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
|
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
|
||||||
private final LuaTable table = LuaValue.tableOf();
|
private final LuaTable table = LuaValue.tableOf();
|
||||||
private final LuaFunction somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
private final LuaFunction somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
||||||
private final LuaThread thread = new LuaThread(somefunc);
|
private final LuaThread thread = new LuaThread(new Globals(), somefunc);
|
||||||
private final LuaClosure someclosure = new LuaClosure(new Prototype());
|
private final LuaClosure someclosure = new LuaClosure(new Prototype(), new LuaTable());
|
||||||
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
|
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
|
||||||
private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata);
|
private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user