Browse Source

improve: better error message

Akeit0 7 months ago
parent
commit
e80362efe6
4 changed files with 59 additions and 7 deletions
  1. 24 5
      src/Lua/Exceptions.cs
  2. 1 1
      src/Lua/Internal/LuaDebug.cs
  3. 33 0
      src/Lua/LuaValue.cs
  4. 1 1
      src/Lua/Runtime/LuaVirtualMachine.cs

+ 24 - 5
src/Lua/Exceptions.cs

@@ -101,8 +101,9 @@ public class LuaRuntimeException : LuaException
             thread.ExceptionTrace.Clear();
             thread.CurrentException = this;
         }
+
         Thread = thread;
-        
+
         ErrorObject = errorObject;
     }
 
@@ -110,27 +111,44 @@ public class LuaRuntimeException : LuaException
 
     public Traceback? LuaTraceback
     {
-
         get
         {
             if (luaTraceback == null)
             {
                 Build();
             }
+
             return luaTraceback;
         }
     }
+
     internal LuaThread? Thread { get; private set; } = default!;
     public LuaValue ErrorObject { get; }
 
     public static void AttemptInvalidOperation(LuaThread? thread, string op, LuaValue a, LuaValue b)
     {
-        throw new LuaRuntimeException(thread, $"attempt to {op} a '{a.Type}' with a '{b.Type}'");
+        throw new LuaRuntimeException(thread, $"attempt to {op} a '{a.TypeToString()}' with a '{b.TypeToString()}'");
     }
 
     public static void AttemptInvalidOperation(LuaThread? thread, string op, LuaValue a)
     {
-        throw new LuaRuntimeException(thread, $"attempt to {op} a '{a.Type}' value");
+        throw new LuaRuntimeException(thread, $"attempt to {op} a '{a.TypeToString()}' value");
+    }
+
+    internal static void AttemptInvalidOperationOnLuaStack(LuaThread thread, string op, int lastPc, int reg)
+    {
+        var caller = thread.GetCurrentFrame();
+        var luaValue = thread.Stack[caller.Base + reg];
+        var function = caller.Function;
+        var t = LuaDebug.GetName(((LuaClosure)function).Proto, lastPc, reg, out string? name);
+        if (t == null || name == null)
+        {
+            throw new LuaRuntimeException(thread, $"attempt to {op} a {luaValue.TypeToString()} value");
+        }
+        else
+        {
+            throw new LuaRuntimeException(thread, $"attempt to {op} a {luaValue.TypeToString()} value ({t} '{name}')");
+        }
     }
 
     public static void BadArgument(LuaThread? thread, int argumentId, string functionName)
@@ -193,7 +211,7 @@ public class LuaRuntimeException : LuaException
         {
             var callStack = Thread.ExceptionTrace.AsSpan();
             if (callStack.IsEmpty) return null;
-            luaTraceback = new Traceback(Thread.State,callStack);
+            luaTraceback = new Traceback(Thread.State, callStack);
             Thread.ExceptionTrace.Clear();
             Thread = null;
         }
@@ -227,6 +245,7 @@ public class LuaRuntimeException : LuaException
         {
             return base.ToString();
         }
+
         var pooledList = new PooledList<char>(64);
         pooledList.Clear();
         try

+ 1 - 1
src/Lua/Internal/LuaDebug.cs

@@ -447,7 +447,7 @@ internal readonly struct LuaDebug : IDisposable
                 case OpCode.LoadK:
                 case OpCode.LoadKX:
                     {
-                        int b = (op == OpCode.LoadKX)
+                        int b = (op != OpCode.LoadKX)
                             ? i.Bx
                             : (prototype.Code[pc + 1].Ax);
                         if (prototype.Constants[b].TryReadString(out name))

+ 33 - 0
src/Lua/LuaValue.cs

@@ -547,6 +547,39 @@ public readonly struct LuaValue : IEquatable<LuaValue>
             _ => "",
         };
     }
+    
+    public  string TypeToString()
+    {
+        return Type switch
+        {
+            LuaValueType.Nil => "nil",
+            LuaValueType.Boolean => "boolean",
+            LuaValueType.String => "string",
+            LuaValueType.Number => "number",
+            LuaValueType.Function => "function",
+            LuaValueType.Thread => "thread",
+            LuaValueType.Table => "table",
+            LuaValueType.LightUserData => "userdata",
+            LuaValueType.UserData => "userdata",
+            _ => "",
+        };
+    }
+    public static string ToString(LuaValueType type)
+    {
+        return type switch
+        {
+            LuaValueType.Nil => "nil",
+            LuaValueType.Boolean => "boolean",
+            LuaValueType.String => "string",
+            LuaValueType.Number => "number",
+            LuaValueType.Function => "function",
+            LuaValueType.Thread => "thread",
+            LuaValueType.Table => "table",
+            LuaValueType.LightUserData => "userdata",
+            LuaValueType.UserData => "userdata",
+            _ => "",
+        };
+    }
 
     public static bool TryGetLuaValueType(Type type, out LuaValueType result)
     {

+ 1 - 1
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -1074,7 +1074,7 @@ public static partial class LuaVirtualMachine
             }
             else
             {
-                LuaRuntimeException.AttemptInvalidOperation(GetThreadWithCurrentPc(context), "call", va);
+                LuaRuntimeException.AttemptInvalidOperationOnLuaStack(GetThreadWithCurrentPc(context), "call", context.Pc,instruction.A);
             }
         }