github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/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  //