summaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-11-18 13:24:11 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-11-18 13:24:11 -0200
commit9bab2cf55d9b151d730c1461e3882a5fbc7d790d (patch)
treec264480215e163b96fe1d44d874648ee39cc3cfa /ldo.c
parentc4ae00a3d107a27d80bd157a135ef115104f98f0 (diff)
downloadlua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.tar.gz
lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.tar.bz2
lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.zip
support for yield inside hooks
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/ldo.c b/ldo.c
index 176cf0da..02f0d20b 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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}