Browse Source

Merge pull request #27 from AnnulusGames/function-thread-extensions

Add: LuaFunction/LuaThread extensions
Annulus Games 1 year ago
parent
commit
d8a5ea61dd

+ 3 - 3
src/Lua/LuaCoroutine.cs

@@ -44,7 +44,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
     public bool IsProtectedMode { get; }
     public LuaFunction Function { get; }
 
-    public override async ValueTask<int> Resume(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
+    public override async ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     {
         var baseThread = context.Thread;
         baseThread.UnsafeSetStatus(LuaThreadStatus.Normal);
@@ -122,7 +122,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                 {
                     int frameBase;
                     var variableArgumentCount = Function.GetVariableArgumentCount(context.ArgumentCount - 1);
-                    
+
                     if (variableArgumentCount > 0)
                     {
                         var fixedArgumentCount = context.ArgumentCount - 1 - variableArgumentCount;
@@ -218,7 +218,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
         }
     }
 
-    public override async ValueTask<int> Yield(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
+    public override async ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     {
         if (Volatile.Read(ref status) != (byte)LuaThreadStatus.Running)
         {

+ 1 - 11
src/Lua/LuaFunction.cs

@@ -8,19 +8,9 @@ public abstract partial class LuaFunction
 
     public async ValueTask<int> InvokeAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
-        var state = context.State;
-        
-        if (context.FrameBase == null)
-        {
-            context = context with
-            {
-                FrameBase = context.Thread.Stack.Count - context.ArgumentCount
-            };
-        }
-
         var frame = new CallStackFrame
         {
-            Base = context.FrameBase.Value,
+            Base = context.FrameBase,
             CallPosition = context.SourcePosition,
             ChunkName = context.ChunkName ?? LuaState.DefaultChunkName,
             RootChunkName = context.RootChunkName ?? LuaState.DefaultChunkName,

+ 2 - 2
src/Lua/LuaFunctionExecutionContext.cs

@@ -8,7 +8,7 @@ public readonly record struct LuaFunctionExecutionContext
     public required LuaState State { get; init; }
     public required LuaThread Thread { get; init; }
     public required int ArgumentCount { get; init; }
-    public int? FrameBase { get; init; }
+    public int FrameBase { get; init; }
     public SourcePosition? SourcePosition { get; init; }
     public string? RootChunkName { get; init; }
     public string? ChunkName { get; init; }
@@ -17,7 +17,7 @@ public readonly record struct LuaFunctionExecutionContext
     {
         get
         {
-            return Thread.GetStackValues().Slice(FrameBase!.Value, ArgumentCount);
+            return Thread.GetStackValues().Slice(FrameBase, ArgumentCount);
         }
     }
 

+ 30 - 0
src/Lua/LuaFunctionExtensions.cs

@@ -0,0 +1,30 @@
+using Lua.Internal;
+
+namespace Lua;
+
+public static class LuaFunctionExtensions
+{
+
+    public static async ValueTask<LuaValue[]> InvokeAsync(this LuaFunction function, LuaState state, LuaValue[] arguments, CancellationToken cancellationToken = default)
+    {
+        using var buffer = new PooledArray<LuaValue>(1024);
+
+        var thread = state.CurrentThread;
+        var frameBase = thread.Stack.Count;
+        
+        for (int i = 0; i < arguments.Length; i++)
+        {
+            thread.Stack.Push(arguments[i]);
+        }
+
+        var resultCount = await function.InvokeAsync(new()
+        {
+            State = state,
+            Thread = thread,
+            ArgumentCount = arguments.Length,
+            FrameBase = frameBase,
+        }, buffer.AsMemory(), cancellationToken);
+
+        return buffer.AsSpan()[0..resultCount].ToArray();
+    }
+}

+ 2 - 2
src/Lua/LuaMainThread.cs

@@ -12,14 +12,14 @@ public sealed class LuaMainThread : LuaThread
         // Do nothing
     }
 
-    public override ValueTask<int> Resume(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
+    public override ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     {
         buffer.Span[0] = false;
         buffer.Span[1] = "cannot resume non-suspended coroutine";
         return new(2);
     }
 
-    public override ValueTask<int> Yield(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
+    public override ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     {
         throw new LuaRuntimeException(context.State.GetTraceback(), "attempt to yield from outside a coroutine");
     }

+ 2 - 3
src/Lua/LuaThread.cs

@@ -1,4 +1,3 @@
-using System.Diagnostics;
 using Lua.Internal;
 using Lua.Runtime;
 
@@ -8,8 +7,8 @@ public abstract class LuaThread
 {
     public abstract LuaThreadStatus GetStatus();
     public abstract void UnsafeSetStatus(LuaThreadStatus status);
-    public abstract ValueTask<int> Resume(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default);
-    public abstract ValueTask<int> Yield(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default);
+    public abstract ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default);
+    public abstract ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken = default);
 
     LuaStack stack = new();
     FastStackCore<CallStackFrame> callStack;

+ 46 - 0
src/Lua/LuaThreadExtensions.cs

@@ -0,0 +1,46 @@
+using Lua.Internal;
+
+namespace Lua;
+
+public static class LuaThreadExtensions
+{
+    public static async ValueTask<LuaValue[]> ResumeAsync(this LuaThread thread, LuaState state, CancellationToken cancellationToken = default)
+    {
+        using var buffer = new PooledArray<LuaValue>(1024);
+
+        var frameBase = thread.Stack.Count;
+        thread.Stack.Push(thread);
+
+        var resultCount = await thread.ResumeAsync(new()
+        {
+            State = state,
+            Thread = state.CurrentThread,
+            ArgumentCount = 1,
+            FrameBase = frameBase,
+        }, buffer.AsMemory(), cancellationToken);
+
+        return buffer.AsSpan()[0..resultCount].ToArray();
+    }
+
+    public static async ValueTask<LuaValue[]> ResumeAsync(this LuaThread thread, LuaState state, LuaValue[] arguments, CancellationToken cancellationToken = default)
+    {
+        using var buffer = new PooledArray<LuaValue>(1024);
+
+        var frameBase = thread.Stack.Count;
+        thread.Stack.Push(thread);
+        for (int i = 0; i < arguments.Length; i++)
+        {
+            thread.Stack.Push(arguments[i]);
+        }
+
+        var resultCount = await thread.ResumeAsync(new()
+        {
+            State = state,
+            Thread = state.CurrentThread,
+            ArgumentCount = 1 + arguments.Length,
+            FrameBase = frameBase,
+        }, buffer.AsMemory(), cancellationToken);
+
+        return buffer.AsSpan()[0..resultCount].ToArray();
+    }
+}

+ 1 - 1
src/Lua/Standard/Basic/XPCallFunction.cs

@@ -40,7 +40,7 @@ public sealed class XPCallFunction : LuaFunction
             {
                 State = context.State,
                 ArgumentCount = 1,
-                FrameBase = null,
+                FrameBase = context.Thread.Stack.Count - context.ArgumentCount,
             }, methodBuffer.AsMemory(), cancellationToken);
 
             buffer.Span[0] = false;

+ 1 - 1
src/Lua/Standard/Coroutines/CoroutineResumeFunction.cs

@@ -9,6 +9,6 @@ public sealed class CoroutineResumeFunction : LuaFunction
     protected override async ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var thread = context.GetArgument<LuaThread>(0);
-        return await thread.Resume(context, buffer, cancellationToken);
+        return await thread.ResumeAsync(context, buffer, cancellationToken);
     }
 }

+ 1 - 1
src/Lua/Standard/Coroutines/CoroutineWrapFunction.cs

@@ -27,7 +27,7 @@ public sealed class CoroutineWrapFunction : LuaFunction
             stack.Push(targetThread);
             PushArguments(stack, context.Arguments);
 
-            var resultCount = await targetThread.Resume(context with
+            var resultCount = await targetThread.ResumeAsync(context with
             {
                 ArgumentCount = context.ArgumentCount + 1,
                 FrameBase = frameBase,

+ 1 - 1
src/Lua/Standard/Coroutines/CoroutineYieldFunction.cs

@@ -8,6 +8,6 @@ public sealed class CoroutineYieldFunction : LuaFunction
 
     protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
-        return context.Thread.Yield(context, buffer, cancellationToken);
+        return context.Thread.YieldAsync(context, buffer, cancellationToken);
     }
 }

+ 1 - 1
src/Lua/Standard/Table/SortFunction.cs

@@ -63,7 +63,7 @@ public sealed class SortFunction : LuaFunction
             await comparer.InvokeAsync(context with
             {
                 ArgumentCount = 2,
-                FrameBase = null,
+                FrameBase = context.Thread.Stack.Count - context.ArgumentCount,
             }, methodBuffer.AsMemory(), cancellationToken);
 
             if (methodBuffer[0].ToBoolean())

+ 1 - 1
src/Lua/Standard/Text/GSubFunction.cs

@@ -65,7 +65,7 @@ public sealed class GSubFunction : LuaFunction
                 await func.InvokeAsync(context with
                 {
                     ArgumentCount = match.Groups.Count,
-                    FrameBase = null
+                    FrameBase = context.Thread.Stack.Count - context.ArgumentCount,
                 }, methodBuffer.AsMemory(), cancellationToken);
 
                 result = methodBuffer[0];