Skip to content

Commit

Permalink
xpcall and debug.traceback
Browse files Browse the repository at this point in the history
  • Loading branch information
xanathar committed Dec 2, 2014
1 parent 275b2af commit 2dd128e
Show file tree
Hide file tree
Showing 47 changed files with 582 additions and 235 deletions.
6 changes: 3 additions & 3 deletions src/MoonSharp.Debugger/MainForm.cs
Expand Up @@ -67,12 +67,12 @@ private void Console_WriteLine(string fmt, params object[] args)
private void DebugScript(string filename)
{
m_Script = new Script(CoreModules.Preset_Complete);

m_Script.DebugPrint = s => { Console_WriteLine("{0}", s); };
m_Script.Options.UseLuaErrorLocations = true;
m_Script.Options.DebugPrint = s => { Console_WriteLine("{0}", s); };

var L = new ClassicLuaScriptLoader();
L.ModulePaths = L.UnpackStringPaths("Modules/?;Modules/?.lua");
m_Script.ScriptLoader = L;
m_Script.Options.ScriptLoader = L;

try
{
Expand Down
4 changes: 2 additions & 2 deletions src/MoonSharp.Interpreter.Tests/EndToEnd/StringLibTests.cs
Expand Up @@ -161,7 +161,7 @@ public void PrintTest1()
Script S = new Script();
DynValue main = S.LoadString(script);

S.DebugPrint = s =>
S.Options.DebugPrint = s =>
{
printed = s;
};
Expand Down Expand Up @@ -191,7 +191,7 @@ function m.__tostring()
Script S = new Script();
DynValue main = S.LoadString(script);

S.DebugPrint = s =>
S.Options.DebugPrint = s =>
{
printed = s;
};
Expand Down
10 changes: 7 additions & 3 deletions src/MoonSharp.Interpreter.Tests/TestMore/301-basic.t
Expand Up @@ -341,7 +341,7 @@ else
end
]]

--[[ XPCALL

if jit then
error_like(function () xpcall(assert, nil) end,
"bad argument #2 to 'xpcall' %(function expected, got nil%)",
Expand All @@ -353,7 +353,7 @@ if jit then
else
is(xpcall(assert, nil), false, "function xpcall")
error_like(function () xpcall(assert) end,
"^[^:]+:%d+: bad argument #2 to 'xpcall' %(value expected%)",
"^[^:]+:%d+: bad argument #2 to 'xpcall' %(function expected, got no value%)",
"function xpcall (no arg)")
end

Expand All @@ -364,10 +364,14 @@ r, msg = xpcall(assert, backtrace)
is(r, false, "function xpcall (backtrace)")
is(msg, 'not a back trace')

r, msg = xpcall(function() assert(); end, backtrace)
is(r, false, "function xpcall (backtrace)")
is(msg, 'not a back trace')

r = xpcall(assert, backtrace, true)
is(r, true, "function xpcall")

]]


-- Local Variables:
-- mode: lua
Expand Down
9 changes: 6 additions & 3 deletions src/MoonSharp.Interpreter.Tests/TestMore/TapRunner.cs
Expand Up @@ -29,15 +29,18 @@ public void Run()
Script S = new Script();

//S.Globals["print"] = DynValue.NewCallback(Print);
S.DebugPrint = Print;
S.Options.DebugPrint = Print;

S.Options.UseLuaErrorLocations = true;

S.Globals.Set("arg", DynValue.NewTable(S));

ClassicLuaScriptLoader L = S.ScriptLoader as ClassicLuaScriptLoader;
ClassicLuaScriptLoader L = S.Options.ScriptLoader as ClassicLuaScriptLoader;

if (L == null)
{
L = new ClassicLuaScriptLoader();
S.ScriptLoader = L;
S.Options.ScriptLoader = L;
}

L.ModulePaths = L.UnpackStringPaths("TestMore/Modules/?;TestMore/Modules/?.lua");
Expand Down
12 changes: 6 additions & 6 deletions src/MoonSharp.Interpreter.Tests/TestMore/TestMoreTests.cs
Expand Up @@ -268,12 +268,12 @@ public void TestMore_309_os()
}


[Test]
[Ignore]
public void TestMore_310_debug()
{
TapRunner.Run(@"TestMore\310-debug.t");
}
//[Test]
//[Ignore]
//public void TestMore_310_debug()
//{
// TapRunner.Run(@"TestMore\310-debug.t");
//}


