diff --git a/.gitignore b/.gitignore index c2fc1cd9..9fdbf961 100644 --- a/.gitignore +++ b/.gitignore @@ -170,3 +170,4 @@ $RECYCLE.BIN/ # Mac desktop service store files .DS_Store +/src/.vs diff --git a/src/.vs/restore.dg b/src/.vs/restore.dg deleted file mode 100755 index 0a8c8d32..00000000 --- a/src/.vs/restore.dg +++ /dev/null @@ -1,7 +0,0 @@ -#:Z:\git\my\moonsharp\src\MoonSharp.VsCodeDebugger\_Projects\MoonSharp.VsCodeDebugger.netcore\MoonSharp.VsCodeDebugger.netcore.xproj -Z:\git\my\moonsharp\src\MoonSharp.VsCodeDebugger\_Projects\MoonSharp.VsCodeDebugger.netcore\MoonSharp.VsCodeDebugger.netcore.xproj|Z:\git\my\moonsharp\src\MoonSharp.Interpreter\_Projects\MoonSharp.Interpreter.netcore\MoonSharp.Interpreter.netcore.xproj -#:Z:\git\my\moonsharp\src\TestRunners\DotNetCoreTestRunner\DotNetCoreTestRunner.xproj -Z:\git\my\moonsharp\src\TestRunners\DotNetCoreTestRunner\DotNetCoreTestRunner.xproj|Z:\git\my\moonsharp\src\MoonSharp.Interpreter\_Projects\MoonSharp.Interpreter.netcore\MoonSharp.Interpreter.netcore.xproj -Z:\git\my\moonsharp\src\TestRunners\DotNetCoreTestRunner\DotNetCoreTestRunner.xproj|Z:\git\my\moonsharp\src\MoonSharp.VsCodeDebugger\_Projects\MoonSharp.VsCodeDebugger.netcore\MoonSharp.VsCodeDebugger.netcore.xproj -Z:\git\my\moonsharp\src\MoonSharp.VsCodeDebugger\_Projects\MoonSharp.VsCodeDebugger.netcore\MoonSharp.VsCodeDebugger.netcore.xproj|Z:\git\my\moonsharp\src\MoonSharp.Interpreter\_Projects\MoonSharp.Interpreter.netcore\MoonSharp.Interpreter.netcore.xproj -#:Z:\git\my\moonsharp\src\MoonSharp.Interpreter\_Projects\MoonSharp.Interpreter.netcore\MoonSharp.Interpreter.netcore.xproj diff --git a/src/MoonSharp.Interpreter/CoreLib/BasicModule.cs b/src/MoonSharp.Interpreter/CoreLib/BasicModule.cs index 980e138c..a93c9647 100755 --- a/src/MoonSharp.Interpreter/CoreLib/BasicModule.cs +++ b/src/MoonSharp.Interpreter/CoreLib/BasicModule.cs @@ -42,10 +42,11 @@ public static DynValue assert(ScriptExecutionContext executionContext, CallbackA if (!v.CastToBool()) { + var cor = executionContext.GetCallingCoroutine(); if (message.IsNil()) - throw new ScriptRuntimeException("assertion failed!"); // { DoNotDecorateMessage = true }; + throw new ScriptRuntimeException("assertion failed!") { CallStack = cor.GetStackTrace(0) }; // { DoNotDecorateMessage = true }; else - throw new ScriptRuntimeException(message.ToPrintString()); // { DoNotDecorateMessage = true }; + throw new ScriptRuntimeException(message.ToPrintString()) { CallStack = cor.GetStackTrace(0) }; // { DoNotDecorateMessage = true }; } return DynValue.NewTupleNested(args.GetArray()); @@ -91,7 +92,7 @@ public static DynValue error(ScriptExecutionContext executionContext, CallbackAr WatchItem[] stacktrace = cor.GetStackTrace(0, executionContext.CallingLocation); - var e = new ScriptRuntimeException(message.String); + var e = new ScriptRuntimeException(message.String) { CallStack = stacktrace }; if (level.IsNil()) { @@ -229,8 +230,13 @@ public static DynValue tonumber(ScriptExecutionContext executionContext, Callbac if (e.Type != DataType.String) return DynValue.Nil; - double d; - if (double.TryParse(e.String, NumberStyles.Any, CultureInfo.InvariantCulture, out d)) + if (e.String.StartsWith("0x")) + { + if (long.TryParse(e.String.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long l)) + return DynValue.NewNumber(l); + return DynValue.Nil; + } + if (double.TryParse(e.String, NumberStyles.Any, CultureInfo.InvariantCulture, out double d)) { return DynValue.NewNumber(d); } diff --git a/src/MoonSharp.Interpreter/CoreLib/DebugModule.cs b/src/MoonSharp.Interpreter/CoreLib/DebugModule.cs index c61d30ba..b8890f33 100644 --- a/src/MoonSharp.Interpreter/CoreLib/DebugModule.cs +++ b/src/MoonSharp.Interpreter/CoreLib/DebugModule.cs @@ -297,47 +297,153 @@ public static DynValue traceback(ScriptExecutionContext executionContext, Callba //} - //[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; + [MoonSharpModuleMethod] + public static DynValue getinfo(ScriptExecutionContext executionContext, CallbackArguments args) + { + Coroutine cor = executionContext.GetCallingCoroutine(); + int vfArgIdx = 0; - // DynValue vf = args[vfArgIdx+0]; - // DynValue vwhat = args[vfArgIdx+1]; + if (args[0].Type == DataType.Thread) + cor = args[0].Coroutine; - // args.AsType(vfArgIdx + 1, "getinfo", DataType.String, true); + DynValue vf = args[vfArgIdx+0]; + DynValue vwhat = args[vfArgIdx+1]; + + //args.AsType(vfArgIdx + 1, "getinfo", DataType.String, true); - // string what = vwhat.CastToString() ?? "nfSlu"; + string what = vwhat.CastToString() ?? "nfSlu"; - // DynValue vt = DynValue.NewTable(executionContext.GetScript()); - // Table t = vt.Table; + DynValue vt = DynValue.NewTable(executionContext.GetScript()); + Table t = vt.Table; + if (vf.Type == DataType.Function || vf.Type == DataType.ClrFunction) + { + GetInfoAboutFunction(t, vf, what, executionContext); + return vt; + } + else if (vf.Type == DataType.Number) + { + var stackTrace = cor.GetStackTrace((int)vf.Number); + if (stackTrace.Length <= 0) + return DynValue.Nil; + var info = stackTrace[0]; + if (what.Contains("S")) + { + var source = executionContext.OwnerScript.GetSourceCode(info.Location.SourceIdx); + if (source != null) + { + t["source"] = source != null ? source.Name : "[C]"; + t["short_src"] = source.Name.Substring(0, Math.Min(source.Name.Length, 60)); + t["what"] = "Lua"; + } + else + { + t["source"] = "[C]"; + t["short_src"] = "[C]"; + t["what"] = "C"; + } + } - // if (vf.Type == DataType.Function) - // { - // Closure f = vf.Function; - // executionContext.GetInfoForFunction - // } - // else if (vf.Type == DataType.ClrFunction) - // { + if (what.Contains("L")) + { - // } - // else if (vf.Type == DataType.Number || vf.Type == DataType.String) - // { + } - // } - // else - // { - // args.AsType(vfArgIdx + 0, "getinfo", DataType.Number, true); - // } + if (what.Contains("n")) + { - // return vt; + } + if (what.Contains("u")) + { - //} + } + t["linedefined"] = info.Location.FromLine; + t["lastlinedefined"] = info.Location.ToLine; + return vt; + } + return DynValue.Nil; + } + + private static void GetInfoAboutFunction(Table infoTable, DynValue function, string what, ScriptExecutionContext executionContext) + { + if (function.Type == DataType.Function) + { + Closure f = function.Function; + var sourceRef = executionContext.GetFunctionSourceCodeRef(f); + var source = executionContext.OwnerScript.GetSourceCode(sourceRef.SourceIdx); + if (what.Contains("S")) + { + infoTable["source"] = source.Name; + infoTable["short_src"] = source.Name.Substring(0, Math.Min(source.Name.Length, 60)); + + infoTable["what"] = "Lua"; + } + + if (what.Contains("L")) + { + var lines = new Table(executionContext.OwnerScript); + for (int i = sourceRef.FromLine; i <= sourceRef.ToLine; i++) + lines.Append(DynValue.NewString(source.Lines[i])); + infoTable["activelines"] = lines; + } + + if (what.Contains("n")) + { + var name = executionContext.GetFunctionName(f); + infoTable["name"] = name; + var symbolRef = executionContext.FindSymbolByName(name); + switch (symbolRef.Type) + { + case SymbolRefType.Global: + infoTable["namewhat"] = "global"; + break; + case SymbolRefType.Local: + infoTable["namewhat"] = "local"; + break; + case SymbolRefType.DefaultEnv: + infoTable["namewhat"] = "field"; + break; + } + } + + if (what.Contains("u")) + { + infoTable["nups"] = f.GetUpvaluesCount(); + } + + infoTable["linedefined"] = sourceRef.FromLine; + infoTable["lastlinedefined"] = sourceRef.ToLine; + } + else if (function.Type == DataType.ClrFunction) + { + CallbackFunction f = function.Callback; + if (what.Contains("S")) + { + infoTable["source"] = "[C]"; + infoTable["short_src"] = "[C]"; + infoTable["what"] = "C"; + } + + if (what.Contains("n")) + { + var symbolRef = executionContext.FindSymbolByName(f.Name); + infoTable["name"] = f.Name; + switch (symbolRef.Type) + { + case SymbolRefType.Global: + infoTable["namewhat"] = "global"; + break; + case SymbolRefType.Local: + infoTable["namewhat"] = "local"; + break; + case SymbolRefType.DefaultEnv: + infoTable["namewhat"] = "field"; + break; + } + } + } + + } } } diff --git a/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs b/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs index f9b90cb3..cd51912c 100644 --- a/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs +++ b/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs @@ -101,7 +101,7 @@ public class capture_ }; - public const int MAXCCALLS = 200; + public const int MAXCCALLS = 1000; public const char L_ESC = '%'; public const string SPECIALS = "^$*+?.([%-"; @@ -959,7 +959,7 @@ public static int str_format(LuaState L) case 's': { uint l; - CharPtr s = LuaLCheckLString(L, arg, out l); + CharPtr s = LuaLCheckLString(L, arg, out l, true); if ((strchr(form, '.') == null) && l >= 100) { /* no precision and string is too long to be formatted; diff --git a/src/MoonSharp.Interpreter/CoreLib/TableIteratorsModule.cs b/src/MoonSharp.Interpreter/CoreLib/TableIteratorsModule.cs index 6e3b84fe..c6d7efff 100644 --- a/src/MoonSharp.Interpreter/CoreLib/TableIteratorsModule.cs +++ b/src/MoonSharp.Interpreter/CoreLib/TableIteratorsModule.cs @@ -20,6 +20,8 @@ public class TableIteratorsModule public static DynValue ipairs(ScriptExecutionContext executionContext, CallbackArguments args) { DynValue table = args[0]; + if(table == null || table.Type == DataType.Nil) + throw new System.ApplicationException("attempt to index nil"); DynValue meta = executionContext.GetMetamethodTailCall(table, "__ipairs", args.GetArray()); diff --git a/src/MoonSharp.Interpreter/DataTypes/DynValue.cs b/src/MoonSharp.Interpreter/DataTypes/DynValue.cs index 9df80fe0..24a0f1de 100644 --- a/src/MoonSharp.Interpreter/DataTypes/DynValue.cs +++ b/src/MoonSharp.Interpreter/DataTypes/DynValue.cs @@ -650,7 +650,12 @@ public override bool Equals(object obj) return Table == other.Table; case DataType.Tuple: case DataType.TailCallRequest: - return Tuple == other.Tuple; + if (Tuple.Length != other.Tuple.Length) + return false; + for(int i = 0; i < Tuple.Length; i++) + if (!Equals(Tuple[i], other.Tuple[i])) + return false; + return true; case DataType.Thread: return Coroutine == other.Coroutine; case DataType.UserData: @@ -709,6 +714,13 @@ public string CastToString() } else if (rv.Type == DataType.String) { + if (rv.String.StartsWith("0x")) + { + if (long.TryParse(rv.String, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long value)) + return value; + return null; + } + double num; if (double.TryParse(rv.String, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) return num; diff --git a/src/MoonSharp.Interpreter/DataTypes/TablePair.cs b/src/MoonSharp.Interpreter/DataTypes/TablePair.cs index 6045ab47..fb9d46fd 100644 --- a/src/MoonSharp.Interpreter/DataTypes/TablePair.cs +++ b/src/MoonSharp.Interpreter/DataTypes/TablePair.cs @@ -1,9 +1,12 @@  +using System.Diagnostics; + namespace MoonSharp.Interpreter { /// /// A class representing a key/value pair for Table use /// + [DebuggerDisplay("\\{\"{Key}\", {Value}\\}")] public struct TablePair { private static TablePair s_NilNode = new TablePair(DynValue.Nil, DynValue.Nil); diff --git a/src/MoonSharp.Interpreter/Errors/InterpreterException.cs b/src/MoonSharp.Interpreter/Errors/InterpreterException.cs index a63fe83c..5eac88ba 100755 --- a/src/MoonSharp.Interpreter/Errors/InterpreterException.cs +++ b/src/MoonSharp.Interpreter/Errors/InterpreterException.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using MoonSharp.Interpreter.Debugging; namespace MoonSharp.Interpreter @@ -86,11 +87,36 @@ internal void DecorateMessage(Script script, SourceRef sref, int ip = -1) } else if (sref != null) { - this.DecoratedMessage = string.Format("{0}: {1}", sref.FormatLocation(script), this.Message); + var buffer = new StringBuilder($"{sref.FormatLocation(script)}: {this.Message}"); + if (CallStack != null) + { + buffer.AppendLine(); + foreach (var item in CallStack) + if (item.Location != null) + buffer.AppendLine($"{item.Location.FormatLocation(script)}: {item.Name}"); + else + buffer.AppendLine($"unknown: {item.Name}"); + } + else + new object(); + + this.DecoratedMessage = buffer.ToString(); } else { - this.DecoratedMessage = string.Format("bytecode:{0}: {1}", ip, this.Message); + var buffer = new StringBuilder($"bytecode:{ip}: {this.Message}"); + if (CallStack != null) + { + buffer.AppendLine(); + foreach (var item in CallStack) + if (item.Location != null) + buffer.AppendLine($"{item.Location.FormatLocation(script)}: {item.Name}"); + else + buffer.AppendLine($"unknown: {item.Name}"); + } + else + new object(); + this.DecoratedMessage = buffer.ToString(); } } } diff --git a/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs b/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs index 0a42ccfb..175219d7 100644 --- a/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs +++ b/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs @@ -54,6 +54,17 @@ public object AdditionalData } } + public SourceRef GetFunctionSourceCodeRef(Closure fn) + { + var i = fn.EntryPointByteCodeLocation; + return m_Processor.FindMeta(ref i).SourceCodeRef; + } + + public string GetFunctionName(Closure fn) + { + var i = fn.EntryPointByteCodeLocation; + return m_Processor.FindMeta(ref i).Name; + } /// /// Gets the metatable associated with the given value. diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Errors.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Errors.cs index 65e78659..cac0fa7d 100644 --- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Errors.cs +++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Errors.cs @@ -4,6 +4,15 @@ namespace MoonSharp.Interpreter.Execution.VM { sealed partial class Processor { + public SourceRef GetCurrentSourceRef() + { + if (m_SavedInstructionPtr >= 0 && m_SavedInstructionPtr < m_RootChunk.Code.Count) + { + return m_RootChunk.Code[m_SavedInstructionPtr].SourceCodeRef; + } + + return null; + } private SourceRef GetCurrentSourceRef(int instructionPtr) { if (instructionPtr >= 0 && instructionPtr < m_RootChunk.Code.Count) diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs index 38c0f63e..98846917 100644 --- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs +++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs @@ -703,12 +703,12 @@ private int Internal_ExecCall(int argsCount, int instructionPtr, CallbackFunctio { //IList args = new Slice(m_ValueStack, m_ValueStack.Count - argsCount, argsCount, false); IList args = CreateArgsListForFunctionCall(argsCount, 0); - // we expand tuples before callbacks + // we expand tuples before callbacks // args = DynValue.ExpandArgumentsToList(args); // instructionPtr - 1: instructionPtr already points to the next instruction at this moment // but we need the current instruction here - SourceRef sref = GetCurrentSourceRef(instructionPtr - 1); + SourceRef sref = GetCurrentSourceRef(instructionPtr - 1); m_ExecutionStack.Push(new CallStackItem() { diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs index dc1b2c62..d476cc8e 100644 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs +++ b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs @@ -134,8 +134,13 @@ public CharPtr(IntPtr ptr) public static CharPtr operator +(CharPtr ptr, uint offset) { return new CharPtr(ptr.chars, ptr.index + (int)offset); } public static CharPtr operator -(CharPtr ptr, uint offset) { return new CharPtr(ptr.chars, ptr.index - (int)offset); } - public void inc() { this.index++; } - public void dec() { this.index--; } + public CharPtr Copy() + { + return new CharPtr(this); + } + + public CharPtr inc() { this.index++; return this; } + public CharPtr dec() { this.index--; return this; } public CharPtr next() { return new CharPtr(this.chars, this.index + 1); } public CharPtr prev() { return new CharPtr(this.chars, this.index - 1); } public CharPtr add(int ofs) { return new CharPtr(this.chars, this.index + ofs); } diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs index e62ff92b..c7e947da 100644 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs +++ b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs @@ -76,10 +76,10 @@ protected static lua_Integer LuaType(LuaState L, lua_Integer p) } } - protected static string LuaLCheckLString(LuaState L, lua_Integer argNum, out uint l) + protected static string LuaLCheckLString(LuaState L, lua_Integer argNum, out uint l, bool allowNil = false) { - string str = ArgAsType(L, argNum, DataType.String, false).String; - l = (uint)str.Length; + string str = ArgAsType(L, argNum, DataType.String, allowNil).String; + l = (uint)(str?.Length ?? 0); return str; } @@ -224,6 +224,11 @@ protected static void LuaPop(LuaState L, lua_Integer p) L.Pop(); } + protected static void LuaRemove(LuaState L, lua_Integer p) + { + L.Remove(-p); + } + protected static void LuaGetTable(LuaState L, lua_Integer p) { // DEBT: this should call metamethods, now it performs raw access diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs index 94fbbbcb..6df81bd3 100644 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs +++ b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs @@ -59,6 +59,11 @@ public DynValue Pop() return v; } + public void Remove(int idx) + { + m_Stack.RemoveAt(m_Stack.Count - 1); + } + public DynValue[] GetTopArray(int num) { DynValue[] rets = new DynValue[num]; diff --git a/src/MoonSharp.Interpreter/MoonSharp.Interpreter.net35-client.csproj b/src/MoonSharp.Interpreter/MoonSharp.Interpreter.net35-client.csproj index ff2e9694..859c6616 100644 --- a/src/MoonSharp.Interpreter/MoonSharp.Interpreter.net35-client.csproj +++ b/src/MoonSharp.Interpreter/MoonSharp.Interpreter.net35-client.csproj @@ -9,7 +9,7 @@ Properties MoonSharp.Interpreter MoonSharp.Interpreter - v3.5 + v4.8 512 @@ -19,7 +19,8 @@ - Client + + ee6b0a8a true ..\keypair.snk @@ -31,8 +32,8 @@ bin\Debug\ TRACE;DEBUG prompt - 4 - 3021, 1591 + 0 + 3021, 1591, IDE1006 false @@ -61,6 +62,7 @@ x86 prompt MinimumRecommendedRules.ruleset + false bin\x86\Release\ @@ -71,6 +73,7 @@ x86 prompt ExtendedDesignGuidelineRules.ruleset + false true @@ -81,6 +84,7 @@ AnyCPU prompt MinimumRecommendedRules.ruleset + false true @@ -91,6 +95,7 @@ x86 prompt MinimumRecommendedRules.ruleset + false true @@ -101,6 +106,7 @@ AnyCPU prompt MinimumRecommendedRules.ruleset + false true @@ -111,6 +117,57 @@ x86 prompt MinimumRecommendedRules.ruleset + false + + + true + bin\x64\Debug\ + TRACE;DEBUG + 0 + 3021, 1591, IDE1006 + full + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + false + + + bin\x64\Release\ + TRACE + bin\Release\MoonSharp.Interpreter.xml + true + pdbonly + x64 + false + 7.3 + prompt + ExtendedDesignGuidelineRules.ruleset + false + + + true + bin\x64\Dev\ + TRACE;DEBUG + 3021, 1591 + full + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + false + + + true + bin\x64\Devp4\ + TRACE;DEBUG + 3021, 1591 + full + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + false @@ -390,7 +447,11 @@ - + + + .editorconfig + +