diff --git a/c/lua/_demo/crroutine-continue/corroutine.go b/c/lua/_demo/crroutine-continue/corroutine.go new file mode 100644 index 00000000..4fe9f8c5 --- /dev/null +++ b/c/lua/_demo/crroutine-continue/corroutine.go @@ -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 +*/ diff --git a/c/lua/lauxlib.go b/c/lua/lauxlib.go index 4f07e8de..5b3a54b8 100644 --- a/c/lua/lauxlib.go +++ b/c/lua/lauxlib.go @@ -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 } diff --git a/c/lua/lua.go b/c/lua/lua.go index 0e066cae..94e75ba7 100644 --- a/c/lua/lua.go +++ b/c/lua/lua.go @@ -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 @@ -438,9 +446,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) +} // /* }============================================================== */ @@ -478,10 +496,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 diff --git a/c/lua/luaconf.go b/c/lua/luaconf.go new file mode 100644 index 00000000..3d995ba6 --- /dev/null +++ b/c/lua/luaconf.go @@ -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 +)