From 0e45ffb8e41fa8f6b156bdaff0685e1ddfdfbd2a Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 14 Sep 2009 11:30:39 -0300 Subject: [PATCH] first implementation of 'lua_yieldk' (yield with continuation) --- ldo.c | 28 +++++++++++++++++++++++----- ltests.c | 14 ++++++++++++-- lua.h | 6 ++++-- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/ldo.c b/ldo.c index e93f68e3..913375b0 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.65 2009/06/01 19:09:26 roberto Exp roberto $ +** $Id: ldo.c,v 2.66 2009/07/15 17:26:14 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -418,6 +418,16 @@ static void resume (lua_State *L, void *ud) { if (isLua(ci)) /* yielded inside a hook? */ luaV_execute(L); else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation? */ + int n; + ci->u.c.status = LUA_YIELD; /* 'default' status */ + ci->callstatus |= CIST_YIELDED; + ci->func = restorestack(L, ci->u.c.oldtop); + lua_unlock(L); + n = (*ci->u.c.k)(L); /* call continuation */ + lua_lock(L); + firstArg = L->top - n; + } G(L)->nCcalls--; /* finish 'luaD_call' */ luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ } @@ -499,17 +509,25 @@ LUA_API int lua_resume (lua_State *L, int nargs) { return status; } -LUA_API int lua_yield (lua_State *L, int nresults) { +LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { + CallInfo *ci = L->ci; luai_userstateyield(L, nresults); lua_lock(L); if (L->nny > 0) luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); L->status = LUA_YIELD; - if (!isLua(L->ci)) { /* not inside a hook? */ - L->ci->func = L->top - nresults - 1; /* protect stack slots below ??? */ + if (isLua(ci)) { /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) { /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->u.c.oldtop = savestack(L, ci->func); /* save current 'func' */ + } + ci->func = L->top - nresults - 1; /* protect stack slots below */ luaD_throw(L, LUA_YIELD); } - lua_assert(L->ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ lua_unlock(L); return 0; /* otherwise, return to 'luaD_callhook' */ } diff --git a/ltests.c b/ltests.c index b5b782f5..90050a75 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.69 2009/08/26 17:41:26 roberto Exp roberto $ +** $Id: ltests.c,v 2.70 2009/09/09 20:44:10 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -836,6 +836,8 @@ static int getnum_aux (lua_State *L, const char **pc) { sig = -1; (*pc)++; } + if (!lisdigit(cast(unsigned char, **pc))) + luaL_error(L, "number expected (%s)", *pc); while (lisdigit(cast(unsigned char, **pc))) res = res*10 + (*(*pc)++) - '0'; return sig*res; } @@ -1033,6 +1035,11 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { else if EQ("yield") { return lua_yield(L1, getnum); } + else if EQ("yieldk") { + int nres = getnum; + int i = getnum; + return lua_yieldk(L1, nres, i, Cfunck); + } else if EQ("loadstring") { size_t sl; const char *s = luaL_checklstring(L1, getnum, &sl); @@ -1056,9 +1063,12 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { lua_pushinteger(L1, lua_objlen(L1, i)); } else if EQ("getctx") { + static const char *const codes[] = {"OK", "YIELD", "ERRRUN", + "ERRSYNTAX", "ERRMEM", "ERRGCMM", "ERRERR"}; + int i = 0; int s = lua_getctx(L1, &i); - lua_pushinteger(L1, s); + lua_pushstring(L1, codes[s]); lua_pushinteger(L1, i); } else if EQ("checkstack") { diff --git a/lua.h b/lua.h index 5887d16c..8e373b20 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.240 2009/06/18 18:59:18 roberto Exp roberto $ +** $Id: lua.h,v 1.241 2009/07/15 17:26:14 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -243,7 +243,9 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); /* ** coroutine functions */ -LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, + lua_CFunction k); +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) LUA_API int (lua_resume) (lua_State *L, int narg); LUA_API int (lua_status) (lua_State *L);