Browse Source

Simplify LuaFunctionExecutionContext

Akeit0 7 months ago
parent
commit
21e70008f6

+ 5 - 33
src/Lua/LuaCoroutine.cs

@@ -57,21 +57,13 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                 case LuaThreadStatus.Suspended:
                     Volatile.Write(ref status, (byte)LuaThreadStatus.Running);
 
-                    if (isFirstCall)
-                    {
-                        // copy stack value
-                        var argCount = context.ArgumentCount;
-                        Stack.EnsureCapacity(argCount);
-                        baseThread.Stack.AsSpan()[^argCount..].CopyTo(Stack.GetBuffer());
-                        Stack.NotifyTop(argCount);
-                    }
-                    else
+                    if (!isFirstCall)
                     {
                         yield.SetResult(new()
                         {
-                            Results = context.ArgumentCount == 1
+                            Results = context.ArgumentCount == 0
                                 ? []
-                                : context.Arguments[1..].ToArray()
+                                : context.Arguments.ToArray()
                         });
                     }
 
@@ -114,32 +106,12 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                 if (isFirstCall)
                 {
                     returnFrameBase = Stack.Count;
-                    int frameBase;
-                    var variableArgumentCount = Function.GetVariableArgumentCount(context.ArgumentCount - 1);
-
-                    if (variableArgumentCount > 0)
-                    {
-                        var fixedArgumentCount = context.ArgumentCount - 1 - variableArgumentCount;
-                        var args = context.Arguments;
-                        Stack.PushRange(args.Slice(1 + fixedArgumentCount, variableArgumentCount));
-
-                        frameBase = Stack.Count;
-
-                        Stack.PushRange(args.Slice(1, fixedArgumentCount));
-                    }
-                    else
-                    {
-                        frameBase = Stack.Count;
-
-                        Stack.PushRange(context.Arguments[1..]);
-                    }
-
+                    Stack.PushRange(context.Arguments);
                     functionTask = Function.InvokeAsync(new()
                     {
                         State = context.State,
                         Thread = this,
-                        ArgumentCount = context.ArgumentCount - 1,
-                        FrameBase = frameBase,
+                        ArgumentCount = Stack.Count-returnFrameBase,
                         ReturnFrameBase = returnFrameBase
                     }, cancellationToken).Preserve();
 

+ 7 - 1
src/Lua/LuaFunction.cs

@@ -13,7 +13,13 @@ public class LuaFunction(string name, Func<LuaFunctionExecutionContext, Cancella
 
     public async ValueTask<int> InvokeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var frame = new CallStackFrame { Base = context.FrameBase, VariableArgumentCount = this.GetVariableArgumentCount(context.ArgumentCount), Function = this, ReturnBase = context.ReturnFrameBase };
+        var varArgumentCount = this.GetVariableArgumentCount(context.ArgumentCount);
+        if (varArgumentCount != 0)
+        {
+           LuaVirtualMachine.PrepareVariableArgument(context.Thread.Stack,context.ArgumentCount, varArgumentCount);
+           context =context with{ArgumentCount = context.ArgumentCount- varArgumentCount};
+        }
+        var frame = new CallStackFrame { Base = context.FrameBase , VariableArgumentCount = varArgumentCount, Function = this, ReturnBase = context.ReturnFrameBase };
         context.Thread.PushCallStackFrame(frame);
         try
         {

+ 7 - 5
src/Lua/LuaFunctionExecutionContext.cs

@@ -10,17 +10,19 @@ public readonly record struct LuaFunctionExecutionContext
     public required LuaState State { get; init; }
     public required LuaThread Thread { get; init; }
     public required int ArgumentCount { get; init; }
-    public required int FrameBase { get; init; }
+    public  int FrameBase => Thread.Stack.Count-ArgumentCount;
     public required int ReturnFrameBase { get; init; }
     public int? SourceLine { get; init; }
-    public string? RootChunkName { get; init; }
-    public string? ChunkName { get; init; }
     public int? CallerInstructionIndex { get; init; }
-    public object? AdditionalContext { get; init; }
+    //public object? AdditionalContext { get; init; }
 
     public ReadOnlySpan<LuaValue> Arguments
     {
-        get { return Thread.GetStackValues().Slice(FrameBase, ArgumentCount); }
+        get
+        {
+           var stack = Thread.Stack.AsSpan(); 
+            return stack.Slice(stack.Length-ArgumentCount);
+        }
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]

+ 0 - 1
src/Lua/LuaFunctionExtensions.cs

@@ -19,7 +19,6 @@ public static class LuaFunctionExtensions
             State = state,
             Thread = thread,
             ArgumentCount = arguments.Length,
-            FrameBase = frameBase,
             ReturnFrameBase = frameBase,
         }, cancellationToken);
         var r = thread.Stack.GetBuffer()[frameBase..(frameBase + resultCount)].ToArray();

+ 0 - 3
src/Lua/LuaState.cs

@@ -79,11 +79,8 @@ public sealed class LuaState
                 State = this,
                 Thread = CurrentThread,
                 ArgumentCount = 0,
-                FrameBase = 0,
                 ReturnFrameBase = 0,
                 SourceLine = null,
-                RootChunkName = closure.Proto.ChunkName,
-                ChunkName = closure.Proto.ChunkName,
             }, cancellationToken);
 
             return new LuaResult(CurrentThread.Stack, 0);

