mirror of https://github.com/lua/lua
support for yield inside hooks
This commit is contained in:
parent
c4ae00a3d1
commit
9bab2cf55d
44
ldo.c
44
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
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** 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");
|
luaG_runerror(L, "cannot resume dead coroutine");
|
||||||
luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
|
luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
|
||||||
}
|
}
|
||||||
else if (ci->state && CI_YIELD) { /* inside a yield? */
|
else if (ci->state & CI_YIELD) { /* inside a yield? */
|
||||||
/* finish interrupted execution of `OP_CALL' */
|
if (ci->state & CI_C) { /* `common' yield? */
|
||||||
int nresults;
|
/* finish interrupted execution of `OP_CALL' */
|
||||||
lua_assert((ci-1)->state & CI_SAVEDPC);
|
int nresults;
|
||||||
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
|
lua_assert((ci-1)->state & CI_SAVEDPC);
|
||||||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
|
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
|
||||||
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
|
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
|
||||||
luaD_poscall(L, nresults, L->top - nargs); /* complete it */
|
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
|
||||||
if (nresults >= 0) L->top = L->ci->top;
|
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
|
else
|
||||||
luaG_runerror(L, "cannot resume non-suspended coroutine");
|
luaG_runerror(L, "cannot resume non-suspended coroutine");
|
||||||
|
@ -349,15 +354,18 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
ci = L->ci;
|
ci = L->ci;
|
||||||
if ((ci-1)->state & CI_C)
|
if (ci->state & CI_C) { /* usual yield */
|
||||||
luaG_runerror(L, "cannot yield a C function");
|
if ((ci-1)->state & CI_C)
|
||||||
lua_assert(ci->state & CI_C); /* current function is not Lua */
|
luaG_runerror(L, "cannot yield a C function");
|
||||||
if (L->top - nresults > ci->base) { /* is there garbage in the stack? */
|
if (L->top - nresults > ci->base) { /* is there garbage in the stack? */
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<nresults; i++) /* move down results */
|
for (i=0; i<nresults; i++) /* move down results */
|
||||||
setobjs2s(ci->base + i, L->top - nresults + i);
|
setobjs2s(ci->base + i, L->top - nresults + i);
|
||||||
L->top = ci->base + nresults;
|
L->top = ci->base + nresults;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* else it's an yield inside a hook: nothing to do */
|
||||||
|
ci->state |= CI_YIELD;
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
13
lvm.c
13
lvm.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 1.261 2002/11/14 16:15:53 roberto Exp roberto $
|
** $Id: lvm.c,v 1.262 2002/11/18 11:01:55 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -393,8 +393,14 @@ StkId luaV_execute (lua_State *L) {
|
||||||
const Instruction i = *pc++;
|
const Instruction i = *pc++;
|
||||||
StkId ra;
|
StkId ra;
|
||||||
if (L->hookmask >= LUA_MASKLINE &&
|
if (L->hookmask >= LUA_MASKLINE &&
|
||||||
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
|
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
|
||||||
traceexec(L);
|
traceexec(L);
|
||||||
|
if (L->ci->state & CI_YIELD) { /* did hook yield? */
|
||||||
|
L->ci->u.l.savedpc = pc - 1;
|
||||||
|
L->ci->state |= CI_SAVEDPC;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* warning!! several calls may realloc the stack and invalidate `ra' */
|
/* warning!! several calls may realloc the stack and invalidate `ra' */
|
||||||
ra = RA(i);
|
ra = RA(i);
|
||||||
lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
|
lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
|
||||||
|
@ -595,8 +601,7 @@ StkId luaV_execute (lua_State *L) {
|
||||||
if (firstResult) {
|
if (firstResult) {
|
||||||
if (firstResult > L->top) { /* yield? */
|
if (firstResult > L->top) { /* yield? */
|
||||||
(L->ci - 1)->u.l.savedpc = pc;
|
(L->ci - 1)->u.l.savedpc = pc;
|
||||||
(L->ci - 1)->state = CI_SAVEDPC;
|
(L->ci - 1)->state |= CI_SAVEDPC;
|
||||||
L->ci->state |= CI_YIELD;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* it was a C function (`precall' called it); adjust results */
|
/* it was a C function (`precall' called it); adjust results */
|
||||||
|
|
Loading…
Reference in New Issue