Browse Source

api revision

Akeit0 7 months ago
parent
commit
2633de4751

+ 13 - 8
sanbox/ConsoleApp2/Program.cs

@@ -37,7 +37,7 @@ state.OpenStandardLibraries();
             local args = {...}
             local args = {...}
             for i = 1, #args do
             for i = 1, #args do
                 local v = args[i]
                 local v = args[i]
-                print('To Lua:\t' .. coroutine.yield('from C# ' .. i ..' '..v))
+                print('In Lua:', coroutine.yield('from lua', i,v))
             end
             end
         end
         end
         """, "coroutine");
         """, "coroutine");
@@ -45,21 +45,26 @@ state.OpenStandardLibraries();
     using var coroutineLease = state.MainThread.RentCoroutine(f);
     using var coroutineLease = state.MainThread.RentCoroutine(f);
     var coroutine = coroutineLease.Thread;
     var coroutine = coroutineLease.Thread;
     {
     {
-        coroutine.Push("a", "b", "c", "d", "e");
+        var stack =new LuaStack();
+        stack.PushRange("a", "b", "c", "d", "e");
 
 
         for (int i = 0; coroutine.CanResume; i++)
         for (int i = 0; coroutine.CanResume; i++)
         {
         {
-            if (i != 0) coroutine.Push($"from C# {i}");
-            var count = await coroutine.ResumeAsync();
-            using var resumeResult = coroutine.ReadReturnValues(count);
-            Console.Write("To C#:\t");
-            for (int j = 0; j < resumeResult.Length; j++)
+            if (i != 0)
             {
             {
-                Console.Write(resumeResult[j]);
+                stack.Push("from C# ");
+                stack.Push(i);
+            }
+            await coroutine.ResumeAsync(stack);
+            Console.Write("In C#:\t");
+            for (int j = 1; j < stack.Count; j++)
+            {
+                Console.Write(stack[j]);
                 Console.Write('\t');
                 Console.Write('\t');
             }
             }
 
 
             Console.WriteLine();
             Console.WriteLine();
+            stack.Clear();
         }
         }
     }
     }
 }
 }

+ 2 - 4
src/Lua/CodeAnalysis/Compilation/Parser.cs

@@ -1,12 +1,10 @@
 using Lua.Internal;
 using Lua.Internal;
 using Lua.Runtime;
 using Lua.Runtime;
 using System.Buffers;
 using System.Buffers;
-
-namespace Lua.CodeAnalysis.Compilation;
-
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
-using static Lua.Runtime.Instruction;
 using static System.Diagnostics.Debug;
 using static System.Diagnostics.Debug;
+namespace Lua.CodeAnalysis.Compilation;
+
 using static Function;
 using static Function;
 using static Scanner;
 using static Scanner;
 using static Constants;
 using static Constants;

+ 0 - 1
src/Lua/CodeAnalysis/Compilation/PrototypeBuilder.cs

@@ -1,5 +1,4 @@
 using Lua.Internal;
 using Lua.Internal;
-using System;
 using Lua.Runtime;
 using Lua.Runtime;
 
 
 namespace Lua.CodeAnalysis.Compilation;
 namespace Lua.CodeAnalysis.Compilation;

+ 91 - 93
src/Lua/LuaCoroutine.cs

@@ -72,18 +72,12 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
 
 
     public bool CanResume => status == (byte)LuaThreadStatus.Suspended;
     public bool CanResume => status == (byte)LuaThreadStatus.Suspended;
 
 
-    int lastBase;
-
-    private LuaStack? stackForDead;
-
-    LuaStack GetStackForDead(int capacity)
+    public  ValueTask<int> ResumeAsync(LuaStack stack, CancellationToken cancellationToken = default)
     {
     {
-        stackForDead ??= new LuaStack(capacity);
-        stackForDead.Clear();
-        return stackForDead;
+        return ResumeAsync(stack,stack.Count,0, cancellationToken);
     }
     }
 
 
