Closure.cs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. using System.Runtime.CompilerServices;
  2. using Lua.Internal;
  3. namespace Lua.Runtime;
  4. public sealed class Closure : LuaFunction
  5. {
  6. Chunk proto;
  7. FastListCore<UpValue> upValues;
  8. public Closure(LuaState state, Chunk proto, LuaTable? environment = null)
  9. : base(proto.Name, (context, buffer, ct) => LuaVirtualMachine.ExecuteClosureAsync(context.State, buffer, ct))
  10. {
  11. this.proto = proto;
  12. // add upvalues
  13. for (int i = 0; i < proto.UpValues.Length; i++)
  14. {
  15. var description = proto.UpValues[i];
  16. var upValue = GetUpValueFromDescription(state, state.CurrentThread, environment == null ? state.EnvUpValue : UpValue.Closed(environment), description);
  17. upValues.Add(upValue);
  18. }
  19. }
  20. public Chunk Proto => proto;
  21. public ReadOnlySpan<UpValue> UpValues => upValues.AsSpan();
  22. internal Span<UpValue> GetUpValuesSpan() => upValues.AsSpan();
  23. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  24. internal LuaValue GetUpValue(int index)
  25. {
  26. return upValues[index].GetValue();
  27. }
  28. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  29. internal ref readonly LuaValue GetUpValueRef(int index)
  30. {
  31. return ref upValues[index].GetValueRef();
  32. }
  33. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  34. internal void SetUpValue(int index, LuaValue value)
  35. {
  36. upValues[index].SetValue(value);
  37. }
  38. static UpValue GetUpValueFromDescription(LuaState state, LuaThread thread, UpValue envUpValue, UpValueInfo description)
  39. {
  40. if (description.IsInRegister)
  41. {
  42. return state.GetOrAddUpValue(thread, thread.GetCallStackFrames()[^1].Base + description.Index);
  43. }
  44. if (description.Index == -1) // -1 is global environment
  45. {
  46. return envUpValue;
  47. }
  48. if (thread.GetCallStackFrames()[^1].Function is Closure parentClosure)
  49. {
  50. return parentClosure.UpValues[description.Index];
  51. }
  52. throw new Exception();
  53. }
  54. }