coroutinelib.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package lua
  2. func OpenCoroutine(L *LState) int {
  3. // TODO: Tie module name to contents of linit.go?
  4. mod := L.RegisterModule(CoroutineLibName, coFuncs)
  5. L.Push(mod)
  6. return 1
  7. }
  8. var coFuncs = map[string]LGFunction{
  9. "create": coCreate,
  10. "yield": coYield,
  11. "resume": coResume,
  12. "running": coRunning,
  13. "status": coStatus,
  14. "wrap": coWrap,
  15. }
  16. func coCreate(L *LState) int {
  17. fn := L.CheckFunction(1)
  18. newthread, _ := L.NewThread()
  19. base := 0
  20. newthread.stack.Push(callFrame{
  21. Fn: fn,
  22. Pc: 0,
  23. Base: base,
  24. LocalBase: base + 1,
  25. ReturnBase: base,
  26. NArgs: 0,
  27. NRet: MultRet,
  28. Parent: nil,
  29. TailCall: 0,
  30. })
  31. L.Push(newthread)
  32. return 1
  33. }
  34. func coYield(L *LState) int {
  35. return -1
  36. }
  37. func coResume(L *LState) int {
  38. th := L.CheckThread(1)
  39. if L.G.CurrentThread == th {
  40. msg := "can not resume a running thread"
  41. if th.wrapped {
  42. L.RaiseError(msg)
  43. return 0
  44. }
  45. L.Push(LFalse)
  46. L.Push(LString(msg))
  47. return 2
  48. }
  49. if th.Dead {
  50. msg := "can not resume a dead thread"
  51. if th.wrapped {
  52. L.RaiseError(msg)
  53. return 0
  54. }
  55. L.Push(LFalse)
  56. L.Push(LString(msg))
  57. return 2
  58. }
  59. th.Parent = L
  60. L.G.CurrentThread = th
  61. if !th.isStarted() {
  62. cf := th.stack.Last()
  63. th.currentFrame = cf
  64. th.SetTop(0)
  65. nargs := L.GetTop() - 1
  66. L.XMoveTo(th, nargs)
  67. cf.NArgs = nargs
  68. th.initCallFrame(cf)
  69. th.Panic = panicWithoutTraceback
  70. } else {
  71. nargs := L.GetTop() - 1
  72. L.XMoveTo(th, nargs)
  73. }
  74. top := L.GetTop()
  75. threadRun(th)
  76. return L.GetTop() - top
  77. }
  78. func coRunning(L *LState) int {
  79. if L.G.MainThread == L {
  80. L.Push(LNil)
  81. return 1
  82. }
  83. L.Push(L.G.CurrentThread)
  84. return 1
  85. }
  86. func coStatus(L *LState) int {
  87. L.Push(LString(L.Status(L.CheckThread(1))))
  88. return 1
  89. }
  90. func wrapaux(L *LState) int {
  91. L.Insert(L.ToThread(UpvalueIndex(1)), 1)
  92. return coResume(L)
  93. }
  94. func coWrap(L *LState) int {
  95. coCreate(L)
  96. L.CheckThread(L.GetTop()).wrapped = true
  97. v := L.Get(L.GetTop())
  98. L.Pop(1)
  99. L.Push(L.NewClosure(wrapaux, v))
  100. return 1
  101. }
  102. //