-    public async ValueTask<int> ResumeAsync(CancellationToken cancellationToken = default)
+    public async ValueTask<int> ResumeAsync(LuaStack stack, int argCount, int returnBase,CancellationToken cancellationToken = default)
     {
     {
         if (isFirstCall)
         if (isFirstCall)
         {
         {
@@ -92,108 +86,112 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
         }
         }
 
 
         switch ((LuaThreadStatus)Volatile.Read(ref status))
         switch ((LuaThreadStatus)Volatile.Read(ref status))
-        {
-            case LuaThreadStatus.Suspended:
-                Volatile.Write(ref status, (byte)LuaThreadStatus.Running);
+            {
+                case LuaThreadStatus.Suspended:
+                    Volatile.Write(ref status, (byte)LuaThreadStatus.Running);
 
 
-                if (!isFirstCall)
-                {
-                    yield.SetResult(new()
+                    if (!isFirstCall)
+                    {
+                        yield.SetResult(new()
+                        {
+                            Results = argCount == 0
+                                ? []
+                                : stack.AsSpan()[^argCount..].ToArray()
+                        });
+                    }
+
+                    break;
+                case LuaThreadStatus.Normal:
+                case LuaThreadStatus.Running:
+                    if (IsProtectedMode)
+                    {
+                        stack.PopUntil(returnBase);
+                        stack.Push(false);
+                        stack.Push( "cannot resume non-suspended coroutine");
+                        return 2;
+                    }
+                    else
+                    {
+                        throw new LuaException( "cannot resume non-suspended coroutine");
+                    }
+                case LuaThreadStatus.Dead:
+                    if (IsProtectedMode)
                     {
                     {
-                        Results = lastBase == Stack.Count
-                            ? []
-                            : Stack.AsSpan()[lastBase..].ToArray()
-                    });
-                    Stack.PopUntil(lastBase);
+                        stack.PopUntil(returnBase);
+                        stack.Push(false);
+                        stack.Push( "cannot resume non-suspended coroutine");
+                        return 2;
+                    }
+                    else
+                    {
+                        throw new LuaException("cannot resume dead coroutine");
+                    }
+            }
+
+            var resumeTask = new ValueTask<ResumeContext>(this, resume.Version);
+
+            CancellationTokenRegistration registration = default;
+            if (cancellationToken.CanBeCanceled)
+            {
+                registration = cancellationToken.UnsafeRegister(static x =>
+                {
+                    var coroutine = (LuaCoroutine)x!;
+                    coroutine.yield.SetException(new OperationCanceledException());
+                }, this);
+            }
+
+            try
+            {
+                if (isFirstCall)
+                {
+                    Stack.PushRange(stack.AsSpan()[^argCount..]);
+                    functionTask = Function.InvokeAsync(new() { Thread = this, ArgumentCount = Stack.Count, ReturnFrameBase = 0 }, cancellationToken).Preserve();
+
+                    Volatile.Write(ref isFirstCall, false);
                 }
                 }
 
 
-                break;
-            case LuaThreadStatus.Normal:
-            case LuaThreadStatus.Running:
-                if (IsProtectedMode)
+                var (index, result0, result1) = await ValueTaskEx.WhenAny(resumeTask, functionTask!);
+
+                if (index == 0)
                 {
                 {
-                    Stack.PopUntil(lastBase);
-                    Stack.Push("cannot resume non-suspended coroutine");
-                    return 1;
+                    var results = result0.Results;
+                    stack.PopUntil(returnBase);
+                    stack.Push(true);
+                    stack.PushRange(results.AsSpan());
+                    return results.Length+1;
                 }
                 }
                 else
                 else
                 {
                 {
-                    throw new LuaException("cannot resume non-suspended coroutine");
+                    Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
+                    stack.PopUntil(returnBase);
+                    stack.Push(true);
+                    stack.PushRange(Stack.AsSpan());
+                    ReleaseCore();
+                    return stack.Count-returnBase;
                 }
                 }
-            case LuaThreadStatus.Dead:
+            }
+            catch (Exception ex) when (ex is not OperationCanceledException)
+            {
                 if (IsProtectedMode)
                 if (IsProtectedMode)
                 {
                 {
-                    var stack = GetStackForDead(1);
-                    stack.Push("cannot resume dead coroutine");
-                    return 1;
+                    traceback = (ex as LuaRuntimeException)?.LuaTraceback;
+                    Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
+                    ReleaseCore();
+                    stack.PopUntil(returnBase);
+                    stack.Push(false);
+                    stack.Push( ex is LuaRuntimeException luaEx ? luaEx.ErrorObject : ex.Message);
+                    return 2;
                 }
                 }
                 else
                 else
                 {
                 {
-                    throw new LuaException("cannot resume dead coroutine");
+                    throw;
                 }
                 }
-        }
-
-        var resumeTask = new ValueTask<ResumeContext>(this, resume.Version);
-
-        CancellationTokenRegistration registration = default;
-        if (cancellationToken.CanBeCanceled)
-        {
-            registration = cancellationToken.UnsafeRegister(static x =>
-            {
-                var coroutine = (LuaCoroutine)x!;
-                coroutine.yield.SetException(new OperationCanceledException());
-            }, this);
-        }
-
-        try
-        {
-            if (isFirstCall)
-            {
-                functionTask = Function.InvokeAsync(new() { Thread = this, ArgumentCount = Stack.Count, ReturnFrameBase = 0 }, cancellationToken).Preserve();
-
-                Volatile.Write(ref isFirstCall, false);
             }
             }
-
-            var (index, result0, result1) = await ValueTaskEx.WhenAny(resumeTask, functionTask!);
-
-            if (index == 0)
-            {
-                var results = result0.Results;
-                Stack.PushRange(results.AsSpan());
-                lastBase = Stack.Count - results.Length;
-                return results.Length;
-            }
-            else
-            {
-                Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
-                var results = Stack.AsSpan();
-                var stack = GetStackForDead(Math.Max(1, results.Length));
-                stack.PushRange(results);
-                ReleaseCore();
-                return results.Length;
-            }
-        }
-        catch (Exception ex) when (ex is not OperationCanceledException)
-        {
-            if (IsProtectedMode)
-            {
-                traceback = (ex as LuaRuntimeException)?.LuaTraceback;
-                Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
-                ReleaseCore();
-                var stack = GetStackForDead(1);
-                stack.Push(ex is LuaRuntimeException luaEx ? luaEx.ErrorObject : ex.Message);
-                return 1;
-            }
-            else
+            finally
             {
             {
-                throw;
+                registration.Dispose();
+                resume.Reset();
             }
             }
-        }
-        finally
-        {
-            registration.Dispose();
-            resume.Reset();
-        }
     }
     }
 
 
     public override async ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
     public override async ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)

