From 9bab2cf55d9b151d730c1461e3882a5fbc7d790d Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 18 Nov 2002 13:24:11 -0200 Subject: support for yield inside hooks --- ldo.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) (limited to 'ldo.c') diff --git a/ldo.c b/ldo.c index 176cf0da..02f0d20b 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.201 2002/11/14 16:15:53 roberto Exp roberto $ +** $Id: ldo.c,v 1.202 2002/11/18 11:01:55 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -308,15 +308,20 @@ static void resume (lua_State *L, void *ud) { luaG_runerror(L, "cannot resume dead coroutine"); luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ } - else if (ci->state && CI_YIELD) { /* inside a yield? */ - /* finish interrupted execution of `OP_CALL' */ - int nresults; - lua_assert((ci-1)->state & CI_SAVEDPC); - lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || - GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); - nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; - luaD_poscall(L, nresults, L->top - nargs); /* complete it */ - if (nresults >= 0) L->top = L->ci->top; + else if (ci->state & CI_YIELD) { /* inside a yield? */ + if (ci->state & CI_C) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + int nresults; + lua_assert((ci-1)->state & CI_SAVEDPC); + lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); + nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; + luaD_poscall(L, nresults, L->top - nargs); /* complete it */ + if (nresults >= 0) L->top = L->ci->top; + } + else { /* yielded inside a hook: just continue its execution */ + ci->state &= ~CI_YIELD; + } } else luaG_runerror(L, "cannot resume non-suspended coroutine"); @@ -349,15 +354,18 @@ LUA_API int lua_yield (lua_State *L, int nresults) { CallInfo *ci; lua_lock(L); ci = L->ci; - if ((ci-1)->state & CI_C) - luaG_runerror(L, "cannot yield a C function"); - lua_assert(ci->state & CI_C); /* current function is not Lua */ - if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ - int i; - for (i=0; ibase + i, L->top - nresults + i); - L->top = ci->base + nresults; + if (ci->state & CI_C) { /* usual yield */ + if ((ci-1)->state & CI_C) + luaG_runerror(L, "cannot yield a C function"); + if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ + int i; + for (i=0; ibase + i, L->top - nresults + i); + L->top = ci->base + nresults; + } } + /* else it's an yield inside a hook: nothing to do */ + ci->state |= CI_YIELD; lua_unlock(L); return -1; } -- cgit v1.2.3-55-g6feb