+ 110 - 33
src/Lua/LuaThread.cs

@@ -4,79 +4,148 @@ using Lua.Runtime;
 
 namespace Lua;
 
-public abstract class LuaThread
+public class LuaThread : IPoolNode<LuaThread>
 {
-    public abstract LuaThreadStatus GetStatus();
-    public abstract void UnsafeSetStatus(LuaThreadStatus status);
-    public abstract ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default);
-    public abstract ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default);
+    static LinkedPool<LuaThread> pool;
+    LuaThread? parent;
+    ref LuaThread? IPoolNode<LuaThread>.NextNode => ref parent;
+    public static LuaThread Create(LuaState state)
+    {
+        var thread = new LuaThread { CoreData = { State = state } };
+        return thread;
+    }
+    public virtual LuaThreadStatus GetStatus()
+    {
+        return LuaThreadStatus.Running;
+    }
 
-    LuaStack stack = new();
-    FastStackCore<CallStackFrame> callStack;
+    public virtual void UnsafeSetStatus(LuaThreadStatus status){}
+    public virtual ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
+    {
+        return new(context.Return(false, "cannot resume non-suspended coroutine"));
+    }
 
-    internal LuaStack Stack => stack;
-    internal ref FastStackCore<CallStackFrame> CallStack => ref callStack;
+    public virtual ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
+    {
+        throw new LuaRuntimeException(context.State.GetTraceback(), "attempt to yield from outside a coroutine");
+    }
+
+    internal class ThreadCoreData
+    {
+        internal LuaState State;
+        //internal  LuaCoroutineData? coroutineData;
+        internal LuaStack Stack = new();
+        internal FastStackCore<CallStackFrame> CallStack;
+        internal BitFlags2 LineAndCountHookMask;
+        internal BitFlags2 CallOrReturnHookMask;
+        internal bool IsInHook;
+        internal int HookCount;
+        internal int BaseHookCount;
+        internal int LastPc;
+        internal LuaFunction? Hook { get; set; }
+    }
+
+    internal ThreadCoreData CoreData = new();
+    
+    public LuaState State=> CoreData.State;
+
+    internal LuaStack Stack => CoreData.Stack;
+    internal ref FastStackCore<CallStackFrame> CallStack => ref CoreData.CallStack;
 
     internal bool IsLineHookEnabled
     {
-        get => LineAndCountHookMask.Flag0;
-        set => LineAndCountHookMask.Flag0 = value;
+        get => CoreData.LineAndCountHookMask.Flag0;
+        set => CoreData.LineAndCountHookMask.Flag0 = value;
     }
 
     internal bool IsCountHookEnabled
     {
-        get => LineAndCountHookMask.Flag1;
-        set => LineAndCountHookMask.Flag1 = value;
+        get => CoreData.LineAndCountHookMask.Flag1;
+        set => CoreData.LineAndCountHookMask.Flag1 = value;
     }
 
