diff --git a/src/core/org/luaj/compiler/LexState.java b/src/core/org/luaj/compiler/LexState.java index 2114b95d..07782342 100644 --- a/src/core/org/luaj/compiler/LexState.java +++ b/src/core/org/luaj/compiler/LexState.java @@ -33,6 +33,7 @@ import org.luaj.vm.LPrototype; import org.luaj.vm.LString; import org.luaj.vm.LocVars; import org.luaj.vm.Lua; +import org.luaj.vm.LuaErrorException; public class LexState { @@ -257,7 +258,7 @@ public class LexState { L.pushfstring( cid+":"+linenumber+": "+msg ); if ( token != 0 ) L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) ); - throw new RuntimeException(cid+":"+linenumber+": "+msg); + throw new LuaErrorException(cid+":"+linenumber+": "+msg); } String chunkid( String source ) { diff --git a/src/core/org/luaj/compiler/LuaC.java b/src/core/org/luaj/compiler/LuaC.java index 06a5e817..78735416 100644 --- a/src/core/org/luaj/compiler/LuaC.java +++ b/src/core/org/luaj/compiler/LuaC.java @@ -32,6 +32,7 @@ import org.luaj.vm.LValue; import org.luaj.vm.LoadState; import org.luaj.vm.LocVars; import org.luaj.vm.Lua; +import org.luaj.vm.LuaErrorException; import org.luaj.vm.Platform; import org.luaj.vm.LoadState.LuaCompiler; @@ -50,7 +51,7 @@ public class LuaC extends Lua implements LuaCompiler { } 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; @@ -172,7 +173,7 @@ public class LuaC extends Lua implements LuaCompiler { /** Compile source bytes into a LPrototype. * * 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. * 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, * or an exception is thrown if there is an error. * @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 { Reader r = Platform.getInstance().createReader( stream ); diff --git a/src/core/org/luaj/lib/BaseLib.java b/src/core/org/luaj/lib/BaseLib.java index 7dfc3337..7c87600e 100644 --- a/src/core/org/luaj/lib/BaseLib.java +++ b/src/core/org/luaj/lib/BaseLib.java @@ -20,6 +20,7 @@ import org.luaj.vm.LString; import org.luaj.vm.LTable; import org.luaj.vm.LValue; import org.luaj.vm.Lua; +import org.luaj.vm.LuaErrorException; import org.luaj.vm.LuaState; import org.luaj.vm.Platform; @@ -289,7 +290,7 @@ public class BaseLib extends LFunction { } else { // This is supposed to set the environment of the current // "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) { - throw new java.lang.RuntimeException("next() not supported yet"); + throw new LuaErrorException("next() not supported yet"); } diff --git a/src/core/org/luaj/vm/LThread.java b/src/core/org/luaj/vm/LThread.java index 350dc26f..d1a21329 100644 --- a/src/core/org/luaj/vm/LThread.java +++ b/src/core/org/luaj/vm/LThread.java @@ -81,7 +81,7 @@ public class LThread extends LValue implements Runnable { public boolean yield() { synchronized ( this ) { if ( status != STATUS_RUNNING ) - throw new RuntimeException(this+" not running"); + threadVm.error(this+" not running"); status = STATUS_SUSPENDED; this.notify(); try { @@ -89,7 +89,7 @@ public class LThread extends LValue implements Runnable { status = STATUS_RUNNING; } catch ( InterruptedException e ) { status = STATUS_DEAD; - throw new RuntimeException(this+" "+e); + threadVm.error(this+" "+e); } return false; } diff --git a/src/core/org/luaj/vm/LValue.java b/src/core/org/luaj/vm/LValue.java index 5c2ebc64..593a6934 100644 --- a/src/core/org/luaj/vm/LValue.java +++ b/src/core/org/luaj/vm/LValue.java @@ -32,11 +32,11 @@ public class LValue { public static final LString TM_NEWINDEX = new LString("__newindex"); protected static LValue luaUnsupportedOperation() { - throw new java.lang.RuntimeException( "not supported" ); + throw new LuaErrorException( "not supported" ); } protected void luaConversionError(String target) { - throw new java.lang.RuntimeException( "bad conversion: "+luaGetTypeName()+" to "+target ); + throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target ); } diff --git a/src/core/org/luaj/vm/LuaErrorException.java b/src/core/org/luaj/vm/LuaErrorException.java new file mode 100644 index 00000000..2ca4f92c --- /dev/null +++ b/src/core/org/luaj/vm/LuaErrorException.java @@ -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); + } + +} diff --git a/src/core/org/luaj/vm/LuaState.java b/src/core/org/luaj/vm/LuaState.java index b756275e..b2ec26a1 100644 --- a/src/core/org/luaj/vm/LuaState.java +++ b/src/core/org/luaj/vm/LuaState.java @@ -94,8 +94,6 @@ public class LuaState extends Lua { // main debug hook, overridden by DebugStackState protected void debugHooks(int pc) { } - protected void debugPcallError(Throwable t) { - } protected void debugAssert(boolean b) { } @@ -377,7 +375,6 @@ public class LuaState extends Lua { return 0; } catch ( Throwable t ) { - debugPcallError( t ); this.base = oldbase; this.cc = oldcc; closeUpVals(oldtop); /* close eventual pending closures */ @@ -709,8 +706,8 @@ public class LuaState extends Lua { if (this.stack[base].luaStackCall(this)) { return; } - } catch (RuntimeException e) { - // in case of error, we need to restore cc so that + } catch (LuaErrorException e) { + // in case of lua error, we need to restore cc so that // the debug can get the correct location where the error // occured. cc++; @@ -898,7 +895,7 @@ public class LuaState extends Lua { //=============================================================== 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; } - /** + /** + * 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. * 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. * - * In the java implementation this throws a RuntimeException, possibly filling - * line number information first. + * In the java implementation this throws a LuaErrorException + * after filling line number information first when level > 0. */ 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. * - * In the java implementation this throws a RuntimeException, possibly filling - * line number information first. + * In the java implementation this calls error(message,1) */ public void error(String message) { - throw new RuntimeException( message ); + error( message, 1 ); } /** @@ -955,7 +983,7 @@ public class LuaState extends Lua { */ public void error() { String message = tostring(-1); - pop(1); + // pop(1); error( message ); } @@ -1624,7 +1652,7 @@ public class LuaState extends Lua { throw new java.lang.IllegalArgumentException("stack values cannot be null"); try { stack[top] = value; - } catch ( java.lang.RuntimeException arrayIndexOutOfBounds ) { + } catch ( java.lang.ArrayIndexOutOfBoundsException aiobe ) { checkstack( LUA_MINSTACK ); stack[top] = value; } finally { diff --git a/src/debug/org/luaj/debug/DebugLuaState.java b/src/debug/org/luaj/debug/DebugLuaState.java index a5c47ca2..beb533f7 100644 --- a/src/debug/org/luaj/debug/DebugLuaState.java +++ b/src/debug/org/luaj/debug/DebugLuaState.java @@ -92,32 +92,7 @@ public class DebugLuaState extends LuaState implements DebugRequestListener { 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) { error(message, 1); } @@ -285,16 +260,6 @@ public class DebugLuaState extends LuaState implements DebugRequestListener { 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 ------------------- public void handleRequest(DebugRequest request) { diff --git a/src/j2se/org/luaj/lib/j2se/LuajavaLib.java b/src/j2se/org/luaj/lib/j2se/LuajavaLib.java index 15ad3b51..30d48b19 100644 --- a/src/j2se/org/luaj/lib/j2se/LuajavaLib.java +++ b/src/j2se/org/luaj/lib/j2se/LuajavaLib.java @@ -39,6 +39,7 @@ import org.luaj.vm.LFunction; import org.luaj.vm.LTable; import org.luaj.vm.LUserData; import org.luaj.vm.LValue; +import org.luaj.vm.LuaErrorException; import org.luaj.vm.LuaState; @@ -84,7 +85,7 @@ public final class LuajavaLib extends LFunction { vm.settop(0); vm.pushlvalue( new LInstance( clazz, clazz ) ); } catch (Exception e) { - throw new RuntimeException(e); + throw new LuaErrorException(e); } break; case NEWINSTANCE: @@ -104,7 +105,7 @@ public final class LuajavaLib extends LFunction { vm.pushlvalue( new LInstance( o, clazz ) ); } catch (Exception e) { - throw new RuntimeException(e); + throw new LuaErrorException(e); } break; default: @@ -153,7 +154,7 @@ public final class LuajavaLib extends LFunction { } catch (NoSuchFieldException nsfe) { vm.pushlvalue( new LMethod(m_instance,clazz,s) ); } catch (Exception e) { - throw new RuntimeException(e); + throw new LuaErrorException(e); } } 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); vm.settop(0); } 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) ); return false; } catch (Exception e) { - throw new RuntimeException(e); + throw new LuaErrorException(e); } } }