TableIteratorsModule.cs 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using MoonSharp.Interpreter.Execution;
  6. namespace MoonSharp.Interpreter.CoreLib
  7. {
  8. [MoonSharpModule]
  9. public class TableIteratorsModule
  10. {
  11. // ipairs (t)
  12. // -------------------------------------------------------------------------------------------------------------------
  13. // If t has a metamethod __ipairs, calls it with t as argument and returns the first three results from the call.
  14. // Otherwise, returns three values: an iterator function, the table t, and 0, so that the construction
  15. // for i,v in ipairs(t) do body end
  16. // will iterate over the pairs (1,t[1]), (2,t[2]), ..., up to the first integer key absent from the table.
  17. [MoonSharpMethod]
  18. public static DynValue ipairs(ScriptExecutionContext executionContext, CallbackArguments args)
  19. {
  20. DynValue table = args[0];
  21. DynValue meta = executionContext.GetMetamethodTailCall(table, "__ipairs", args.GetArray());
  22. return meta ?? DynValue.NewTuple(DynValue.NewCallback(__next_i), table, DynValue.NewNumber(0));
  23. }
  24. // pairs (t)
  25. // -------------------------------------------------------------------------------------------------------------------
  26. // If t has a metamethod __pairs, calls it with t as argument and returns the first three results from the call.
  27. // Otherwise, returns three values: the next function, the table t, and nil, so that the construction
  28. // for k,v in pairs(t) do body end
  29. // will iterate over all key–value pairs of table t.
  30. // See function next for the caveats of modifying the table during its traversal.
  31. [MoonSharpMethod]
  32. public static DynValue pairs(ScriptExecutionContext executionContext, CallbackArguments args)
  33. {
  34. DynValue table = args[0];
  35. DynValue meta = executionContext.GetMetamethodTailCall(table, "__pairs", args.GetArray());
  36. return meta ?? DynValue.NewTuple(DynValue.NewCallback(next), table);
  37. }
  38. // next (table [, index])
  39. // -------------------------------------------------------------------------------------------------------------------
  40. // Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an
  41. // index in this table. next returns the next index of the table and its associated value.
  42. // When called with nil as its second argument, next returns an initial index and its associated value.
  43. // When called with the last index, or with nil in an empty table, next returns nil. If the second argument is absent,
  44. // then it is interpreted as nil. In particular, you can use next(t) to check whether a table is empty.
  45. // The order in which the indices are enumerated is not specified, even for numeric indices.
  46. // (To traverse a table in numeric order, use a numerical for.)
  47. // The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table.
  48. // You may however modify existing fields. In particular, you may clear existing fields.
  49. [MoonSharpMethod]
  50. public static DynValue next(ScriptExecutionContext executionContext, CallbackArguments args)
  51. {
  52. DynValue table = args.AsType(0, "next", DataType.Table);
  53. DynValue index = args[1];
  54. TablePair? pair = table.Table.NextKey(index);
  55. if (pair.HasValue)
  56. return DynValue.NewTuple(pair.Value.Key, pair.Value.Value);
  57. else
  58. throw new ScriptRuntimeException("invalid key to 'next'");
  59. }
  60. // __next_i (table [, index])
  61. // -------------------------------------------------------------------------------------------------------------------
  62. // Allows a program to traverse all fields of an array. index is an integer number
  63. public static DynValue __next_i(ScriptExecutionContext executionContext, CallbackArguments args)
  64. {
  65. DynValue table = args.AsType(0, "!!next_i!!", DataType.Table);
  66. DynValue index = args.AsType(1, "!!next_i!!", DataType.Number);
  67. int idx = ((int)index.Number) + 1;
  68. DynValue val = table.Table.Get(idx);
  69. if (val.Type != DataType.Nil)
  70. {
  71. return DynValue.NewTuple(DynValue.NewNumber(idx), val);
  72. }
  73. else
  74. {
  75. return DynValue.Nil;
  76. }
  77. }
  78. }
  79. }