Closure.cs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. using Lua.Internal;
  2. namespace Lua.Runtime;
  3. public sealed class Closure : LuaFunction
  4. {
  5. Chunk proto;
  6. FastListCore<UpValue> upValues;
  7. public Closure(LuaState state, Chunk proto, LuaTable? environment = null)
  8. {
  9. this.proto = proto;
  10. // add upvalues
  11. for (int i = 0; i < proto.UpValues.Length; i++)
  12. {
  13. var description = proto.UpValues[i];
  14. var upValue = GetUpValueFromDescription(state, environment == null ? state.EnvUpValue : UpValue.Closed(state.CurrentThread, environment), proto, description);
  15. upValues.Add(upValue);
  16. }
  17. }
  18. public Chunk Proto => proto;
  19. public ReadOnlySpan<UpValue> UpValues => upValues.AsSpan();
  20. public override string Name => Proto.Name;
  21. protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  22. {
  23. return LuaVirtualMachine.ExecuteClosureAsync(context.State, this, context.State.CurrentThread.GetCurrentFrame(), buffer, cancellationToken);
  24. }
  25. static UpValue GetUpValueFromDescription(LuaState state, UpValue envUpValue, Chunk proto, UpValueInfo description)
  26. {
  27. if (description.IsInRegister)
  28. {
  29. var thread = state.CurrentThread;
  30. return state.GetOrAddUpValue(thread, thread.GetCurrentFrame().Base + description.Index);
  31. }
  32. else if (description.Index == -1) // -1 is global environment
  33. {
  34. return envUpValue;
  35. }
  36. else
  37. {
  38. return GetUpValueFromDescription(state, envUpValue, proto.Parent!, proto.Parent!.UpValues[description.Index]);
  39. }
  40. }
  41. }