+ 8 - 1
src/Lua/LuaThread.cs

@@ -105,7 +105,7 @@ public abstract class LuaThread
         {
         {
             await closure.InvokeAsync(new()
             await closure.InvokeAsync(new()
             {
             {
-                Thread = this, ArgumentCount = 0, ReturnFrameBase = 0, SourceLine = null,
+                Thread = this, ArgumentCount = Stack.Count, ReturnFrameBase = 0, SourceLine = null,
             }, cancellationToken);
             }, cancellationToken);
 
 
             return Stack.Count;
             return Stack.Count;
@@ -126,6 +126,13 @@ public abstract class LuaThread
         }
         }
     }
     }
 
 
+    public Traceback GetTraceback()
+    {
+        var frames = this.GetCallStackFrames();
+
+        return new(State) { RootFunc = frames[0].Function, StackFrames = this.GetCallStackFrames()[1..].ToArray() };
+    }
+
     protected void ThrowIfRunning()
     protected void ThrowIfRunning()
     {
     {
         if (IsRunning)
         if (IsRunning)

+ 0 - 6
src/Lua/LuaThreadExtensions.cs

@@ -128,10 +128,4 @@ public static class LuaThreadExtensions
         coreData!.CallStack.Pop();
         coreData!.CallStack.Pop();
     }
     }
     
     
-    public static Traceback GetTraceback(this LuaThread thread)
-    {
-        var frames = thread.GetCallStackFrames();
-
-        return new(thread.State) { RootFunc = frames[0].Function, StackFrames = thread.GetCallStackFrames()[1..].ToArray() };
-    }
 }
 }