-    internal BitFlags2 LineAndCountHookMask;
 
     internal bool IsCallHookEnabled
     {
-        get => CallOrReturnHookMask.Flag0;
-        set => CallOrReturnHookMask.Flag0 = value;
+        get => CoreData.CallOrReturnHookMask.Flag0;
+        set => CoreData.CallOrReturnHookMask.Flag0 = value;
     }
 
     internal bool IsReturnHookEnabled
     {
-        get => CallOrReturnHookMask.Flag1;
-        set => CallOrReturnHookMask.Flag1 = value;
+        get => CoreData.CallOrReturnHookMask.Flag1;
+        set => CoreData.CallOrReturnHookMask.Flag1 = value;
+    }
+
+    internal BitFlags2 LineAndCountHookMask
+    {
+        get => CoreData.LineAndCountHookMask;
+        set => CoreData.LineAndCountHookMask = value;
+    }
+
+    internal BitFlags2 CallOrReturnHookMask
+    {
+        get => CoreData.CallOrReturnHookMask;
+        set => CoreData.CallOrReturnHookMask = value;
     }
 
-    internal BitFlags2 CallOrReturnHookMask;
-    internal bool IsInHook;
-    internal int HookCount;
-    internal int BaseHookCount;
-    internal int LastPc;
-    internal LuaFunction? Hook { get; set; }
+    internal bool IsInHook
+    {
+        get => CoreData.IsInHook;
+        set => CoreData.IsInHook = value;
+    }
+
+    internal int HookCount
+    {
+        get => CoreData.HookCount;
+        set => CoreData.HookCount = value;
+    }
+
+    internal int BaseHookCount
+    {
+        get => CoreData.BaseHookCount;
+        set => CoreData.BaseHookCount = value;
+    }
+
+    internal int LastPc
+    {
+        get => CoreData.LastPc;
+        set => CoreData.LastPc = value;
+    }
+
+    internal LuaFunction? Hook
+    {
+        get => CoreData.Hook;
+        set => CoreData.Hook = value;
+    }
 
     public ref readonly CallStackFrame GetCurrentFrame()
     {
-        return ref callStack.PeekRef();
+        return ref CoreData.CallStack.PeekRef();
     }
 
     public ReadOnlySpan<LuaValue> GetStackValues()
     {
-        return stack.AsSpan();
+        return CoreData.Stack.AsSpan();
     }
 
     public ReadOnlySpan<CallStackFrame> GetCallStackFrames()
     {
-        return callStack.AsSpan();
+        return CoreData.CallStack.AsSpan();
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     internal void PushCallStackFrame(in CallStackFrame frame)
     {
-        callStack.Push(frame);
+        CoreData.CallStack.Push(frame);
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     internal void PopCallStackFrameWithStackPop()
     {
-        if (callStack.TryPop(out var frame))
+        if (CoreData.CallStack.TryPop(out var frame))
         {
-            stack.PopUntil(frame.Base);
+            CoreData.Stack.PopUntil(frame.Base);
         }
         else
         {
@@ -87,9 +156,9 @@ public abstract class LuaThread
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     internal void PopCallStackFrameWithStackPop(int frameBase)
     {
-        if (callStack.TryPop())
+        if (CoreData.CallStack.TryPop())
         {
-            stack.PopUntil(frameBase);
+            CoreData.Stack.PopUntil(frameBase);
         }
         else
         {
@@ -100,7 +169,7 @@ public abstract class LuaThread
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     internal void PopCallStackFrame()
     {
-        if (!callStack.TryPop())
+        if (!CoreData.CallStack.TryPop())
         {
             ThrowForEmptyStack();
         }
@@ -115,5 +184,13 @@ public abstract class LuaThread
         }
     }
 
+    public void Release()
+    {
+        if (CoreData.CallStack.Count != 0)
+        {
+            throw new InvalidOperationException("This thread is running! Call stack is not empty!!");
+        }
+    }
+
     static void ThrowForEmptyStack() => throw new InvalidOperationException("Empty stack");
 }

+ 0 - 2
src/Lua/LuaThreadExtensions.cs

@@ -14,7 +14,6 @@ public static class LuaThreadExtensions
             State = state,
             Thread = state.CurrentThread,
             ArgumentCount = 1,
-            FrameBase = frameBase,
             ReturnFrameBase = frameBase,
         }, cancellationToken);
         var returnBase = ((LuaCoroutine)thread).ReturnFrameBase;
@@ -37,7 +36,6 @@ public static class LuaThreadExtensions
             State = state,
             Thread = state.CurrentThread,
             ArgumentCount = 1 + arguments.Length,
-            FrameBase = frameBase,
             ReturnFrameBase = frameBase,
         }, cancellationToken);
         var returnBase = ((LuaCoroutine)thread).ReturnFrameBase;

