Introduce LuaErrorException which is thrown and caught when a lua error() needs to be processed.

This commit is contained in:
James Roseborough
2007-11-15 00:49:02 +00:00
parent 7e22487624
commit abad119a5c
9 changed files with 133 additions and 66 deletions

View File

@@ -33,6 +33,7 @@ import org.luaj.vm.LPrototype;
import org.luaj.vm.LString; import org.luaj.vm.LString;
import org.luaj.vm.LocVars; import org.luaj.vm.LocVars;
import org.luaj.vm.Lua; import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
public class LexState { public class LexState {
@@ -257,7 +258,7 @@ public class LexState {
L.pushfstring( cid+":"+linenumber+": "+msg ); L.pushfstring( cid+":"+linenumber+": "+msg );
if ( token != 0 ) if ( token != 0 )
L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) ); L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) );
throw new RuntimeException(cid+":"+linenumber+": "+msg); throw new LuaErrorException(cid+":"+linenumber+": "+msg);
} }
String chunkid( String source ) { String chunkid( String source ) {

View File

@@ -32,6 +32,7 @@ import org.luaj.vm.LValue;
import org.luaj.vm.LoadState; import org.luaj.vm.LoadState;
import org.luaj.vm.LocVars; import org.luaj.vm.LocVars;
import org.luaj.vm.Lua; import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.Platform; import org.luaj.vm.Platform;
import org.luaj.vm.LoadState.LuaCompiler; import org.luaj.vm.LoadState.LuaCompiler;
@@ -50,7 +51,7 @@ public class LuaC extends Lua implements LuaCompiler {
} }
protected static void _assert(boolean b) { protected static void _assert(boolean b) {
if (!b) throw new RuntimeException("assert failed"); if (!b) throw new LuaErrorException("compiler assert failed");
} }
public static final int MAXSTACK = 250; public static final int MAXSTACK = 250;
@@ -172,7 +173,7 @@ public class LuaC extends Lua implements LuaCompiler {
/** Compile source bytes into a LPrototype. /** Compile source bytes into a LPrototype.
* *
* Try to compile the file, and return the Prototype on success, * Try to compile the file, and return the Prototype on success,
* or throw RuntimeException on syntax error or I/O Exception * or throw LuaErrorException on syntax error or I/O Exception
* *
* @param firstByte the first byte from the InputStream. * @param firstByte the first byte from the InputStream.
* This can be read by the client and tested to see if it is already a binary chunk. * This can be read by the client and tested to see if it is already a binary chunk.
@@ -182,7 +183,7 @@ public class LuaC extends Lua implements LuaCompiler {
* a LPrototype instance if it can be compiled, * a LPrototype instance if it can be compiled,
* or an exception is thrown if there is an error. * or an exception is thrown if there is an error.
* @throws IOException if an I/O exception occurs * @throws IOException if an I/O exception occurs
* @throws RuntimeException if there is a syntax error. * @throws LuaErrorException if there is a syntax error.
*/ */
public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException { public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException {
Reader r = Platform.getInstance().createReader( stream ); Reader r = Platform.getInstance().createReader( stream );

View File

@@ -20,6 +20,7 @@ import org.luaj.vm.LString;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
import org.luaj.vm.LValue; import org.luaj.vm.LValue;
import org.luaj.vm.Lua; import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState; import org.luaj.vm.LuaState;
import org.luaj.vm.Platform; import org.luaj.vm.Platform;
@@ -289,7 +290,7 @@ public class BaseLib extends LFunction {
} else { } else {
// This is supposed to set the environment of the current // This is supposed to set the environment of the current
// "thread". But, we have not implemented coroutines yet. // "thread". But, we have not implemented coroutines yet.
throw new RuntimeException( "not implemented" ); throw new LuaErrorException( "not implemented" );
} }
} }
@@ -440,7 +441,7 @@ public class BaseLib extends LFunction {
} }
private LValue next(LuaState vm, LValue table, int index) { private LValue next(LuaState vm, LValue table, int index) {
throw new java.lang.RuntimeException("next() not supported yet"); throw new LuaErrorException("next() not supported yet");
} }

View File