[Test]
Expand Down
10 changes: 5 additions & 5 deletions src/MoonSharp.Interpreter/CoreLib/BasicModule.cs
Expand Up @@ -38,9 +38,9 @@ public static DynValue assert(ScriptExecutionContext executionContext, CallbackA
if (!v.CastToBool())
{
if (message.IsNil())
throw new ScriptRuntimeException("assertion failed!");
throw new ScriptRuntimeException("assertion failed!") { DoNotDecorateMessage = true };
else
throw new ScriptRuntimeException(message.ToPrintString());
throw new ScriptRuntimeException(message.ToPrintString()) { DoNotDecorateMessage = true };
}

return DynValue.NewTupleNested(args.GetArray());
Expand Down Expand Up @@ -74,7 +74,7 @@ public static DynValue collectgarbage(ScriptExecutionContext executionContext, C
public static DynValue error(ScriptExecutionContext executionContext, CallbackArguments args)
{
DynValue message = args.AsType(0, "error", DataType.String, false);
throw new ScriptRuntimeException(message.String);
throw new ScriptRuntimeException(message.String) { DoNotDecorateMessage = true };
}


Expand All @@ -96,7 +96,7 @@ public static DynValue tostring(ScriptExecutionContext executionContext, Callbac
if (tail == null || tail.IsNil())
return DynValue.NewString(v.ToPrintString());

tail.TailCallData.Continuation = new CallbackFunction(__tostring_continuation);
tail.TailCallData.Continuation = new CallbackFunction(__tostring_continuation, "__tostring");

return tail;
}
Expand Down Expand Up @@ -230,7 +230,7 @@ public static DynValue print(ScriptExecutionContext executionContext, CallbackAr
sb.Append(args.AsStringUsingMeta(executionContext, i, "print"));
}

executionContext.GetScript().DebugPrint(sb.ToString());
executionContext.GetScript().Options.DebugPrint(sb.ToString());

return DynValue.Nil;
}
Expand Down
107 changes: 103 additions & 4 deletions src/MoonSharp.Interpreter/CoreLib/DebugModule.cs
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MoonSharp.Interpreter.Debugging;
using MoonSharp.Interpreter.Execution;

namespace MoonSharp.Interpreter.CoreLib
Expand All @@ -18,22 +19,22 @@ public static DynValue debug(ScriptExecutionContext executionContext, CallbackAr
{
try
{
string cmd = script.DebugInput();
string cmd = script.Options.DebugInput();

if (cmd == "cont")
return DynValue.Void;

DynValue v = script.LoadString(cmd, null, "stdin");
DynValue result = script.Call(v);
script.DebugPrint(string.Format("={0}", result));
script.Options.DebugPrint(string.Format("={0}", result));
}
catch (ScriptRuntimeException ex)
{
script.DebugPrint(string.Format("{0}", ex.DecoratedMessage ?? ex.Message));
script.Options.DebugPrint(string.Format("{0}", ex.DecoratedMessage ?? ex.Message));
}
catch (Exception ex)
{
script.DebugPrint(string.Format("{0}", ex.Message));
script.Options.DebugPrint(string.Format("{0}", ex.Message));
}
}
}
Expand Down Expand Up @@ -157,5 +158,103 @@ public static DynValue setupvalue(ScriptExecutionContext executionContext, Callb
}


[MoonSharpMethod]
public static DynValue traceback(ScriptExecutionContext executionContext, CallbackArguments args)
{
StringBuilder sb = new StringBuilder();

DynValue vmessage = args[0];
DynValue vlevel = args[1];

double defaultSkip = 1.0;

Coroutine cor = executionContext.GetCallingCoroutine();

if (vmessage.Type == DataType.Thread)
{
cor = vmessage.Coroutine;
vmessage = args[1];
vlevel = args[2];
defaultSkip = 0.0;
}

if (vmessage.IsNotNil() && vmessage.Type != DataType.String && vmessage.Type != DataType.Number)
{
return vmessage;
}

string message = vmessage.CastToString();

int skip = (int)((vlevel.CastToNumber()) ?? defaultSkip);

WatchItem[] stacktrace = cor.GetStackTrace(Math.Max(0, skip));

if (message != null)
sb.AppendLine(message);

sb.AppendLine("stack traceback:");

foreach (WatchItem wi in stacktrace)
{
string name;

if (wi.Name == null)
if (wi.RetAddress < 0)
name = "main chunk";
else
name = "?";
else
name = "function '" + wi.Name + "'";

string loc = wi.Location != null ? wi.Location.FormatLocation(executionContext.GetScript()) : "[clr]";
sb.AppendFormat("\t{0}: in {1}\n", loc, name);
}

return DynValue.NewString(sb);
}


//[MoonSharpMethod]
//public static DynValue getinfo(ScriptExecutionContext executionContext, CallbackArguments args)
//{
// Coroutine cor = executionContext.GetCallingCoroutine();
// int vfArgIdx = 0;

// if (args[0].Type == DataType.Thread)
// cor = args[0].Coroutine;

// DynValue vf = args[vfArgIdx+0];
// DynValue vwhat = args[vfArgIdx+1];

// args.AsType(vfArgIdx + 1, "getinfo", DataType.String, true);

// string what = vwhat.CastToString() ?? "nfSlu";

// DynValue vt = DynValue.NewTable(executionContext.GetScript());
// Table t = vt.Table;

// if (vf.Type == DataType.Function)
// {
// Closure f = vf.Function;
// executionContext.GetInfoForFunction
// }
// else if (vf.Type == DataType.ClrFunction)
// {

// }
// else if (vf.Type == DataType.Number || vf.Type == DataType.String)
// {

// }
// else
// {
// args.AsType(vfArgIdx + 0, "getinfo", DataType.Number, true);
// }

// return vt;


//}

}
}
41 changes: 32 additions & 9 deletions src/MoonSharp.Interpreter/CoreLib/ErrorHandlingModule.cs
Expand Up @@ -12,6 +12,15 @@ public class ErrorHandlingModule
{
[MoonSharpMethod]
public static DynValue pcall(ScriptExecutionContext executionContext, CallbackArguments args)
{
return SetErrorHandlerStrategy("pcall", executionContext, args, null);
}


private static DynValue SetErrorHandlerStrategy(string funcName,
ScriptExecutionContext executionContext,
CallbackArguments args,
DynValue handlerBeforeUnwind)
{
DynValue v = args[0];
DynValue[] a = new DynValue[args.Count - 1];
Expand All @@ -27,19 +36,20 @@ public static DynValue pcall(ScriptExecutionContext executionContext, CallbackAr
if (ret.Type == DataType.TailCallRequest)
{
if (ret.TailCallData.Continuation != null || ret.TailCallData.ErrorHandler != null)
throw new ScriptRuntimeException("the function passed to pcall cannot be called directly by pcall. wrap in a script function instead.");
throw new ScriptRuntimeException("the function passed to {0} cannot be called directly by {0}. wrap in a script function instead.", funcName);

return DynValue.NewTailCallReq(new TailCallData()
{
Args = ret.TailCallData.Args,
Function = ret.TailCallData.Function,
Continuation = new CallbackFunction(pcall_continuation),
ErrorHandler = new CallbackFunction(pcall_onerror)
Continuation = new CallbackFunction(pcall_continuation, funcName),
ErrorHandler = new CallbackFunction(pcall_onerror, funcName),
ErrorHandlerBeforeUnwind = handlerBeforeUnwind
});
}
else if (ret.Type == DataType.YieldRequest)
{
throw new ScriptRuntimeException("the function passed to pcall cannot be called directly by pcall. wrap in a script function instead.");
throw new ScriptRuntimeException("the function passed to {0} cannot be called directly by {0}. wrap in a script function instead.", funcName);
}
else
{
Expand All @@ -48,25 +58,28 @@ public static DynValue pcall(ScriptExecutionContext executionContext, CallbackAr
}
catch (ScriptRuntimeException ex)
{
return DynValue.NewTupleNested(DynValue.False, DynValue.NewString(ex.Message));
executionContext.PerformMessageDecorationBeforeUnwind(handlerBeforeUnwind, ex);
return DynValue.NewTupleNested(DynValue.False, DynValue.NewString(ex.DecoratedMessage));
}
}
else if (args[0].Type != DataType.Function)
{
return DynValue.NewTupleNested(DynValue.False, DynValue.NewString("attempt to pcall a non-function"));
return DynValue.NewTupleNested(DynValue.False, DynValue.NewString("attempt to " + funcName + " a non-function"));
}
else
{
return DynValue.NewTailCallReq(new TailCallData()
{
Args = a,
Function = v,
Continuation = new CallbackFunction(pcall_continuation),
ErrorHandler = new CallbackFunction(pcall_onerror)
Continuation = new CallbackFunction(pcall_continuation, funcName),
ErrorHandler = new CallbackFunction(pcall_onerror, funcName),
ErrorHandlerBeforeUnwind = handlerBeforeUnwind
});
}
}


public static DynValue pcall_continuation(ScriptExecutionContext executionContext, CallbackArguments args)
{
return DynValue.NewTupleNested(DynValue.True, args[0]);
Expand All @@ -89,7 +102,17 @@ public static DynValue xpcall(ScriptExecutionContext executionContext, CallbackA
a.Add(args[i]);
}

return pcall(executionContext, new CallbackArguments(a, false));
DynValue handler = null;
if (args[1].Type == DataType.Function || args[1].Type == DataType.ClrFunction)
{
handler = args[1];
}
else if (args[1].Type != DataType.Nil)
{
args.AsType(1, "xpcall", DataType.Function, false);
}

return SetErrorHandlerStrategy("xpcall", executionContext, new CallbackArguments(a, false), handler);
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/MoonSharp.Interpreter/CoreLib/IoModule.cs
Expand Up @@ -22,7 +22,7 @@ public static void MoonSharpInit(Table globalTable, Table ioTable)
UserData.RegisterType<FileUserDataBase>(InteropAccessMode.Default, "file");

Table meta = new Table(ioTable.OwnerScript);
DynValue __index = DynValue.NewCallback(new CallbackFunction(__index_callback));
DynValue __index = DynValue.NewCallback(new CallbackFunction(__index_callback, "__index_callback"));
meta.Set("__index", __index);
ioTable.MetaTable = meta;

Expand Down

0 comments on commit 2dd128e

Please sign in to comment.