Browse Source

Fix: nested upvalues not working

AnnulusGames 1 year ago
parent
commit
6f5028d08c
4 changed files with 17 additions and 15 deletions
  1. 2 2
      src/Lua/LuaState.cs
  2. 2 2
      src/Lua/LuaThread.cs
  3. 6 4
      src/Lua/Runtime/Closure.cs
  4. 7 7
      src/Lua/Runtime/UpValue.cs

+ 2 - 2
src/Lua/LuaState.cs

@@ -50,7 +50,7 @@ public sealed class LuaState
     LuaState()
     LuaState()
     {
     {
         environment = new();
         environment = new();
-        envUpValue = UpValue.Closed(mainThread, environment);
+        envUpValue = UpValue.Closed(environment);
     }
     }
 
 
     public async ValueTask<int> RunAsync(Chunk chunk, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     public async ValueTask<int> RunAsync(Chunk chunk, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
@@ -94,7 +94,7 @@ public sealed class LuaState
         {
         {
             StackFrames = threadStack.AsSpan().ToArray()
             StackFrames = threadStack.AsSpan().ToArray()
                 .Append(MainThread)
                 .Append(MainThread)
-                .SelectMany(x => x.GetStackFrames())
+                .SelectMany(x => x.GetCallStackFrames()[1..].ToArray())
                 .ToArray()
                 .ToArray()
         };
         };
     }
     }

+ 2 - 2
src/Lua/LuaThread.cs

@@ -24,9 +24,9 @@ public abstract class LuaThread
         return stack.AsSpan();
         return stack.AsSpan();
     }
     }
 
 
-    internal CallStackFrame[] GetStackFrames()
+    internal ReadOnlySpan<CallStackFrame> GetCallStackFrames()
     {
     {
-        return callStack.AsSpan()[1..].ToArray();
+        return callStack.AsSpan();
     }
     }
 
 
     internal void PushCallStackFrame(CallStackFrame frame)
     internal void PushCallStackFrame(CallStackFrame frame)

+ 6 - 4
src/Lua/Runtime/Closure.cs

@@ -15,7 +15,7 @@ public sealed class Closure : LuaFunction
         for (int i = 0; i < proto.UpValues.Length; i++)
         for (int i = 0; i < proto.UpValues.Length; i++)
         {
         {
             var description = proto.UpValues[i];
             var description = proto.UpValues[i];
-            var upValue = GetUpValueFromDescription(state, environment == null ? state.EnvUpValue : UpValue.Closed(state.CurrentThread, environment), proto, description);
+            var upValue = GetUpValueFromDescription(state, environment == null ? state.EnvUpValue : UpValue.Closed(environment), proto, description, 1);
             upValues.Add(upValue);
             upValues.Add(upValue);
         }
         }
     }
     }
@@ -30,12 +30,14 @@ public sealed class Closure : LuaFunction
         return LuaVirtualMachine.ExecuteClosureAsync(context.State, this, context.State.CurrentThread.GetCurrentFrame(), buffer, cancellationToken);
         return LuaVirtualMachine.ExecuteClosureAsync(context.State, this, context.State.CurrentThread.GetCurrentFrame(), buffer, cancellationToken);
     }
     }
 
 
-    static UpValue GetUpValueFromDescription(LuaState state, UpValue envUpValue, Chunk proto, UpValueInfo description)
+    static UpValue GetUpValueFromDescription(LuaState state, UpValue envUpValue, Chunk proto, UpValueInfo description, int depth)
     {
     {
         if (description.IsInRegister)
         if (description.IsInRegister)
         {
         {
             var thread = state.CurrentThread;
             var thread = state.CurrentThread;
-            return state.GetOrAddUpValue(thread, thread.GetCurrentFrame().Base + description.Index);
+            var callStack = thread.GetCallStackFrames();
+            var frame = callStack[^depth];
+            return state.GetOrAddUpValue(thread, frame.Base + description.Index);
         }
         }
         else if (description.Index == -1) // -1 is global environment
         else if (description.Index == -1) // -1 is global environment
         {
         {
@@ -43,7 +45,7 @@ public sealed class Closure : LuaFunction
         }
         }
         else
         else
         {
         {
-            return GetUpValueFromDescription(state, envUpValue, proto.Parent!, proto.Parent!.UpValues[description.Index]);
+            return GetUpValueFromDescription(state, envUpValue, proto.Parent!, proto.Parent!.UpValues[description.Index], depth + 1);
         }
         }
     }
     }
 }
 }

+ 7 - 7
src/Lua/Runtime/UpValue.cs

@@ -7,11 +7,11 @@ public sealed class UpValue
 {
 {
     LuaValue value;
     LuaValue value;
 
 
-    public LuaThread Thread { get; }
+    public LuaThread? Thread { get; }
     public bool IsClosed { get; private set; }
     public bool IsClosed { get; private set; }
     public int RegisterIndex { get; private set; }
     public int RegisterIndex { get; private set; }
 
 
-    UpValue(LuaThread thread)
+    UpValue(LuaThread? thread)
     {
     {
         Thread = thread;
         Thread = thread;
     }
     }
@@ -24,9 +24,9 @@ public sealed class UpValue
         };
         };
     }
     }
 
 
-    public static UpValue Closed(LuaThread thread, LuaValue value)
+    public static UpValue Closed(LuaValue value)
     {
     {
-        return new(thread)
+        return new(null)
         {
         {
             IsClosed = true,
             IsClosed = true,
             value = value
             value = value
@@ -42,7 +42,7 @@ public sealed class UpValue
         }
         }
         else
         else
         {
         {
-            return Thread.Stack.UnsafeGet(RegisterIndex);
+            return Thread!.Stack.UnsafeGet(RegisterIndex);
         }
         }
     }
     }
 
 
@@ -55,7 +55,7 @@ public sealed class UpValue
         }
         }
         else
         else
         {
         {
-            Thread.Stack.UnsafeGet(RegisterIndex) = value;
+            Thread!.Stack.UnsafeGet(RegisterIndex) = value;
         }
         }
     }
     }
 
 
@@ -64,7 +64,7 @@ public sealed class UpValue
     {
     {
         if (!IsClosed)
         if (!IsClosed)
         {
         {
-            value = Thread.Stack.UnsafeGet(RegisterIndex);
+            value = Thread!.Stack.UnsafeGet(RegisterIndex);
         }
         }
 
 
         IsClosed = true;
         IsClosed = true;