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