diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-18 13:24:11 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-18 13:24:11 -0200 |
commit | 9bab2cf55d9b151d730c1461e3882a5fbc7d790d (patch) | |
tree | c264480215e163b96fe1d44d874648ee39cc3cfa /ldo.c | |
parent | c4ae00a3d107a27d80bd157a135ef115104f98f0 (diff) | |
download | lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.tar.gz lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.tar.bz2 lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.zip |
support for yield inside hooks
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 44 |
1 files changed, 26 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.201 2002/11/14 16:15:53 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.202 2002/11/18 11:01:55 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -308,15 +308,20 @@ static void resume (lua_State *L, void *ud) { | |||
308 | luaG_runerror(L, "cannot resume dead coroutine"); | 308 | luaG_runerror(L, "cannot resume dead coroutine"); |
309 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | 309 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ |
310 | } | 310 | } |
311 | else if (ci->state && CI_YIELD) { /* inside a yield? */ | 311 | else if (ci->state & CI_YIELD) { /* inside a yield? */ |
312 | /* finish interrupted execution of `OP_CALL' */ | 312 | if (ci->state & CI_C) { /* `common' yield? */ |
313 | int nresults; | 313 | /* finish interrupted execution of `OP_CALL' */ |
314 | lua_assert((ci-1)->state & CI_SAVEDPC); | 314 | int nresults; |
315 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 315 | lua_assert((ci-1)->state & CI_SAVEDPC); |
316 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 316 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
317 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | 317 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
318 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ | 318 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; |
319 | if (nresults >= 0) L->top = L->ci->top; | 319 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ |
320 | if (nresults >= 0) L->top = L->ci->top; | ||
321 | } | ||
322 | else { /* yielded inside a hook: just continue its execution */ | ||
323 | ci->state &= ~CI_YIELD; | ||
324 | } | ||
320 | } | 325 | } |
321 | else | 326 | else |
322 | luaG_runerror(L, "cannot resume non-suspended coroutine"); | 327 | luaG_runerror(L, "cannot resume non-suspended coroutine"); |
@@ -349,15 +354,18 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
349 | CallInfo *ci; | 354 | CallInfo *ci; |
350 | lua_lock(L); | 355 | lua_lock(L); |
351 | ci = L->ci; | 356 | ci = L->ci; |
352 | if ((ci-1)->state & CI_C) | 357 | if (ci->state & CI_C) { /* usual yield */ |
353 | luaG_runerror(L, "cannot yield a C function"); | 358 | if ((ci-1)->state & CI_C) |
354 | lua_assert(ci->state & CI_C); /* current function is not Lua */ | 359 | luaG_runerror(L, "cannot yield a C function"); |
355 | if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ | 360 | if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ |
356 | int i; | 361 | int i; |
357 | for (i=0; i<nresults; i++) /* move down results */ | 362 | for (i=0; i<nresults; i++) /* move down results */ |
358 | setobjs2s(ci->base + i, L->top - nresults + i); | 363 | setobjs2s(ci->base + i, L->top - nresults + i); |
359 | L->top = ci->base + nresults; | 364 | L->top = ci->base + nresults; |
365 | } | ||
360 | } | 366 | } |
367 | /* else it's an yield inside a hook: nothing to do */ | ||
368 | ci->state |= CI_YIELD; | ||
361 | lua_unlock(L); | 369 | lua_unlock(L); |
362 | return -1; | 370 | return -1; |
363 | } | 371 | } |