Improve error handling, introduce lua stack trace processing.
This commit is contained in:
@@ -6,6 +6,7 @@ package lua;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import lua.value.LBoolean;
|
||||
import lua.value.LFunction;
|
||||
import lua.value.LNil;
|
||||
import lua.value.LTable;
|
||||
@@ -71,8 +72,13 @@ final class Builtin extends LFunction {
|
||||
vm.setResult( vm.getArg(0).luaGetType() );
|
||||
break;
|
||||
case PCALL:
|
||||
// TODO: implement pcall
|
||||
vm.setResult( LNil.NIL );
|
||||
if ( 0 != vm.lua_pcall( vm.getArgCount()-1, Lua.LUA_MULTRET ) ) {
|
||||
LValue v = vm.getArg(0);
|
||||
vm.setResult( LBoolean.FALSE );
|
||||
vm.push( v );
|
||||
} else {
|
||||
vm.setResult( LBoolean.TRUE );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
luaUnsupportedOperation();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package lua;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import lua.io.Closure;
|
||||
import lua.value.LNil;
|
||||
import lua.value.LString;
|
||||
import lua.value.LValue;
|
||||
|
||||
@@ -140,17 +143,40 @@ public interface VM {
|
||||
*/
|
||||
public void setResult(LValue val);
|
||||
|
||||
|
||||
/**
|
||||
* Generates a Lua error. The error message(which can actually be a Lua value of any type)
|
||||
* must be on the top of the stack.
|
||||
*/
|
||||
public void lua_error();
|
||||
|
||||
/**
|
||||
* Set up an error result on the stack.
|
||||
* @param value the LValue to return as the first return value
|
||||
* @param message the String error message to supply
|
||||
*/
|
||||
public void setErrorResult(LValue value, String message);
|
||||
|
||||
// ====================== lua Java API =======================
|
||||
|
||||
/**
|
||||
* Raises an error. The message is pushed onto the stack and used as the error message.
|
||||
* It also adds at the beginning of the message the file name and the line number where
|
||||
* the error occurred, if this information is available.
|
||||
* the error occurred, if this information is available.
|
||||
*
|
||||
* In the java implementation this throws a RuntimeException, possibly filling
|
||||
* line number information first.
|
||||
*/
|
||||
public void luaL_error(String message);
|
||||
public void lua_error(String message);
|
||||
|
||||
/**
|
||||
* Run the method on the stack in protected mode.
|
||||
* @param nArgs number of arguments on the stack
|
||||
* @param nResults number of results on the stack
|
||||
* @return 0 if successful, LUA_ERRMEM if no memory, LUA_ERRRUN for any other error
|
||||
*/
|
||||
public int lua_pcall(int nArgs, int nResults);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param is InputStream providing the data to be loaded
|
||||
* @param chunkname Name of the chunk to be used in debugging
|
||||
* @return 0 if successful, LUA_ERRMEM if no memory, LUA_ERRSYNTAX for i/o or any other errors
|
||||
*/
|
||||
public int lua_load( InputStream is, String chunkname );
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@ import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import lua.CallInfo;
|
||||
import lua.Print;
|
||||
import lua.StackState;
|
||||
import lua.io.LocVars;
|
||||
import lua.io.Proto;
|
||||
|
||||
public class DebugStackState extends StackState implements DebugRequestListener {
|
||||
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
public Map<Integer,Boolean> breakpoints = new HashMap<Integer,Boolean>();
|
||||
private boolean exiting = false;
|
||||
private boolean suspended = false;
|
||||
@@ -19,6 +23,47 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
||||
public DebugStackState() {
|
||||
}
|
||||
|
||||
private String getFileLine(int cindex) {
|
||||
String func = "?";
|
||||
String line = "?";
|
||||
String source = "?";
|
||||
if ( cindex >= 0 ) {
|
||||
CallInfo call = this.calls[cindex];
|
||||
Proto p = call.closure.p;
|
||||
if ( p != null && p.source != null )
|
||||
source = p.source.toJavaString();
|
||||
if ( p.lineinfo != null && p.lineinfo.length > call.pc )
|
||||
line = String.valueOf( p.lineinfo[call.pc] );
|
||||
// TODO: reverse lookup on function name ????
|
||||
func = call.closure.luaAsString().toJavaString();
|
||||
}
|
||||
return source+":"+line+"("+func+")";
|
||||
}
|
||||
|
||||
|
||||
// override and fill in line number info
|
||||
public void lua_error(String message) {
|
||||
super.lua_error( getFileLine(cc)+": "+message );
|
||||
}
|
||||
|
||||
private void printLuaTrace() {
|
||||
System.out.println( "Lua location: "+getFileLine(cc) );
|
||||
for ( int cindex=cc-1; cindex>=0; cindex-- )
|
||||
System.out.println( "\tin "+getFileLine( cindex ) );
|
||||
}
|
||||
|
||||
// intercept exceptions and fill in line numbers
|
||||
public void exec() {
|
||||
try {
|
||||
super.exec();
|
||||
} catch ( Exception t ) {
|
||||
t.printStackTrace();
|
||||
printLuaTrace();
|
||||
System.out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// debug hooks
|
||||
public void debugHooks( int pc ) {
|
||||
if ( exiting )
|
||||
|
||||
@@ -196,6 +196,8 @@ public class LoadState {
|
||||
Proto f = new Proto();
|
||||
// this.L.push(f);
|
||||
f.source = loadString();
|
||||
if ( f.source == null )
|
||||
f.source = p;
|
||||
f.linedefined = loadInt();
|
||||
f.lastlinedefined = loadInt();
|
||||
f.nups = loadByte();
|
||||
|
||||
@@ -33,7 +33,7 @@ public class LValue {
|
||||
// perform a lua call, return true if the call is to a lua function, false
|
||||
// if it ran to completion.
|
||||
public boolean luaStackCall(VM vm) {
|
||||
luaUnsupportedOperation();
|
||||
vm.lua_error("attempt to call "+this);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user