Browse Source

Add: debug.upvaluejoin

Akeit0 10 months ago
parent
commit
320a634779

+ 1 - 0
src/Lua/Runtime/Closure.cs

@@ -24,6 +24,7 @@ public sealed class Closure : LuaFunction
 
     public Chunk Proto => proto;
     public ReadOnlySpan<UpValue> UpValues => upValues.AsSpan();
+    internal Span<UpValue> GetUpValuesSpan() => upValues.AsSpan();
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     internal LuaValue GetUpValue(int index)

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

@@ -18,7 +18,8 @@ public class DebugLibrary
             new("getmetatable", GetMetatable),
             new("setmetatable", SetMetatable),
             new("traceback", Traceback),
-            new("getregistry", GetRegistry)
+            new("getregistry", GetRegistry),
+            new("upvaluejoin", UpValueJoin)
         ];
     }
 
@@ -283,4 +284,33 @@ public class DebugLibrary
         buffer.Span[0] = context.State.Registry;
         return new(1);
     }
+
+    public ValueTask<int> UpValueJoin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var n2 = context.GetArgument<int>(3);
+        var f2 = context.GetArgument<LuaFunction>(2);
+        var n1 = context.GetArgument<int>(1);
+        var f1 = context.GetArgument<LuaFunction>(0);
+
+        if (f1 is not Closure closure1 || f2 is not Closure closure2)
+        {
+            buffer.Span[0] = LuaValue.Nil;
+            return new(1);
+        }
+
+        var upValues1 = closure1.GetUpValuesSpan();
+        var upValues2 = closure2.GetUpValuesSpan();
+        if (n1 <= 0 || n1 > upValues1.Length)
+        {
+            context.ThrowBadArgument(1, "invalid upvalue index");
+        }
+
+        if (n2 < 0 || n2 > upValues2.Length)
+        {
+            context.ThrowBadArgument(3, "invalid upvalue index");
+        }
+
+        upValues1[n1 - 1] = upValues2[n2 - 1];
+        return new(0);
+    }
 }

+ 16 - 0
tests/Lua.Tests/tests-lua/db-mini.lua

@@ -53,6 +53,22 @@ local mt = {
         return o+k
     end
 }
+
+local a = 1
+local b = 2
+local function f()
+    return a
+end
+local function g()
+    return b
+end
+
+debug.upvaluejoin(f,1,g,1)
+
+assert(f() == 2)
+b=3
+assert(f() == 3)
+
 debug.setmetatable(10, mt)
 assert(debug.getmetatable(10) == mt)
 a = 10