+ 3 - 1
src/Lua/Runtime/LuaStack.cs

@@ -12,6 +12,8 @@ public sealed class LuaStack(int initialSize = 256)
 
 
     public int Count => top;
     public int Count => top;
 
 
+    public ref LuaValue this[int index] => ref Get(index);
+
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public void EnsureCapacity(int newSize)
     public void EnsureCapacity(int newSize)
     {
     {
@@ -52,7 +54,7 @@ public sealed class LuaStack(int initialSize = 256)
     }
     }
 
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public void PushRange(ReadOnlySpan<LuaValue> values)
+    public void PushRange(params ReadOnlySpan<LuaValue> values)
     {
     {
         EnsureCapacity(top + values.Length);
         EnsureCapacity(top + values.Length);
         values.CopyTo(array.AsSpan()[top..]);
         values.CopyTo(array.AsSpan()[top..]);

+ 3 - 3
src/Lua/Standard/BasicLibrary.cs

@@ -91,7 +91,7 @@ public sealed class BasicLibrary
         var bytes = await File.ReadAllBytesAsync(arg0, cancellationToken);
         var bytes = await File.ReadAllBytesAsync(arg0, cancellationToken);
         var fileName = "@" + Path.GetFileName(arg0);
         var fileName = "@" + Path.GetFileName(arg0);
 
 
-        return await context.State.Compile(bytes, fileName).InvokeAsync(context, cancellationToken);
+        return await context.State.Load(bytes, fileName).InvokeAsync(context, cancellationToken);
     }
     }
 
 
     public ValueTask<int> Error(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     public ValueTask<int> Error(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
@@ -161,7 +161,7 @@ public sealed class BasicLibrary
         {
         {
             var bytes = await File.ReadAllBytesAsync(arg0, cancellationToken);
             var bytes = await File.ReadAllBytesAsync(arg0, cancellationToken);
             var fileName = "@" + Path.GetFileName(arg0);
             var fileName = "@" + Path.GetFileName(arg0);
-            return context.Return(context.State.Compile(bytes, fileName, mode, arg2));
+            return context.Return(context.State.Load(bytes, fileName, mode, arg2));
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
@@ -191,7 +191,7 @@ public sealed class BasicLibrary
         {
         {
             if (arg0.TryRead<string>(out var str))
             if (arg0.TryRead<string>(out var str))
             {
             {
-                return new(context.Return(context.State.Compile(str, name ?? str, arg3)));
+                return new(context.Return(context.State.Load(str, name ?? str, arg3)));
             }
             }
             else if (arg0.TryRead<LuaFunction>(out var function))
             else if (arg0.TryRead<LuaFunction>(out var function))
             {
             {

+ 1 - 5
src/Lua/Standard/ModuleLibrary.cs

@@ -1,7 +1,3 @@
-using Lua.CodeAnalysis.Compilation;
-using Lua.Internal;
-using Lua.Runtime;
-
 namespace Lua.Standard;
 namespace Lua.Standard;
 
 
 public sealed class ModuleLibrary
 public sealed class ModuleLibrary
@@ -23,7 +19,7 @@ public sealed class ModuleLibrary
         if (!loaded.TryGetValue(arg0, out var loadedTable))
         if (!loaded.TryGetValue(arg0, out var loadedTable))
         {
         {
             var module = await context.State.ModuleLoader.LoadAsync(arg0, cancellationToken);
             var module = await context.State.ModuleLoader.LoadAsync(arg0, cancellationToken);
-            await context.State.Compile(module.ReadText(), module.Name).InvokeAsync(context, cancellationToken);
+            await context.State.Load(module.ReadText(), module.Name).InvokeAsync(context, cancellationToken);
 
 
             loadedTable = context.Thread.Stack.Get(context.ReturnFrameBase);
             loadedTable = context.Thread.Stack.Get(context.ReturnFrameBase);
             loaded[arg0] = loadedTable;
             loaded[arg0] = loadedTable;