@@ -81,7 +81,7 @@ public class LThread extends LValue implements Runnable {
public boolean yield() { public boolean yield() {
synchronized ( this ) { synchronized ( this ) {
if ( status != STATUS_RUNNING ) if ( status != STATUS_RUNNING )
throw new RuntimeException(this+" not running"); threadVm.error(this+" not running");
status = STATUS_SUSPENDED; status = STATUS_SUSPENDED;
this.notify(); this.notify();
try { try {
@@ -89,7 +89,7 @@ public class LThread extends LValue implements Runnable {
status = STATUS_RUNNING; status = STATUS_RUNNING;
} catch ( InterruptedException e ) { } catch ( InterruptedException e ) {
status = STATUS_DEAD; status = STATUS_DEAD;
throw new RuntimeException(this+" "+e); threadVm.error(this+" "+e);
} }
return false; return false;
} }

View File

@@ -32,11 +32,11 @@ public class LValue {
public static final LString TM_NEWINDEX = new LString("__newindex"); public static final LString TM_NEWINDEX = new LString("__newindex");
protected static LValue luaUnsupportedOperation() { protected static LValue luaUnsupportedOperation() {
throw new java.lang.RuntimeException( "not supported" ); throw new LuaErrorException( "not supported" );
} }
protected void luaConversionError(String target) { protected void luaConversionError(String target) {
throw new java.lang.RuntimeException( "bad conversion: "+luaGetTypeName()+" to "+target ); throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target );
} }

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright (c) 2007 LuaJ. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm;
/**
* RuntimeException that is thrown and caught in response to a lua error.
* This error does not indicate any problem with the normal functioning
* of the Lua VM, but rather indicates that the lua script being interpreted
* has encountered a lua error, eigher via LuaState.error() or lua error() calls.
*
*/
public class LuaErrorException extends RuntimeException {
private static final String DEFAULT_MESSAGE = "lua error";
/**
* Construct a LuaErrorException with the default message.
*/
public LuaErrorException() {
super(DEFAULT_MESSAGE);
}
/**
* Construct a LuaErrorException with a specific message.
*
* @param message message to supply
*/
public LuaErrorException(String message) {
super(message);
}
/**
* Construct a LuaErrorException in response to a Throwable that was caught
* and with the default message.
*/
public LuaErrorException(Throwable cause) {
super(DEFAULT_MESSAGE, cause);
}
/**
* Construct a LuaErrorException in response to a Throwable that was caught
* and with a specific message.
*
* @param message message to supply
* @param cause
*/
public LuaErrorException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -94,8 +94,6 @@ public class LuaState extends Lua {
// main debug hook, overridden by DebugStackState // main debug hook, overridden by DebugStackState
protected void debugHooks(int pc) { protected void debugHooks(int pc) {
} }
protected void debugPcallError(Throwable t) {
}
protected void debugAssert(boolean b) { protected void debugAssert(boolean b) {
} }
@@ -377,7 +375,6 @@ public class LuaState extends Lua {
return 0; return 0;
} catch ( Throwable t ) { } catch ( Throwable t ) {
debugPcallError( t );
this.base = oldbase; this.base = oldbase;
this.cc = oldcc; this.cc = oldcc;
closeUpVals(oldtop); /* close eventual pending closures */ closeUpVals(oldtop); /* close eventual pending closures */
@@ -709,8 +706,8 @@ public class LuaState extends Lua {
if (this.stack[base].luaStackCall(this)) { if (this.stack[base].luaStackCall(this)) {
return; return;
} }
} catch (RuntimeException e) { } catch (LuaErrorException e) {
// in case of error, we need to restore cc so that // in case of lua error, we need to restore cc so that
// the debug can get the correct location where the error // the debug can get the correct location where the error
// occured. // occured.
cc++; cc++;
@@ -898,7 +895,7 @@ public class LuaState extends Lua {
//=============================================================== //===============================================================
private void notImplemented() { private void notImplemented() {
throw new java.lang.RuntimeException("AbstractStack: not yet implemented"); throw new LuaErrorException("AbstractStack: not yet implemented");
} }
/** /**
@@ -922,26 +919,57 @@ public class LuaState extends Lua {
return f; return f;
} }
/**
* Returns the current program counter for the given call frame.
* @param ci -- A call frame
* @return the current program counter for the given call frame.
*/
protected int getCurrentPc(CallInfo ci) {
int pc = (ci != calls[cc] ? ci.pc - 1 : ci.pc);
return pc;
}
/**
* Get the file line number info for a particular call frame.
* @param cindex
* @return
*/
protected String getFileLine(int cindex) {
String source = "?";
String line = "";
if (cindex >= 0) {
CallInfo call = this.calls[cindex];
LPrototype p = call.closure.p;
if (p != null && p.source != null)
source = p.source.toJavaString();
int pc = getCurrentPc(call);
if (p.lineinfo != null && p.lineinfo.length > pc)
line = ":" + String.valueOf(p.lineinfo[pc]);
}
return source + line;
}
/** /**
* Raises an error. The message is pushed onto the stack and used as the error message. * 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 * 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 * In the java implementation this throws a LuaErrorException
* line number information first. * after filling line number information first when level > 0.
*/ */
public void error(String message, int level) { public void error(String message, int level) {
error( message ); if ( level > 0 )
message = getFileLine(cc + 1 - level) + ": " + message;
throw new LuaErrorException( message );
} }
/** /**
* Raises an error with the default level. * Raises an error with the default level.
* *
* In the java implementation this throws a RuntimeException, possibly filling * In the java implementation this calls error(message,1)
* line number information first.
*/ */
public void error(String message) { public void error(String message) {
throw new RuntimeException( message ); error( message, 1 );
} }
/** /**
@@ -955,7 +983,7 @@ public class LuaState extends Lua {
*/ */
public void error() { public void error() {
String message = tostring(-1); String message = tostring(-1);
pop(1); // pop(1);
error( message ); error( message );
} }
@@ -1624,7 +1652,7 @@ public class LuaState extends Lua {
throw new java.lang.IllegalArgumentException("stack values cannot be null"); throw new java.lang.IllegalArgumentException("stack values cannot be null");
try { try {
stack[top] = value; stack[top] = value;
} catch ( java.lang.RuntimeException arrayIndexOutOfBounds ) { } catch ( java.lang.ArrayIndexOutOfBoundsException aiobe ) {
checkstack( LUA_MINSTACK ); checkstack( LUA_MINSTACK );
stack[top] = value; stack[top] = value;
} finally { } finally {

View File

@@ -92,31 +92,6 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
error("assert failure"); error("assert failure");
} }
private String getFileLine(int cindex) {
String func = "?";
String line = "?";
String source = "?";
if (cindex >= 0) {
CallInfo call = this.calls[cindex];
LPrototype p = call.closure.p;
if (p != null && p.source != null)
source = p.source.toJavaString();
int pc = getCurrentPc(call);
if (p.lineinfo != null && p.lineinfo.length > pc)
line = String.valueOf(p.lineinfo[pc]);
// TODO: reverse lookup on function name ????
func = call.closure.toJavaString();
}
return source + ":" + line + "(" + func + ")";
}
// override and fill in line number info
public void error(String message, int level) {
super.error(level <= 0 ?
message :
getFileLine(cc + 1 - level) + ": " + message);
}
// use line numbers by default // use line numbers by default
public void error(String message) { public void error(String message) {
error(message, 1); error(message, 1);
@@ -285,16 +260,6 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
return line; return line;
} }
/**
* Returns the current program counter for the given call frame.
* @param ci -- A call frame
* @return the current program counter for the given call frame.
*/
private int getCurrentPc(CallInfo ci) {
int pc = (ci != calls[cc] ? ci.pc - 1 : ci.pc);
return pc;
}
// ------------------ commands coming from the debugger ------------------- // ------------------ commands coming from the debugger -------------------
public void handleRequest(DebugRequest request) { public void handleRequest(DebugRequest request) {

View File

@@ -39,6 +39,7 @@ import org.luaj.vm.LFunction;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
import org.luaj.vm.LUserData; import org.luaj.vm.LUserData;
import org.luaj.vm.LValue; import org.luaj.vm.LValue;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState; import org.luaj.vm.LuaState;
@@ -84,7 +85,7 @@ public final class LuajavaLib extends LFunction {
vm.settop(0); vm.settop(0);
vm.pushlvalue( new LInstance( clazz, clazz ) ); vm.pushlvalue( new LInstance( clazz, clazz ) );
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new LuaErrorException(e);
} }
break; break;
case NEWINSTANCE: case NEWINSTANCE:
@@ -104,7 +105,7 @@ public final class LuajavaLib extends LFunction {
vm.pushlvalue( new LInstance( o, clazz ) ); vm.pushlvalue( new LInstance( o, clazz ) );
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new LuaErrorException(e);
} }
break; break;
default: default:
@@ -153,7 +154,7 @@ public final class LuajavaLib extends LFunction {
} catch (NoSuchFieldException nsfe) { } catch (NoSuchFieldException nsfe) {
vm.pushlvalue( new LMethod(m_instance,clazz,s) ); vm.pushlvalue( new LMethod(m_instance,clazz,s) );
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new LuaErrorException(e);
} }
} }
public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) { public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) {
@@ -165,7 +166,7 @@ public final class LuajavaLib extends LFunction {
f.set(m_instance,v); f.set(m_instance,v);
vm.settop(0); vm.settop(0);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new LuaErrorException(e);
} }
} }
@@ -203,7 +204,7 @@ public final class LuajavaLib extends LFunction {
vm.pushlvalue( CoerceJavaToLua.coerce(result) ); vm.pushlvalue( CoerceJavaToLua.coerce(result) );
return false; return false;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new LuaErrorException(e);
} }
} }
} }