Browse Source

Fix: find function name from global fields for traceback

Akeit0 10 months ago
parent
commit
53c4cc168b
4 changed files with 31 additions and 21 deletions
  1. 2 2
      src/Lua/LuaState.cs
  2. 2 0
      src/Lua/LuaTable.cs
  3. 26 18
      src/Lua/Runtime/Tracebacks.cs
  4. 1 1
      src/Lua/Standard/DebugLibrary.cs

+ 2 - 2
src/Lua/LuaState.cs

@@ -95,7 +95,7 @@ public sealed class LuaState
     {
     {
         if (threadStack.Count == 0)
         if (threadStack.Count == 0)
         {
         {
-            return new()
+            return new(this)
             {
             {
                 RootFunc = (Closure)MainThread.GetCallStackFrames()[0].Function,
                 RootFunc = (Closure)MainThread.GetCallStackFrames()[0].Function,
                 StackFrames = MainThread.GetCallStackFrames()[1..]
                 StackFrames = MainThread.GetCallStackFrames()[1..]
@@ -116,7 +116,7 @@ public sealed class LuaState
                 list.Add(frame);
                 list.Add(frame);
             }
             }
         }
         }
-        return new()
+        return new(this)
         {
         {
             RootFunc = (Closure)MainThread.GetCallStackFrames()[0].Function,
             RootFunc = (Closure)MainThread.GetCallStackFrames()[0].Function,
             StackFrames = list.AsSpan().ToArray()
             StackFrames = list.AsSpan().ToArray()

+ 2 - 0
src/Lua/LuaTable.cs

@@ -19,6 +19,8 @@ public sealed class LuaTable
     readonly LuaValueDictionary dictionary;
     readonly LuaValueDictionary dictionary;
     LuaTable? metatable;
     LuaTable? metatable;
 
 
+    internal LuaValueDictionary Dictionary => dictionary;
+
     public LuaValue this[LuaValue key]
     public LuaValue this[LuaValue key]
     {
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]

+ 26 - 18
src/Lua/Runtime/Tracebacks.cs

@@ -5,8 +5,9 @@ using Lua.Internal;
 
 
 namespace Lua.Runtime;
 namespace Lua.Runtime;
 
 
-public class Traceback
+public class Traceback(LuaState state)
 {
 {
+    public LuaState State => state;
     public required Closure RootFunc { get; init; }
     public required Closure RootFunc { get; init; }
     public required CallStackFrame[] StackFrames { get; init; }
     public required CallStackFrame[] StackFrames { get; init; }
 
 
@@ -35,10 +36,10 @@ public class Traceback
 
 
     public override string ToString()
     public override string ToString()
     {
     {
-        return GetTracebackString(RootFunc, StackFrames, LuaValue.Nil);
+        return GetTracebackString(State,RootFunc, StackFrames, LuaValue.Nil);
     }
     }
 
 
-    internal static string GetTracebackString(Closure rootFunc, ReadOnlySpan<CallStackFrame> stackFrames, LuaValue message)
+    internal static string GetTracebackString(LuaState state,Closure rootFunc, ReadOnlySpan<CallStackFrame> stackFrames, LuaValue message)
     {
     {
         using var list = new PooledList<char>(64);
         using var list = new PooledList<char>(64);
         if (message.Type is not LuaValueType.Nil)
         if (message.Type is not LuaValueType.Nil)
@@ -79,6 +80,19 @@ public class Traceback
                     continue;
                     continue;
                 }
                 }
 
 
+                foreach (var pair in state.Environment.Dictionary)
+                {
+                    if (pair.Key.TryReadString(out var name) 
+                        && pair.Value.TryReadFunction(out var result) && 
+                        result == closure)
+                    {
+                        list.AddRange("function '");
+                        list.AddRange(name);
+                        list.AddRange("'\n");
+                        goto Next;
+                    }
+                }
+
                 var caller = index > 1 ? stackFrames[index - 2].Function : rootFunc;
                 var caller = index > 1 ? stackFrames[index - 2].Function : rootFunc;
                 if (index > 0 && caller is Closure callerClosure)
                 if (index > 0 && caller is Closure callerClosure)
                 {
                 {
@@ -103,21 +117,15 @@ public class Traceback
                     }
                     }
                 }
                 }
 
 
-                if (p.Name != "")
-                {
-                    list.AddRange("function '");
-                    list.AddRange(p.Name);
-                    list.AddRange("'\n");
-                }
-                else
-                {
-                    list.AddRange("function <");
-                    list.AddRange(shortSourceBuffer[..len]);
-                    list.AddRange(":");
-                    p.LineDefined.TryFormat(intFormatBuffer, out charsWritten, provider: CultureInfo.InvariantCulture);
-                    list.AddRange(intFormatBuffer[..charsWritten]);
-                    list.AddRange(">\n");
-                }
+                
+                list.AddRange("function <");
+                list.AddRange(shortSourceBuffer[..len]);
+                list.AddRange(":");
+                p.LineDefined.TryFormat(intFormatBuffer, out charsWritten, provider: CultureInfo.InvariantCulture);
+                list.AddRange(intFormatBuffer[..charsWritten]);
+                list.AddRange(">\n");
+                
+                Next: ;
             }
             }
         }
         }
 
 

+ 1 - 1
src/Lua/Standard/DebugLibrary.cs

@@ -276,7 +276,7 @@ public class DebugLibrary
         var callStack = thread.GetCallStackFrames();
         var callStack = thread.GetCallStackFrames();
         var skipCount = Math.Min(level, callStack.Length - 1);
         var skipCount = Math.Min(level, callStack.Length - 1);
         var frames = callStack[1..^skipCount];
         var frames = callStack[1..^skipCount];
-        buffer.Span[0] = Runtime.Traceback.GetTracebackString((Closure)callStack[0].Function, frames, message);
+        buffer.Span[0] = Runtime.Traceback.GetTracebackString(context.State,(Closure)callStack[0].Function, frames, message);
         thread.PopCallStackFrame();
         thread.PopCallStackFrame();
         return new(1);
         return new(1);
     }
     }