Improve error and traceback reporting.

This commit is contained in:
James Roseborough
2010-05-08 23:50:51 +00:00
parent 482b6056a1
commit 8d16726e8b
5 changed files with 79 additions and 49 deletions

View File

@@ -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();

View File

@@ -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 );
}
/**

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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