+ 1 - 1
src/Lua/LuaValue.cs

@@ -602,7 +602,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
             var stack = context.Thread.Stack;
             stack.Push(this);
 
-            return func.InvokeAsync(context with { ArgumentCount = 1, FrameBase = stack.Count - 1, ReturnFrameBase = stack.Count - 1, }, cancellationToken);
+            return func.InvokeAsync(context with { ArgumentCount = 1, ReturnFrameBase = stack.Count - 1, }, cancellationToken);
         }
         else
         {

+ 0 - 6
src/Lua/Runtime/LuaVirtualMachine.Debug.cs

@@ -40,7 +40,6 @@ public static partial class LuaVirtualMachine
                     State = context.State,
                     Thread = context.Thread,
                     ArgumentCount = 2,
-                    FrameBase = context.Thread.Stack.Count - 2,
                     ReturnFrameBase = context.Thread.Stack.Count - 2,
                 };
                 var frame = new CallStackFrame
@@ -84,7 +83,6 @@ public static partial class LuaVirtualMachine
                         State = context.State,
                         Thread = context.Thread,
                         ArgumentCount = 2,
-                        FrameBase = context.Thread.Stack.Count - 2,
                         ReturnFrameBase = context.Thread.Stack.Count - 2,
                     };
                     var frame = new CallStackFrame
@@ -124,7 +122,6 @@ public static partial class LuaVirtualMachine
             State = context.State,
             Thread = context.Thread,
             ArgumentCount = arguments,
-            FrameBase = frame.Base,
             ReturnFrameBase = frame.ReturnBase,
             CallerInstructionIndex = frame.CallerInstructionIndex,
         }, context.CancellationToken, isTailCall);
@@ -145,7 +142,6 @@ public static partial class LuaVirtualMachine
                 State = context.State,
                 Thread = context.Thread,
                 ArgumentCount = 2,
-                FrameBase = context.Thread.Stack.Count - 2,
                 ReturnFrameBase = context.Thread.Stack.Count - 2,
             };
             CallStackFrame frame = new()
@@ -178,7 +174,6 @@ public static partial class LuaVirtualMachine
                 State = context.State,
                 Thread = context.Thread,
                 ArgumentCount = argCount,
-                FrameBase = frame.Base,
                 ReturnFrameBase = frame.ReturnBase,
             }, cancellationToken);
             var r = await task;
@@ -194,7 +189,6 @@ public static partial class LuaVirtualMachine
                 State = context.State,
                 Thread = context.Thread,
                 ArgumentCount = 2,
-                FrameBase = context.Thread.Stack.Count - 2,
                 ReturnFrameBase = context.Thread.Stack.Count - 2,
             };
 

+ 22 - 3
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -314,7 +314,7 @@ public static partial class LuaVirtualMachine
             var stack = context.Stack;
             stack.EnsureCapacity(frameBase + context.Prototype.MaxStackSize);
             ref var constHead = ref MemoryMarshalEx.UnsafeElementAt(context.Prototype.Constants, 0);
-            ref var lineAndCountHookMask = ref context.Thread.LineAndCountHookMask;
+            ref var lineAndCountHookMask = ref context.Thread.CoreData.LineAndCountHookMask;
             goto Loop;
         LineHook:
 
@@ -962,6 +962,8 @@ public static partial class LuaVirtualMachine
         var thread = context.Thread;
         var (argumentCount, variableArgumentCount) = PrepareForFunctionCall(thread, func, instruction, newBase, isMetamethod);
         newBase += variableArgumentCount;
+        thread.Stack.PopUntil(newBase+argumentCount);
+
         var newFrame = func.CreateNewFrame(context, newBase, RA, variableArgumentCount);
 
         thread.PushCallStackFrame(newFrame);
@@ -1059,7 +1061,7 @@ public static partial class LuaVirtualMachine
 
         var (argumentCount, variableArgumentCount) = PrepareForFunctionTailCall(thread, func, instruction, newBase, isMetamethod);
         newBase = context.FrameBase + variableArgumentCount;
