Improve error and traceback reporting.
This commit is contained in:
@@ -431,13 +431,9 @@ public class LuaClosure extends LuaFunction {
|
||||
}
|
||||
}
|
||||
} catch ( LuaError le ) {
|
||||
if ( p.lineinfo!=null && p.lineinfo.length>=pc )
|
||||
le.addTracebackLine(p.source+":"+p.lineinfo[pc-1]);
|
||||
throw le;
|
||||
} catch ( Throwable t ) {
|
||||
LuaError le = new LuaError(t);
|
||||
if ( p.lineinfo!=null && p.lineinfo.length>=pc )
|
||||
le.addTracebackLine(p.source+":"+p.lineinfo[pc-1]);
|
||||
throw le;
|
||||
} finally {
|
||||
LuaThread.onReturn();
|
||||
|
||||
@@ -23,6 +23,8 @@ package org.luaj.vm2;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.luaj.vm2.lib.DebugLib;
|
||||
|
||||
/**
|
||||
* RuntimeException that is thrown and caught in response to a lua error.
|
||||
* This error does not indicate any problem with the normal functioning
|
||||
@@ -34,7 +36,7 @@ public class LuaError extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private LuaValue msgvalue = null;
|
||||
private Vector traceback = null;
|
||||
private String traceback;
|
||||
|
||||
/** Run the error hook if there is one */
|
||||
private static String errorHook(String msg) {
|
||||
@@ -62,8 +64,9 @@ public class LuaError extends RuntimeException {
|
||||
* All errors generated from lua code should throw LuaError(String) instead.
|
||||
*/
|
||||
public LuaError(Throwable cause) {
|
||||
this( errorHook( "vm error: "+cause ) );
|
||||
super( errorHook( addFileLine( "vm error: "+cause ) ) );
|
||||
this.cause = cause;
|
||||
this.traceback = DebugLib.traceback(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +76,8 @@ public class LuaError extends RuntimeException {
|
||||
* @param message message to supply
|
||||
*/
|
||||
public LuaError(String message) {
|
||||
super( errorHook( message ) );
|
||||
super( errorHook( addFileLine( message ) ) );
|
||||
this.traceback = DebugLib.traceback(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,38 +86,35 @@ public class LuaError extends RuntimeException {
|
||||
*/
|
||||
public LuaError(String message, int level) {
|
||||
super( errorHook( addFileLine( message, level ) ) );
|
||||
this.traceback = DebugLib.traceback(1);
|
||||
}
|
||||
|
||||
/** Add file and line info to a message */
|
||||
/** Add file and line info to a message at a particular level */
|
||||
private static String addFileLine( String message, int level ) {
|
||||
if ( message == null ) return message;
|
||||
LuaFunction f = LuaThread.getCallstackFunction(level);
|
||||
return f!=null? f+": "+message: message;
|
||||
if ( message == null ) return null;
|
||||
if ( level == 0 ) return message;
|
||||
String fileline = DebugLib.fileline(level-1);
|
||||
return fileline!=null? fileline+": "+message: message;
|
||||
}
|
||||
|
||||
/** Get the message, including source line info if there is any */
|
||||
public String getMessage() {
|
||||
String msg = super.getMessage();
|
||||
return msg!=null && traceback!=null? traceback.elementAt(0)+": "+msg: msg;
|
||||
/** Add file and line info for the nearest enclosing closure */
|
||||
private static String addFileLine( String message ) {
|
||||
if ( message == null ) return null;
|
||||
String fileline = DebugLib.fileline();
|
||||
return fileline!=null? fileline+": "+message: message;
|
||||
}
|
||||
|
||||
/** Add a line of traceback info */
|
||||
public void addTracebackLine( String line ) {
|
||||
if ( traceback == null ) {
|
||||
traceback = new Vector();
|
||||
}
|
||||
traceback.addElement( line );
|
||||
}
|
||||
// /** Get the message, including source line info if there is any */
|
||||
// public String getMessage() {
|
||||
// String msg = super.getMessage();
|
||||
// return msg!=null && traceback!=null? traceback+": "+msg: msg;
|
||||
// }
|
||||
|
||||
/** Print the message and stack trace */
|
||||
public void printStackTrace() {
|
||||
System.out.println( toString() );
|
||||
if ( traceback != null ) {
|
||||
for ( int i=0,n=traceback.size(); i<n; i++ ) {
|
||||
System.out.print("\t");
|
||||
System.out.println(traceback.elementAt(i));
|
||||
}
|
||||
}
|
||||
if ( traceback != null )
|
||||
System.out.println( traceback );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -351,7 +351,7 @@ public class LuaValue extends Varargs {
|
||||
if ((!res.isnil()) || (tm = t.metatag(INDEX)).isnil())
|
||||
return res;
|
||||
} else if ((tm = t.metatag(INDEX)).isnil())
|
||||
t.typerror("index");
|
||||
t.typerror("table");
|
||||
if (tm.isfunction())
|
||||
return tm.call(t, key);
|
||||
t = tm;
|
||||
|
||||
@@ -190,7 +190,7 @@ public class DebugLib extends VarArgFunction {
|
||||
int stackpos = (closure.p.code[pc] >> 6) & 0xff;
|
||||
return getobjname(this, stackpos);
|
||||
}
|
||||
public Object sourceline() {
|
||||
public String sourceline() {
|
||||
if ( closure == null ) return func.tojstring();
|
||||
String s = closure.p.source.tojstring();
|
||||
int line = currentline();
|
||||
@@ -209,7 +209,7 @@ public class DebugLib extends VarArgFunction {
|
||||
return closure.p.getlocalname(index, pc);
|
||||
}
|
||||
public String tojstring() {
|
||||
return sourceline()+": in "+tracename();
|
||||
return tracename()+" "+sourceline();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,10 +605,10 @@ public class DebugLib extends VarArgFunction {
|
||||
static LuaValue _traceback(Varargs args) {
|
||||
int a=1;
|
||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
|
||||
String message = args.optjstring(a++, "stack traceback:");
|
||||
String message = args.optjstring(a++, null);
|
||||
int level = args.optint(a++,1);
|
||||
String tb = DebugLib.traceback(thread, level);
|
||||
return valueOf(message+"\n"+tb);
|
||||
String tb = DebugLib.traceback(thread, level-1);
|
||||
return valueOf(message!=null? message+"\n"+tb: tb);
|
||||
}
|
||||
|
||||
// =================== public utilities ====================
|
||||
@@ -622,26 +622,59 @@ public class DebugLib extends VarArgFunction {
|
||||
|
||||
/**
|
||||
* Get a traceback for a particular thread.
|
||||
* @param thread
|
||||
* @param level
|
||||
* @return
|
||||
* @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);
|
||||
DebugInfo di;
|
||||
for ( int i=level, n=ds.debugCalls; i<n; i++ ) {
|
||||
di = ds.getDebugInfo(i);
|
||||
if ( di != null ) {
|
||||
sb.append( "\t" );
|
||||
sb.append( di.tojstring() );
|
||||
if ( i<n )
|
||||
sb.append( "\n" );
|
||||
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 sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get file and line for the nearest calling closure.
|
||||
* @return String identifying the file and line of the nearest lua closure,
|
||||
* or the function name of the Java call if no closure is being called.
|
||||
*/
|
||||
public static String fileline() {
|
||||
DebugState ds = getDebugState(LuaThread.getRunning());
|
||||
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
|
||||
*/
|
||||
public static String fileline(int level) {
|
||||
DebugState ds = getDebugState(LuaThread.getRunning());
|
||||
DebugInfo di = ds.getDebugInfo(level);
|
||||
return di!=null? di.sourceline(): null;
|
||||
}
|
||||
|
||||
// =======================================================
|
||||
|
||||
static void lua_assert(boolean x) {
|
||||
|
||||
@@ -64,7 +64,7 @@ public class lua {
|
||||
public static void main( String[] args ) throws IOException {
|
||||
|
||||
// new lua state
|
||||
_G = JsePlatform.standardGlobals();
|
||||
_G = JsePlatform.debugGlobals();
|
||||
LuaC.install();
|
||||
|
||||
// process args
|
||||
|
||||
Reference in New Issue
Block a user