Merge pull request #746 from luoliwoshang/c/lua/corroutine

c:lua:coroutine continuation
This commit is contained in:
xushiwei
2024-08-25 17:52:36 +08:00
committed by GitHub
5 changed files with 127 additions and 13 deletions

View File

@@ -0,0 +1,72 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/lua"
)
func countdownContinue(L *lua.State, status c.Int, ctx lua.KContext) c.Int {
return countdown(L)
}
func countdown(L *lua.State) c.Int {
arg := L.Tointeger(lua.Upvalueindex(1))
c.Printf(c.Str("resume called with %d\n"), arg)
if arg > 0 {
L.Pushinteger(arg - 1)
L.Replace(lua.Upvalueindex(1))
L.Pushinteger(arg)
return L.Yieldk(1, c.Pointer(uintptr(0)), countdownContinue)
}
return 0
}
func createCountdown(L *lua.State) c.Int {
max := L.Checkinteger(1)
L.Pushinteger(max)
L.Pushcclosure(countdown, 1)
return 1
}
func main() {
L := lua.Newstate()
L.Openlibs()
defer L.Close()
L.Register(c.Str("create_countdown"), createCountdown)
testcode := c.Str(`
local countdown = create_countdown(5)
local co = coroutine.create(countdown)
while true do
local success, value = coroutine.resume(co)
if not success then
print('Error:', value)
break
end
if value == nil then break end
print('Lua received:', value)
end
print('Countdown finished');
`)
if L.Dostring(testcode) != lua.OK {
c.Printf(c.Str("Error: %s\n"), L.Tostring(-1))
}
L.Openlibs()
}
/* Expected output:
resume called with 5
Lua received: 5
resume called with 4
Lua received: 4
resume called with 3
Lua received: 3
resume called with 2
Lua received: 2
resume called with 1
Lua received: 1
resume called with 0
Countdown finished
*/

View File

@@ -31,10 +31,8 @@ func main() {
L.Atpanic(customPanic)
L.Pushcfunction(triggerError)
L.Setglobal(c.Str("trigger_error"))
L.Pushcfunction(triggerFormatError)
L.Setglobal(c.Str("trigger_format_error"))
L.Register(c.Str("trigger_error"), triggerError)
L.Register(c.Str("trigger_format_error"), triggerFormatError)
c.Printf(c.Str("1. error (protected):\n"))
L.Getglobal(c.Str("trigger_error"))

View File

@@ -14,6 +14,12 @@ import (
// /* key, in the registry, for table of preloaded loaders */
// llgo:link (*State).Checkinteger C.luaL_checkinteger
func (L *State) Checkinteger(arg c.Int) Integer { return 0 }
// llgo:link (*State).Checknumber C.luaL_checknumber
func (L *State) Checknumber(arg c.Int) Number { return 0 }
// llgo:link (*State).LError C.luaL_error
func (L *State) LError(format *c.Char, __llgo_va_list ...any) c.Int { return 0 }

View File

@@ -23,6 +23,14 @@ const (
// ** space after that to help overflow detection)
// */
const (
REGISTRYINDEX = -MAXSTACK - 1000
)
func Upvalueindex(i c.Int) c.Int {
return c.Int(REGISTRYINDEX) - i
}
// /* thread status */
const (
OK = 0
@@ -91,7 +99,7 @@ type CFunction func(L *State) c.Int
// ** Type for continuation functions
// */
// TODO(zzy): KFunction does not currently support
// llgo:type C
type KFunction func(L *State, status c.Int, ctx KContext) c.Int
// /*
@@ -426,7 +434,10 @@ func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
func (L *State) Newtable() { L.Createtable(0, 0) }
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
func (L *State) Register(name *c.Char, f CFunction) {
L.Pushcfunction(f)
L.Setglobal(name)
}
func (L *State) Pushcfunction(f CFunction) { L.Pushcclosure(f, 0) }
func (L *State) Isfunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
@@ -441,9 +452,19 @@ func (L *State) Isnoneornil(n c.Int) bool { return L.Type(n) <= 0 }
// #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
// #define lua_pushglobaltable(L) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
// #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
// #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
// #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
func (L *State) Insert(idx c.Int) {
L.Rotate(idx, 1)
}
func (L *State) Remove(idx c.Int) {
L.Rotate(idx, -1)
L.Pop(1)
}
func (L *State) Replace(idx c.Int) {
L.Copy(-1, idx)
L.Pop(1)
}
// /* }============================================================== */
@@ -484,10 +505,6 @@ const (
// /*
// ** Event masks
// */
// #define LUA_MASKCALL (1 << LUA_HOOKCALL)
// #define LUA_MASKRET (1 << LUA_HOOKRET)
// #define LUA_MASKLINE (1 << LUA_HOOKLINE)
// #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
const (
MASKCALL = 1 << HOOKCOUNT

21
c/lua/luaconf.go Normal file
View File

@@ -0,0 +1,21 @@
package lua
/*
** {==================================================================
** Macros that affect the API and must be stable (that is, must be the
** same when you compile Lua and when you compile code that links to
** Lua).
** =====================================================================
*/
/*
@@ LUAI_MAXSTACK limits the size of the Lua stack.
** CHANGE it if you need a different limit. This limit is arbitrary;
** its only purpose is to stop Lua from consuming unlimited stack
** space (and to reserve some numbers for pseudo-indices).
** (It must fit into max(size_t)/32 and max(int)/2.)
*/
const (
MAXSTACK = 1000000
)