Browse Source

Add: xpcall

AnnulusGames 1 year ago
parent
commit
75ad06bf2a
2 changed files with 53 additions and 2 deletions
  1. 1 2
      src/Lua/LuaState.cs
  2. 52 0
      src/Lua/Standard/Basic/XPCallFunction.cs

+ 1 - 2
src/Lua/LuaState.cs

@@ -66,8 +66,7 @@ public sealed class LuaState
 
     public void Push(LuaValue value)
     {
-        ThrowIfRunning();
-        mainThread.Stack.Push(value);
+        CurrentThread.Stack.Push(value);
     }
 
     public LuaThread CreateThread(LuaFunction function, bool isProtectedMode = true)

+ 52 - 0
src/Lua/Standard/Basic/XPCallFunction.cs

@@ -0,0 +1,52 @@
+using Lua.Internal;
+
+namespace Lua.Standard.Basic;
+
+public sealed class XPCallFunction : LuaFunction
+{
+    public override string Name => "xpcall";
+    public static readonly XPCallFunction Instance = new();
+
+    protected override async ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<LuaFunction>(0);
+        var arg1 = context.ReadArgument<LuaFunction>(1);
+
+        using var methodBuffer = new PooledArray<LuaValue>(1024);
+        methodBuffer.AsSpan().Clear();
+
+        try
+        {
+            var resultCount = await arg0.InvokeAsync(context with
+            {
+                State = context.State,
+                ArgumentCount = context.ArgumentCount - 2,
+                StackPosition = context.StackPosition + 2,
+            }, methodBuffer.AsMemory(), cancellationToken);
+
+            buffer.Span[0] = true;
+            methodBuffer.AsSpan()[..resultCount].CopyTo(buffer.Span[1..]);
+
+            return resultCount + 1;
+        }
+        catch (Exception ex)
+        {
+            methodBuffer.AsSpan().Clear();
+
+            context.State.Push(ex.Message);
+
+            // invoke error handler
+            await arg1.InvokeAsync(context with
+            {
+                State = context.State,
+                ArgumentCount = 1,
+                StackPosition = null,
+            }, methodBuffer.AsMemory(), cancellationToken);
+
+            buffer.Span[0] = false;
+            buffer.Span[1] = ex.Message;
+
+            return 2;
+        }
+    }
+}