113 lines
1.9 KiB
Go
113 lines
1.9 KiB
Go
package lua
|
|
|
|
func OpenCoroutine(L *LState) int {
|
|
// TODO: Tie module name to contents of linit.go?
|
|
mod := L.RegisterModule(CoroutineLibName, coFuncs)
|
|
L.Push(mod)
|
|
return 1
|
|
}
|
|
|
|
var coFuncs = map[string]LGFunction{
|
|
"create": coCreate,
|
|
"yield": coYield,
|
|
"resume": coResume,
|
|
"running": coRunning,
|
|
"status": coStatus,
|
|
"wrap": coWrap,
|
|
}
|
|
|
|
func coCreate(L *LState) int {
|
|
fn := L.CheckFunction(1)
|
|
newthread, _ := L.NewThread()
|
|
base := 0
|
|
newthread.stack.Push(callFrame{
|
|
Fn: fn,
|
|
Pc: 0,
|
|
Base: base,
|
|
LocalBase: base + 1,
|
|
ReturnBase: base,
|
|
NArgs: 0,
|
|
NRet: MultRet,
|
|
Parent: nil,
|
|
TailCall: 0,
|
|
})
|
|
L.Push(newthread)
|
|
return 1
|
|
}
|
|
|
|
func coYield(L *LState) int {
|
|
return -1
|
|
}
|
|
|
|
func coResume(L *LState) int {
|
|
th := L.CheckThread(1)
|
|
if L.G.CurrentThread == th {
|
|
msg := "can not resume a running thread"
|
|
if th.wrapped {
|
|
L.RaiseError(msg)
|
|
return 0
|
|
}
|
|
L.Push(LFalse)
|
|
L.Push(LString(msg))
|
|
return 2
|
|
}
|
|
if th.Dead {
|
|
msg := "can not resume a dead thread"
|
|
if th.wrapped {
|
|
L.RaiseError(msg)
|
|
return 0
|
|
}
|
|
L.Push(LFalse)
|
|
L.Push(LString(msg))
|
|
return 2
|
|
}
|
|
th.Parent = L
|
|
L.G.CurrentThread = th
|
|
if !th.isStarted() {
|
|
cf := th.stack.Last()
|
|
th.currentFrame = cf
|
|
th.SetTop(0)
|
|
nargs := L.GetTop() - 1
|
|
L.XMoveTo(th, nargs)
|
|
cf.NArgs = nargs
|
|
th.initCallFrame(cf)
|
|
th.Panic = panicWithoutTraceback
|
|
} else {
|
|
nargs := L.GetTop() - 1
|
|
L.XMoveTo(th, nargs)
|
|
}
|
|
top := L.GetTop()
|
|
threadRun(th)
|
|
return L.GetTop() - top
|
|
}
|
|
|
|
func coRunning(L *LState) int {
|
|
if L.G.MainThread == L {
|
|
L.Push(LNil)
|
|
return 1
|
|
}
|
|
L.Push(L.G.CurrentThread)
|
|
return 1
|
|
}
|
|
|
|
func coStatus(L *LState) int {
|
|
L.Push(LString(L.Status(L.CheckThread(1))))
|
|
return 1
|
|
}
|
|
|
|
func wrapaux(L *LState) int {
|
|
L.Insert(L.ToThread(UpvalueIndex(1)), 1)
|
|
return coResume(L)
|
|
}
|
|
|
|
func coWrap(L *LState) int {
|
|
coCreate(L)
|
|
L.CheckThread(L.GetTop()).wrapped = true
|
|
v := L.Get(L.GetTop())
|
|
L.Pop(1)
|
|
L.Push(L.NewClosure(wrapaux, v))
|
|
return 1
|
|
}
|
|
|
|
//
|