-
+        stack.PopUntil(newBase+argumentCount);
         var lastPc = thread.GetCurrentFrame().CallerInstructionIndex;
         context.Thread.PopCallStackFrame();
         var newFrame = func.CreateNewTailCallFrame(context, newBase, context.CurrentReturnFrameBase, variableArgumentCount);
@@ -1148,6 +1150,7 @@ public static partial class LuaVirtualMachine
             PrepareVariableArgument(stack, newBase, argumentCount, variableArgumentCount);
             newBase += variableArgumentCount;
         }
+        stack.PopUntil(newBase+argumentCount);
 
         var newFrame = iterator.CreateNewFrame(context, newBase, RA + 3, variableArgumentCount);
         context.Thread.PushCallStackFrame(newFrame);
@@ -1636,6 +1639,23 @@ public static partial class LuaVirtualMachine
         return true;
     }
 
+    // If there are variable arguments, the base of the stack is moved by that number and the values of the variable arguments are placed in front of it.
+    // see: https://wubingzheng.github.io/build-lua-in-rust/en/ch08-02.arguments.html
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    internal static void PrepareVariableArgument(LuaStack stack, int argumentCount,
+        int variableArgumentCount)
+    {
+        var top = stack.Count;
+        var newBase=stack.Count-argumentCount;
+        var temp = newBase;
+        newBase += variableArgumentCount;
+        stack.EnsureCapacity(newBase + argumentCount);
+        stack.NotifyTop(newBase + argumentCount);
+        var stackBuffer = stack.GetBuffer()[temp..];
+        stackBuffer[..argumentCount].CopyTo(stackBuffer[variableArgumentCount..]);
+        stackBuffer.Slice(argumentCount, variableArgumentCount).CopyTo(stackBuffer);;
+        stack.PopUntil(top);
+    }
     // If there are variable arguments, the base of the stack is moved by that number and the values of the variable arguments are placed in front of it.
     // see: https://wubingzheng.github.io/build-lua-in-rust/en/ch08-02.arguments.html
     [MethodImpl(MethodImplOptions.NoInlining)]
@@ -1788,7 +1808,6 @@ public static partial class LuaVirtualMachine
             State = context.State,
             Thread = context.Thread,
             ArgumentCount = arguments,
-            FrameBase = frame.Base,
             ReturnFrameBase = frame.ReturnBase,
             CallerInstructionIndex = frame.CallerInstructionIndex,
         }, context.CancellationToken);

+ 5 - 6
src/Lua/Runtime/Tracebacks.cs

@@ -11,9 +11,7 @@ public class Traceback(LuaState state)
     public required LuaClosure RootFunc { get; init; }
     public required CallStackFrame[] StackFrames { get; init; }
 
-    internal string RootChunkName => RootFunc.Proto.ChunkName;
-    
-    internal void WriteLastLuaTrace(ref PooledList<char> list )
+    internal void WriteLastLuaTrace(ref PooledList<char> list)
     {
         var intFormatBuffer = (stackalloc char[15]);
         var shortSourceBuffer = (stackalloc char[59]);
@@ -37,10 +35,10 @@ public class Traceback(LuaState state)
                     p.LineInfo[frame.CallerInstructionIndex].TryFormat(intFormatBuffer, out var charsWritten, provider: CultureInfo.InvariantCulture);
                     list.AddRange(intFormatBuffer[..charsWritten]);
                 }
+
                 return;
             }
         }
-        
     }
 
     public int LastLine
@@ -74,13 +72,14 @@ public class Traceback(LuaState state)
     {
         return GetTracebackString(State, RootFunc, StackFrames, LuaValue.Nil);
     }
-    
+
     public string ToString(int skipFrames)
     {
-        if(skipFrames < 0 || skipFrames >= StackFrames.Length)
+        if (skipFrames < 0 || skipFrames >= StackFrames.Length)
         {
             return "stack traceback:\n";
         }
+
         return GetTracebackString(State, RootFunc, StackFrames[..^skipFrames], LuaValue.Nil);
     }
 

+ 4 - 5
src/Lua/Standard/BasicLibrary.cs

