|
|
@ -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; i<nresults; i++) /* move down results */ |
|
|
|
setobjs2s(ci->base + 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; i<nresults; i++) /* move down results */ |
|
|
|
setobjs2s(ci->base + 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; |
|
|
|
} |
|
|
|