CoroutineLibrary.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. namespace Lua.Standard;
  2. public static class CoroutineLibrary
  3. {
  4. public static void OpenCoroutineLibrary(this LuaState state)
  5. {
  6. var coroutine = new LuaTable(0, Functions.Length);
  7. foreach (var func in Functions)
  8. {
  9. coroutine[func.Name] = func;
  10. }
  11. state.Environment["coroutine"] = coroutine;
  12. }
  13. static readonly LuaFunction[] Functions = [
  14. new("create", Create),
  15. new("resume", Resume),
  16. new("running", Running),
  17. new("wrap", Wrap),
  18. new("yield", Yield),
  19. ];
  20. public static ValueTask<int> Create(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  21. {
  22. var arg0 = context.GetArgument<LuaFunction>(0);
  23. buffer.Span[0] = new LuaCoroutine(arg0, true);
  24. return new(1);
  25. }
  26. public static ValueTask<int> Resume(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  27. {
  28. var thread = context.GetArgument<LuaThread>(0);
  29. return thread.ResumeAsync(context, buffer, cancellationToken);
  30. }
  31. public static ValueTask<int> Running(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  32. {
  33. buffer.Span[0] = context.Thread;
  34. buffer.Span[1] = context.Thread == context.State.MainThread;
  35. return new(2);
  36. }
  37. public static ValueTask<int> Status(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  38. {
  39. var thread = context.GetArgument<LuaThread>(0);
  40. buffer.Span[0] = thread.GetStatus() switch
  41. {
  42. LuaThreadStatus.Normal => "normal",
  43. LuaThreadStatus.Suspended => "suspended",
  44. LuaThreadStatus.Running => "running",
  45. LuaThreadStatus.Dead => "dead",
  46. _ => "",
  47. };
  48. return new(1);
  49. }
  50. public static ValueTask<int> Wrap(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  51. {
  52. var arg0 = context.GetArgument<LuaFunction>(0);
  53. var thread = new LuaCoroutine(arg0, false);
  54. buffer.Span[0] = new LuaFunction("wrap", async (context, buffer, cancellationToken) =>
  55. {
  56. var stack = context.Thread.Stack;
  57. var frameBase = stack.Count;
  58. stack.Push(thread);
  59. stack.PushRange(context.Arguments);
  60. var resultCount = await thread.ResumeAsync(context with
  61. {
  62. ArgumentCount = context.ArgumentCount + 1,
  63. FrameBase = frameBase,
  64. }, buffer, cancellationToken);
  65. buffer.Span[1..].CopyTo(buffer.Span[0..]);
  66. return resultCount - 1;
  67. });
  68. return new(1);
  69. }
  70. public static ValueTask<int> Yield(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  71. {
  72. return context.Thread.YieldAsync(context, buffer, cancellationToken);
  73. }
  74. }