@@ -248,7 +248,7 @@ public sealed class BasicLibrary
         var arg0 = context.GetArgument<LuaFunction>(0);
         try
         {
-            var count = await arg0.InvokeAsync(context with { State = context.State, ArgumentCount = context.ArgumentCount - 1, FrameBase = context.FrameBase + 1, ReturnFrameBase = context.ReturnFrameBase + 1 }, cancellationToken);
+            var count = await arg0.InvokeAsync(context with { ArgumentCount = context.ArgumentCount - 1, ReturnFrameBase = context.ReturnFrameBase + 1 }, cancellationToken);
 
             context.Thread.Stack.Get(context.ReturnFrameBase) = true;
             return count + 1;
@@ -270,9 +270,8 @@ public sealed class BasicLibrary
     {
         for (int i = 0; i < context.ArgumentCount; i++)
         {
-            var top = context.Thread.Stack.Count;
             await context.Arguments[i].CallToStringAsync(context, cancellationToken);
-            Console.Write(context.Thread.Stack.Get(top).ToString());
+            Console.Write(context.Thread.Stack.Pop().Read<string>());
             Console.Write('\t');
         }
 
@@ -549,7 +548,7 @@ public sealed class BasicLibrary
 
         try
         {
-            var count = await arg0.InvokeAsync(context with { State = context.State, ArgumentCount = context.ArgumentCount - 2, FrameBase = context.FrameBase + 2, ReturnFrameBase = context.ReturnFrameBase + 1 }, cancellationToken);
+            var count = await arg0.InvokeAsync(context with { ArgumentCount = context.ArgumentCount - 2, ReturnFrameBase = context.ReturnFrameBase + 1 }, cancellationToken);
 
             context.Thread.Stack.Get(context.ReturnFrameBase) = true;
             return count + 1;
@@ -561,7 +560,7 @@ public sealed class BasicLibrary
             context.State.Push(error);
 
             // invoke error handler
-            var count = await arg1.InvokeAsync(context with { State = context.State, ArgumentCount = 1, FrameBase = context.Thread.Stack.Count - 1, ReturnFrameBase = context.ReturnFrameBase + 1 }, cancellationToken);
+            var count = await arg1.InvokeAsync(context with { ArgumentCount = 1, ReturnFrameBase = context.ReturnFrameBase + 1 }, cancellationToken);
             context.Thread.Stack.Get(context.ReturnFrameBase) = false;
             return count + 1;
         }

+ 2 - 5
src/Lua/Standard/CoroutineLibrary.cs

@@ -30,7 +30,7 @@ public sealed class CoroutineLibrary
     public ValueTask<int> Resume(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var thread = context.GetArgument<LuaThread>(0);
-        return thread.ResumeAsync(context, cancellationToken);
+        return thread.ResumeAsync(context with{ArgumentCount = context.ArgumentCount-1}, cancellationToken);
     }
 
     public ValueTask<int> Running(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
@@ -67,13 +67,10 @@ public sealed class CoroutineLibrary
 
                 var stack = context.Thread.Stack;
                 var frameBase = stack.Count;
-
-                stack.Push(thread);
-                stack.PushRange(context.Arguments);
                 context.Thread.PushCallStackFrame(new() { Base = frameBase, ReturnBase = context.ReturnFrameBase, VariableArgumentCount = 0, Function = coroutine.Function });
                 try
                 {
-                    await thread.ResumeAsync(context with { ArgumentCount = context.ArgumentCount + 1, FrameBase = frameBase, ReturnFrameBase = context.ReturnFrameBase, }, cancellationToken);
+                    await thread.ResumeAsync(context, cancellationToken);
                     var result = context.GetReturnBuffer(context.Thread.Stack.Count - context.ReturnFrameBase);
                     result[1..].CopyTo(result);
                     context.Thread.Stack.Pop();

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

@@ -463,7 +463,6 @@ public class DebugLibrary
                 State = context.State,
                 Thread = context.Thread,
                 ArgumentCount = 2,
-                FrameBase = stack.Count - 2,
                 ReturnFrameBase = stack.Count - 2,
             };
             var frame = new CallStackFrame

+ 2 - 4
src/Lua/Standard/StringLibrary.cs

@@ -278,9 +278,7 @@ public sealed class StringLibrary
                         break;
                     case 's':
                         {
-                            var top = stack.Count;
-                            stack.Push(default);
-                            await parameter.CallToStringAsync(context with { ReturnFrameBase = top }, cancellationToken);
+                            await parameter.CallToStringAsync(context, cancellationToken);
                             formattedValue = stack.Pop().Read<string>();
                         }
 
@@ -515,7 +513,7 @@ public sealed class StringLibrary
                 }
 
 
-                await func.InvokeAsync(context with { ArgumentCount = match.Groups.Count, FrameBase = context.Thread.Stack.Count - context.ArgumentCount, }, cancellationToken);
+                await func.InvokeAsync(context with { ArgumentCount = match.Groups.Count }, cancellationToken);
 
                 result = context.Thread.Stack.Get(context.ReturnFrameBase);
             }

+ 6 - 6
src/Lua/Standard/TableLibrary.cs

@@ -27,14 +27,14 @@ public sealed class TableLibrary
 
     // TODO: optimize
     private static readonly Prototype defaultComparer = new Prototype(
-        "comp", 0,0,2,2,false,
+        "comp", 0, 0, 2, 2, false,
         [],
         [
             Instruction.Le(1, 0, 1),
             Instruction.LoadBool(2, 1, 1),
             Instruction.LoadBool(2, 0, 0),
             Instruction.Return(2, 2),
-        ],[],[0,0,0,0],[new LocalVariable(){Name = "a",StartPc = 0,EndPc = 4}, new LocalVariable(){Name = "b",StartPc = 0,EndPc = 4}],
+        ], [], [0, 0, 0, 0], [new LocalVariable() { Name = "a", StartPc = 0, EndPc = 4 }, new LocalVariable() { Name = "b", StartPc = 0, EndPc = 4 }],
         []
     );
 
