Commit bdcc2e93 authored by capresti's avatar capresti
Browse files

Further fixes from Bastian:

- Added IsExecuting variable to Lua
- Fix for error info inclusion of line number (Issue #4)


git-svn-id: http://luainterface.googlecode.com/svn/trunk@14 63eb109e-e254-0410-a61e-ed0b8f8614f5
parent 75f46254
...@@ -189,24 +189,19 @@ namespace LuaInterface ...@@ -189,24 +189,19 @@ namespace LuaInterface
/// <summary> /// <summary>
/// Assuming we have a Lua error string sitting on the stack, throw a C# exception out to the user's app /// Assuming we have a Lua error string sitting on the stack, throw a C# exception out to the user's app
/// </summary> /// </summary>
/// <exception cref="LuaScriptException">Thrown if the script caused an exception</exception>
void ThrowExceptionFromError(int oldTop) void ThrowExceptionFromError(int oldTop)
{ {
object err = translator.getObject(luaState, -1); object err = translator.getObject(luaState, -1);
LuaDLL.lua_settop(luaState, oldTop); LuaDLL.lua_settop(luaState, oldTop);
Exception ex = err as Exception; // A pre-wrapped exception - just rethrow it (stack trace of InnerException will be preserved)
LuaScriptException luaEx = err as LuaScriptException;
if (luaEx != null) throw luaEx;
// A true Lua error, best interpreted as a string - wrap it in a LuaException and rethrow. // A non-wrapped Lua error (best interpreted as a string) - wrap it and throw it
if (ex == null) if (err == null) err = "Unknown Lua Error";
{ throw new LuaScriptException(err.ToString(), "");
if (err == null)
err = "Unknown Lua Error";
throw new LuaException(err.ToString());
}
// If the 'error' on the stack is an actual C# exception, wrap and rethrow it to preserve the stack trace
throw new LuaException(".NET exception occured", ex);
} }
...@@ -231,6 +226,13 @@ namespace LuaInterface ...@@ -231,6 +226,13 @@ namespace LuaInterface
return 0; return 0;
} }
private bool executing;
/// <summary>
/// True while a script is being executed
/// </summary>
public bool IsExecuting { get { return executing; } }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
...@@ -240,9 +242,15 @@ namespace LuaInterface ...@@ -240,9 +242,15 @@ namespace LuaInterface
public LuaFunction LoadString(string chunk, string name) public LuaFunction LoadString(string chunk, string name)
{ {
int oldTop = LuaDLL.lua_gettop(luaState); int oldTop = LuaDLL.lua_gettop(luaState);
if (LuaDLL.luaL_loadbuffer(luaState, chunk, name) != 0)
ThrowExceptionFromError(oldTop); executing = true;
try
{
if (LuaDLL.luaL_loadbuffer(luaState, chunk, name) != 0)
ThrowExceptionFromError(oldTop);
}
finally { executing = false; }
LuaFunction result = translator.getFunction(luaState, -1); LuaFunction result = translator.getFunction(luaState, -1);
translator.popValues(luaState, oldTop); translator.popValues(luaState, oldTop);
...@@ -274,14 +282,19 @@ namespace LuaInterface ...@@ -274,14 +282,19 @@ namespace LuaInterface
public object[] DoString(string chunk) public object[] DoString(string chunk)
{ {
int oldTop=LuaDLL.lua_gettop(luaState); int oldTop=LuaDLL.lua_gettop(luaState);
if(LuaDLL.luaL_loadbuffer(luaState,chunk,"chunk")==0) if (LuaDLL.luaL_loadbuffer(luaState, chunk, "chunk") == 0)
{ {
if (LuaDLL.lua_pcall(luaState, 0, -1, 0) == 0) executing = true;
return translator.popValues(luaState, oldTop); try
else {
ThrowExceptionFromError(oldTop); if (LuaDLL.lua_pcall(luaState, 0, -1, 0) == 0)
} return translator.popValues(luaState, oldTop);
else else
ThrowExceptionFromError(oldTop);
}
finally { executing = false; }
}
else
ThrowExceptionFromError(oldTop); ThrowExceptionFromError(oldTop);
return null; // Never reached - keeps compiler happy return null; // Never reached - keeps compiler happy
...@@ -296,12 +309,17 @@ namespace LuaInterface ...@@ -296,12 +309,17 @@ namespace LuaInterface
public object[] DoString(string chunk, string chunkName) public object[] DoString(string chunk, string chunkName)
{ {
int oldTop = LuaDLL.lua_gettop(luaState); int oldTop = LuaDLL.lua_gettop(luaState);
executing = true;
if (LuaDLL.luaL_loadbuffer(luaState, chunk, chunkName) == 0) if (LuaDLL.luaL_loadbuffer(luaState, chunk, chunkName) == 0)
{ {
if (LuaDLL.lua_pcall(luaState, 0, -1, 0) == 0) try
return translator.popValues(luaState, oldTop); {
else if (LuaDLL.lua_pcall(luaState, 0, -1, 0) == 0)
ThrowExceptionFromError(oldTop); return translator.popValues(luaState, oldTop);
else
ThrowExceptionFromError(oldTop);
}
finally { executing = false; }
} }
else else
ThrowExceptionFromError(oldTop); ThrowExceptionFromError(oldTop);
...@@ -318,10 +336,15 @@ namespace LuaInterface ...@@ -318,10 +336,15 @@ namespace LuaInterface
int oldTop=LuaDLL.lua_gettop(luaState); int oldTop=LuaDLL.lua_gettop(luaState);
if(LuaDLL.luaL_loadfile(luaState,fileName)==0) if(LuaDLL.luaL_loadfile(luaState,fileName)==0)
{ {
if (LuaDLL.lua_pcall(luaState, 0, -1, 0) == 0) executing = true;
return translator.popValues(luaState, oldTop); try
else {
ThrowExceptionFromError(oldTop); if (LuaDLL.lua_pcall(luaState, 0, -1, 0) == 0)
return translator.popValues(luaState, oldTop);
else
ThrowExceptionFromError(oldTop);
}
finally { executing = false; }
} }
else else
ThrowExceptionFromError(oldTop); ThrowExceptionFromError(oldTop);
...@@ -577,10 +600,15 @@ namespace LuaInterface ...@@ -577,10 +600,15 @@ namespace LuaInterface
{ {
translator.push(luaState,args[i]); translator.push(luaState,args[i]);
} }
} }
int error = LuaDLL.lua_pcall(luaState, nArgs, -1, 0); executing = true;
if (error != 0) try
ThrowExceptionFromError(oldTop); {
int error = LuaDLL.lua_pcall(luaState, nArgs, -1, 0);
if (error != 0)
ThrowExceptionFromError(oldTop);
}
finally { executing = false; }
if(returnTypes != null) if(returnTypes != null)
return translator.popValues(luaState,oldTop,returnTypes); return translator.popValues(luaState,oldTop,returnTypes);
...@@ -659,7 +687,7 @@ namespace LuaInterface ...@@ -659,7 +687,7 @@ namespace LuaInterface
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
private LuaHookFunction hookCallback = null; private LuaHookFunction hookCallback = null;
/// <summary> /// <summary>
/// Activates the debug hook /// Activates the debug hook
/// </summary> /// </summary>
/// <param name="mask">Mask</param> /// <param name="mask">Mask</param>
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
<Compile Include="LuaGlobalAttribute.cs" /> <Compile Include="LuaGlobalAttribute.cs" />
<Compile Include="LuaHideAttribute.cs" /> <Compile Include="LuaHideAttribute.cs" />
<Compile Include="LuaRegistrationHelper.cs" /> <Compile Include="LuaRegistrationHelper.cs" />
<Compile Include="LuaScriptException.cs" />
<Compile Include="LuaTable.cs" /> <Compile Include="LuaTable.cs" />
<Compile Include="LuaUserData.cs" /> <Compile Include="LuaUserData.cs" />
<Compile Include="Metatables.cs" /> <Compile Include="Metatables.cs" />
......
using System;
namespace LuaInterface
{
/// <summary>
/// Exceptions thrown by the Lua runtime because of errors in the script
/// </summary>
public class LuaScriptException : LuaException
{
/// <summary>
/// Returns true if the exception has occured as the result of a .NET exception in user code
/// </summary>
public bool IsNetException { get; private set; }
private readonly string source;
/// <summary>
/// The position in the script where the exception was triggered.
/// </summary>
public override string Source { get { return source; } }
/// <summary>
/// Creates a new Lua-only exception.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="source">The position in the script where the exception was triggered.</param>
public LuaScriptException(string message, string source) : base(message)
{
this.source = source;
}
/// <summary>
/// Creates a new .NET wrapping exception.
/// </summary>
/// <param name="innerException">The .NET exception triggered by user-code.</param>
/// <param name="source">The position in the script where the exception was triggered.</param>
public LuaScriptException(Exception innerException, string source)
: base("A .NET exception occured in user-code", innerException)
{
this.source = source;
this.IsNetException = true;
}
public override string ToString()
{
// Prepend the error source
return GetType().FullName + ": " + source + Message;
}
}
}
\ No newline at end of file
...@@ -158,27 +158,40 @@ namespace LuaInterface ...@@ -158,27 +158,40 @@ namespace LuaInterface
/* /*
* Passes errors (argument e) to the Lua interpreter * Passes errors (argument e) to the Lua interpreter
*/ */
internal void throwError(IntPtr luaState,object e) internal void throwError(IntPtr luaState, object e)
{ {
// If the argument is a mere string, we are free to add extra info to it (as opposed to some private C# exception object or somesuch, which we just pass up) // We use this to remove anything pushed by luaL_where
if (e is string) int oldTop = LuaDLL.lua_gettop(luaState);
{
// We use this to remove anything pushed by luaL_where
int oldTop = LuaDLL.lua_gettop(luaState);
// Stack frame #1 is our C# wrapper, so not very interesting to the user // Stack frame #1 is our C# wrapper, so not very interesting to the user
// Stack frame #2 must be the lua code that called us, so that's what we want to use // Stack frame #2 must be the lua code that called us, so that's what we want to use
LuaDLL.luaL_where(luaState, 2); LuaDLL.luaL_where(luaState, 1);
object[] curlev = popValues(luaState, oldTop); object[] curlev = popValues(luaState, oldTop);
// Debug.WriteLine(curlev);
if (curlev.Length > 0) // Determine the position in the script where the exception was triggered
e = curlev[0].ToString() + e; string errLocation = "";
if (curlev.Length > 0)
errLocation = curlev[0].ToString();
string message = e as string;
if (message != null)
{
// Wrap Lua error (just a string) and store the error location
e = new LuaScriptException(message, errLocation);
}
else
{
Exception ex = e as Exception;
if (ex != null)
{
// Wrap generic .NET exception as an InnerException and store the error location
e = new LuaScriptException(ex, errLocation);
}
} }
push(luaState,e); push(luaState, e);
LuaDLL.lua_error(luaState); LuaDLL.lua_error(luaState);
} }
/* /*
* Implementation of load_assembly. Throws an error * Implementation of load_assembly. Throws an error
* if the assembly is not found. * if the assembly is not found.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment