IPairsFunction.cs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. using Lua.Runtime;
  2. namespace Lua.Standard.Basic;
  3. public sealed class IPairsFunction : LuaFunction
  4. {
  5. public override string Name => "ipairs";
  6. public static readonly IPairsFunction Instance = new();
  7. protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  8. {
  9. var arg0 = context.GetArgument<LuaTable>(0);
  10. // If table has a metamethod __ipairs, calls it with table as argument and returns the first three results from the call.
  11. if (arg0.Metatable != null && arg0.Metatable.TryGetValue(Metamethods.IPairs, out var metamethod))
  12. {
  13. if (!metamethod.TryRead<LuaFunction>(out var function))
  14. {
  15. LuaRuntimeException.AttemptInvalidOperation(context.State.GetTraceback(), "call", metamethod);
  16. }
  17. return function.InvokeAsync(context, buffer, cancellationToken);
  18. }
  19. buffer.Span[0] = new Iterator(arg0);
  20. return new(1);
  21. }
  22. class Iterator(LuaTable table) : LuaFunction
  23. {
  24. int i;
  25. protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  26. {
  27. i++;
  28. if (table.TryGetValue(i, out var value))
  29. {
  30. buffer.Span[0] = i;
  31. buffer.Span[1] = value;
  32. }
  33. else
  34. {
  35. buffer.Span[0] = LuaValue.Nil;
  36. buffer.Span[1] = LuaValue.Nil;
  37. }
  38. return new(2);
  39. }
  40. }
  41. }