@@ -150,10 +150,10 @@ public sealed class TableLibrary
         var arg1 = context.HasArgument(1)
             ? context.GetArgument<LuaFunction>(1)
             : new LuaClosure(context.State, defaultComparer);
-        
+
         // discard extra  arguments
         context = context with { ArgumentCount = 2 };
-        context.Thread.Stack.PopUntil(context.FrameBase+2);
+        context.Thread.Stack.PopUntil(context.FrameBase + 2);
 
         context.Thread.PushCallStackFrame(new() { Base = context.FrameBase, ReturnBase = context.ReturnFrameBase, VariableArgumentCount = 0, Function = arg1 });
         try
@@ -188,7 +188,7 @@ public sealed class TableLibrary
             var top = stack.Count;
             stack.Push(memory.Span[j]);
             stack.Push(pivot);
-            await comparer.InvokeAsync(context with { ArgumentCount = 2, FrameBase = stack.Count - context.ArgumentCount, ReturnFrameBase = top }, cancellationToken);
+            await comparer.InvokeAsync(context with { ArgumentCount = 2, ReturnFrameBase = top }, cancellationToken);
 
             if (context.Thread.Stack.Get(top).ToBoolean())
             {
@@ -220,7 +220,7 @@ public sealed class TableLibrary
             : arg0.ArrayLength;
 
         var index = 0;
-        arg1 = Math.Min(arg1, arg2+1);
+        arg1 = Math.Min(arg1, arg2 + 1);
         var count = (int)(arg2 - arg1 + 1);
         var buffer = context.GetReturnBuffer(count);
         for (long i = arg1; i <= arg2; i++)

+ 4 - 6
tests/Lua.Tests/LuaTests.cs

@@ -13,7 +13,7 @@ public class LuaTests
         state = LuaState.Create();
         state.OpenStandardLibraries();
     }
-    
+
 
     [Test]
     [TestCase("tests-lua/code.lua")]
@@ -34,19 +34,17 @@ public class LuaTests
     [TestCase("tests-lua/coroutine.lua")]
     [TestCase("tests-lua/db.lua")]
     [TestCase("tests-lua/verybig.lua")]
-    
     public async Task Test_Lua(string file)
     {
         var path = FileHelper.GetAbsolutePath(file);
         try
         {
-            await state.DoFileAsync(FileHelper.GetAbsolutePath(file));
+            await state.DoFileAsync(path);
         }
         catch (LuaRuntimeException e)
         {
-            var traceback = e.LuaTraceback;
-            var line = traceback.LastLine;
-            throw new Exception($"{path}:line {line}\n{e.InnerException}\n{e} ");
+            var line = e.LuaTraceback.LastLine;
+            throw new Exception($"{path}:line {line}\n{e.InnerException}\n {e}");
         }
     }
 }