summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-03-10 14:14:37 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-03-10 14:14:37 -0300
commitba484b9eb16dd62a7c3a5400a66eb952b654d3f0 (patch)
tree31692ddf85265e5a46eab0cd55a0b0757a225e68
parentf9d015523ef48266cea37e13717c223c16941b23 (diff)
downloadlua-ba484b9eb16dd62a7c3a5400a66eb952b654d3f0.tar.gz
lua-ba484b9eb16dd62a7c3a5400a66eb952b654d3f0.tar.bz2
lua-ba484b9eb16dd62a7c3a5400a66eb952b654d3f0.zip
yielding across lua_call (first version)
-rw-r--r--lapi.c22
-rw-r--r--lapi.h6
-rw-r--r--lbaselib.c11
-rw-r--r--ldebug.c4
-rw-r--r--ldo.c103
-rw-r--r--ldo.h5
-rw-r--r--lgc.c4
-rw-r--r--lstate.c4
-rw-r--r--lstate.h7
-rw-r--r--ltablib.c30
-rw-r--r--lua.h8
-rw-r--r--lvm.c72
-rw-r--r--lvm.h3
13 files changed, 169 insertions, 110 deletions
diff --git a/lapi.c b/lapi.c
index ea4d0f1f..60dc19f5 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.69 2009/02/18 17:20:56 roberto Exp roberto $ 2** $Id: lapi.c,v 2.70 2009/02/19 17:15:13 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -757,21 +757,25 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
757*/ 757*/
758 758
759 759
760#define adjustresults(L,nres) \
761 { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
762
763
764#define checkresults(L,na,nr) \ 760#define checkresults(L,na,nr) \
765 api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) 761 api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
766 762
767 763
768LUA_API void lua_call (lua_State *L, int nargs, int nresults) { 764LUA_API void lua_callcont (lua_State *L, int nargs, int nresults,
765 lua_CFunction cont) {
769 StkId func; 766 StkId func;
770 lua_lock(L); 767 lua_lock(L);
768 /* cannot use continuations inside hooks */
769 api_check(L, cont == NULL || !isLua(L->ci));
771 api_checknelems(L, nargs+1); 770 api_checknelems(L, nargs+1);
772 checkresults(L, nargs, nresults); 771 checkresults(L, nargs, nresults);
773 func = L->top - (nargs+1); 772 func = L->top - (nargs+1);
774 luaD_call(L, func, nresults); 773 if (cont) {
774 L->ci->u.c.cont = cont;
775 luaD_call(L, func, nresults, 1);
776 }
777 else
778 luaD_call(L, func, nresults, 0);
775 adjustresults(L, nresults); 779 adjustresults(L, nresults);
776 lua_unlock(L); 780 lua_unlock(L);
777} 781}
@@ -789,7 +793,7 @@ struct CallS { /* data to `f_call' */
789 793
790static void f_call (lua_State *L, void *ud) { 794static void f_call (lua_State *L, void *ud) {
791 struct CallS *c = cast(struct CallS *, ud); 795 struct CallS *c = cast(struct CallS *, ud);
792 luaD_call(L, c->func, c->nresults); 796 luaD_call(L, c->func, c->nresults, 0);
793} 797}
794 798
795 799
@@ -835,7 +839,7 @@ static void f_Ccall (lua_State *L, void *ud) {
835 api_incr_top(L); 839 api_incr_top(L);
836 setpvalue(L->top, c->ud); /* push only argument */ 840 setpvalue(L->top, c->ud); /* push only argument */
837 api_incr_top(L); 841 api_incr_top(L);
838 luaD_call(L, L->top - 2, 0); 842 luaD_call(L, L->top - 2, 0, 0);
839} 843}
840 844
841 845
diff --git a/lapi.h b/lapi.h
index b9ca73bf..82ff87c6 100644
--- a/lapi.h
+++ b/lapi.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.h,v 2.2 2005/04/25 19:24:10 roberto Exp roberto $ 2** $Id: lapi.h,v 2.3 2006/07/11 15:53:29 roberto Exp roberto $
3** Auxiliary functions from Lua API 3** Auxiliary functions from Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -13,4 +13,8 @@
13 13
14#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top);} 14#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top);}
15 15
16#define adjustresults(L,nres) \
17 { if ((nres) == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
18
19
16#endif 20#endif
diff --git a/lbaselib.c b/lbaselib.c
index ffa753a1..43981dc7 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.209 2009/02/06 18:38:47 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.210 2009/02/07 12:23:15 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -323,12 +323,17 @@ static int luaB_load (lua_State *L) {
323} 323}
324 324
325 325
326static int dofilecont (lua_State *L) {
327 return lua_gettop(L) - 1;
328}
329
330
326static int luaB_dofile (lua_State *L) { 331static int luaB_dofile (lua_State *L) {
327 const char *fname = luaL_optstring(L, 1, NULL); 332 const char *fname = luaL_optstring(L, 1, NULL);
328 lua_settop(L, 1); 333 lua_settop(L, 1);
329 if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L); 334 if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L);
330 lua_call(L, 0, LUA_MULTRET); 335 lua_callcont(L, 0, LUA_MULTRET, dofilecont);
331 return lua_gettop(L) - 1; 336 return dofilecont(L);
332} 337}
333 338
334 339
diff --git a/ldebug.c b/ldebug.c
index 6148cfcf..64ad70eb 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.42 2008/10/30 15:39:30 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.43 2009/03/04 13:32:29 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -628,7 +628,7 @@ void luaG_errormsg (lua_State *L) {
628 setobjs2s(L, L->top, L->top - 1); /* move argument */ 628 setobjs2s(L, L->top, L->top - 1); /* move argument */
629 setobjs2s(L, L->top - 1, errfunc); /* push function */ 629 setobjs2s(L, L->top - 1, errfunc); /* push function */
630 incr_top(L); 630 incr_top(L);
631 luaD_call(L, L->top - 2, 1); /* call it */ 631 luaD_call(L, L->top - 2, 1, 0); /* call it */
632 } 632 }
633 luaD_throw(L, LUA_ERRRUN); 633 luaD_throw(L, LUA_ERRRUN);
634} 634}
diff --git a/ldo.c b/ldo.c
index effef571..bf21e609 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.53 2009/03/03 18:51:24 roberto Exp roberto $ 2** $Id: ldo.c,v 2.54 2009/03/04 13:32:29 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*/
@@ -14,6 +14,7 @@
14 14
15#include "lua.h" 15#include "lua.h"
16 16
17#include "lapi.h"
17#include "ldebug.h" 18#include "ldebug.h"
18#include "ldo.h" 19#include "ldo.h"
19#include "lfunc.h" 20#include "lfunc.h"
@@ -365,7 +366,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
365** When returns, all the results are on the stack, starting at the original 366** When returns, all the results are on the stack, starting at the original
366** function position. 367** function position.
367*/ 368*/
368void luaD_call (lua_State *L, StkId func, int nResults) { 369void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
369 global_State *g = G(L); 370 global_State *g = G(L);
370 if (++g->nCcalls >= LUAI_MAXCCALLS) { 371 if (++g->nCcalls >= LUAI_MAXCCALLS) {
371 if (g->nCcalls == LUAI_MAXCCALLS) 372 if (g->nCcalls == LUAI_MAXCCALLS)
@@ -373,64 +374,41 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
373 else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) 374 else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
374 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ 375 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
375 } 376 }
377 if (!allowyield) L->nny++;
376 if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ 378 if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
377 luaV_execute(L); /* call it */ 379 luaV_execute(L); /* call it */
380 if (!allowyield) L->nny--;
378 g->nCcalls--; 381 g->nCcalls--;
379 luaC_checkGC(L); 382 luaC_checkGC(L);
380} 383}
381 384
382 385
386static void finishCcall (lua_State *L) {
387 int n;
388 lua_assert(L->ci->u.c.cont != NULL); /* must have a continuation */
389 lua_assert(L->nny == 0);
390 /* finish 'luaD_call' */
391 G(L)->nCcalls--;
392 /* finish 'lua_callcont' */
393 adjustresults(L, (L->ci + 1)->nresults);
394 /* call continuation function */
395 lua_unlock(L);
396 n = (*L->ci->u.c.cont)(L);
397 lua_lock(L);
398 /* finish 'luaD_precall' */
399 luaD_poscall(L, L->top - n);
400}
401
402
383static void unroll (lua_State *L) { 403static void unroll (lua_State *L) {
384 for (;;) { 404 for (;;) {
385 Instruction inst; 405 if (L->ci == L->base_ci) /* stack is empty? */
386 luaV_execute(L); /* execute down to higher C 'boundary' */
387 if (L->ci == L->base_ci) { /* stack is empty? */
388 lua_assert(L->baseCcalls == G(L)->nCcalls);
389 return; /* coroutine finished normally */ 406 return; /* coroutine finished normally */
390 } 407 if (!isLua(L->ci)) /* C function? */
391 L->baseCcalls--; /* undo increment that allows yields */ 408 finishCcall(L);
392 inst = *(L->savedpc - 1); /* interrupted instruction */ 409 else { /* Lua function */
393 switch (GET_OPCODE(inst)) { /* finish its execution */ 410 luaV_finishOp(L); /* finish interrupted instruction */
394 case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: 411 luaV_execute(L); /* execute down to higher C 'boundary' */
395 case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
396 case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: {
397 setobjs2s(L, L->base + GETARG_A(inst), --L->top);
398 break;
399 }
400 case OP_LE: case OP_LT: case OP_EQ: {
401 int res = !l_isfalse(L->top - 1);
402 L->top--;
403 /* metamethod should not be called when operand is K */
404 lua_assert(!ISK(GETARG_B(inst)));
405 if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */
406 ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE)))
407 res = !res; /* invert result */
408 lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP);
409 if (res != GETARG_A(inst)) /* condition failed? */
410 L->savedpc++; /* skip jump instruction */
411 break;
412 }
413 case OP_CONCAT: {
414 StkId top = L->top - 1; /* top when __concat was called */
415 int last = cast_int(top - L->base) - 2; /* last element and ... */
416 int b = GETARG_B(inst); /* ... first element to concatenate */
417 int total = last - b + 1; /* number of elements to concatenate */
418 setobj2s(L, top - 2, top); /* put TM result in proper position */
419 L->top = L->ci->top; /* correct top */
420 if (total > 1) /* are there elements to concat? */
421 luaV_concat(L, total, last); /* concat them (may yield again) */
422 /* move final result to final position */
423 setobj2s(L, L->base + GETARG_A(inst), L->base + b);
424 continue;
425 }
426 case OP_TFORCALL: {
427 lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP);
428 L->top = L->ci->top; /* correct top */
429 break;
430 }
431 case OP_SETGLOBAL: case OP_SETTABLE:
432 break; /* nothing to be done */
433 default: lua_assert(0);
434 } 412 }
435 } 413 }
436} 414}
@@ -441,23 +419,22 @@ static void resume (lua_State *L, void *ud) {
441 CallInfo *ci = L->ci; 419 CallInfo *ci = L->ci;
442 if (L->status == LUA_OK) { /* start coroutine? */ 420 if (L->status == LUA_OK) { /* start coroutine? */
443 lua_assert(ci == L->base_ci && firstArg > L->base); 421 lua_assert(ci == L->base_ci && firstArg > L->base);
444 if (luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* C function? */ 422 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
445 return; /* done */ 423 luaV_execute(L); /* call it */
446 } 424 }
447 else { /* resuming from previous yield */ 425 else { /* resuming from previous yield */
448 lua_assert(L->status == LUA_YIELD); 426 lua_assert(L->status == LUA_YIELD);
449 L->status = LUA_OK; 427 L->status = LUA_OK;
450 if (isLua(ci)) /* yielded inside a hook? */ 428 if (isLua(ci)) { /* yielded inside a hook? */
451 L->base = L->ci->base; /* just continue its execution */ 429 L->base = L->ci->base; /* just continue its execution */
430 luaV_execute(L);
431 }
452 else { /* 'common' yield */ 432 else { /* 'common' yield */
453 /* finish interrupted execution of `OP_CALL' */ 433 G(L)->nCcalls--; /* finish 'luaD_call' */
454 lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || 434 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
455 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
456 if (luaD_poscall(L, firstArg)) /* complete it... */
457 L->top = L->ci->top; /* and correct top if not multiple results */
458 } 435 }
436 unroll(L);
459 } 437 }
460 unroll(L);
461} 438}
462 439
463 440
@@ -484,7 +461,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
484 if (G(L)->nCcalls >= LUAI_MAXCCALLS) 461 if (G(L)->nCcalls >= LUAI_MAXCCALLS)
485 return resume_error(L, "C stack overflow"); 462 return resume_error(L, "C stack overflow");
486 ++G(L)->nCcalls; /* count resume */ 463 ++G(L)->nCcalls; /* count resume */
487 L->baseCcalls += G(L)->nCcalls; 464 L->nny = 0; /* allow yields */
488 status = luaD_rawrunprotected(L, resume, L->top - nargs); 465 status = luaD_rawrunprotected(L, resume, L->top - nargs);
489 if (status != LUA_OK && status != LUA_YIELD) { /* error? */ 466 if (status != LUA_OK && status != LUA_YIELD) { /* error? */
490 L->status = cast_byte(status); /* mark thread as `dead' */ 467 L->status = cast_byte(status); /* mark thread as `dead' */
@@ -494,7 +471,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
494 else { 471 else {
495 lua_assert(status == L->status); 472 lua_assert(status == L->status);
496 } 473 }
497 L->baseCcalls -= G(L)->nCcalls; 474 L->nny = 1; /* do not allow yields */
498 --G(L)->nCcalls; 475 --G(L)->nCcalls;
499 lua_unlock(L); 476 lua_unlock(L);
500 return status; 477 return status;
@@ -504,7 +481,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
504LUA_API int lua_yield (lua_State *L, int nresults) { 481LUA_API int lua_yield (lua_State *L, int nresults) {
505 luai_userstateyield(L, nresults); 482 luai_userstateyield(L, nresults);
506 lua_lock(L); 483 lua_lock(L);
507 if (G(L)->nCcalls > L->baseCcalls) 484 if (L->nny > 0)
508 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); 485 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
509 L->base = L->top - nresults; /* protect stack slots below */ 486 L->base = L->top - nresults; /* protect stack slots below */
510 L->status = LUA_YIELD; 487 L->status = LUA_YIELD;
@@ -521,6 +498,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
521 int status; 498 int status;
522 ptrdiff_t old_ci = saveci(L, L->ci); 499 ptrdiff_t old_ci = saveci(L, L->ci);
523 lu_byte old_allowhooks = L->allowhook; 500 lu_byte old_allowhooks = L->allowhook;
501 unsigned short old_nny = L->nny;
524 ptrdiff_t old_errfunc = L->errfunc; 502 ptrdiff_t old_errfunc = L->errfunc;
525 L->errfunc = ef; 503 L->errfunc = ef;
526 status = luaD_rawrunprotected(L, func, u); 504 status = luaD_rawrunprotected(L, func, u);
@@ -532,6 +510,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
532 L->base = L->ci->base; 510 L->base = L->ci->base;
533 L->savedpc = L->ci->savedpc; 511 L->savedpc = L->ci->savedpc;
534 L->allowhook = old_allowhooks; 512 L->allowhook = old_allowhooks;
513 L->nny = old_nny;
535 restore_stack_limit(L); 514 restore_stack_limit(L);
536 } 515 }
537 L->errfunc = old_errfunc; 516 L->errfunc = old_errfunc;
diff --git a/ldo.h b/ldo.h
index ad86a09c..c600bfe4 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 2.9 2008/07/03 14:24:36 roberto Exp roberto $ 2** $Id: ldo.h,v 2.10 2008/08/13 17:02:42 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*/
@@ -34,7 +34,8 @@ typedef void (*Pfunc) (lua_State *L, void *ud);
34LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); 34LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
35LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); 35LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
36LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); 36LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
37LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); 37LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
38 int allowyield);
38LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, 39LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
39 ptrdiff_t oldtop, ptrdiff_t ef); 40 ptrdiff_t oldtop, ptrdiff_t ef);
40LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); 41LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
diff --git a/lgc.c b/lgc.c
index 1fd19973..482375d0 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.47 2008/06/26 19:42:45 roberto Exp roberto $ 2** $Id: lgc.c,v 2.48 2009/02/17 19:47:58 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -601,7 +601,7 @@ static Udata *udata2finalize (global_State *g) {
601 601
602static void dothecall (lua_State *L, void *ud) { 602static void dothecall (lua_State *L, void *ud) {
603 UNUSED(ud); 603 UNUSED(ud);
604 luaD_call(L, L->top - 2, 0); 604 luaD_call(L, L->top - 2, 0, 0);
605} 605}
606 606
607 607
diff --git a/lstate.c b/lstate.c
index e1a3237b..df62f3e3 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.48 2009/02/17 19:47:58 roberto Exp roberto $ 2** $Id: lstate.c,v 2.49 2009/02/18 17:20:56 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -95,7 +95,7 @@ static void preinit_state (lua_State *L, global_State *g) {
95 resethookcount(L); 95 resethookcount(L);
96 L->openupval = NULL; 96 L->openupval = NULL;
97 L->size_ci = 0; 97 L->size_ci = 0;
98 L->baseCcalls = 0; 98 L->nny = 1;
99 L->status = LUA_OK; 99 L->status = LUA_OK;
100 L->base_ci = L->ci = NULL; 100 L->base_ci = L->ci = NULL;
101 L->savedpc = NULL; 101 L->savedpc = NULL;
diff --git a/lstate.h b/lstate.h
index 174446dc..f27631d0 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.37 2009/02/18 17:20:56 roberto Exp roberto $ 2** $Id: lstate.h,v 2.38 2009/03/04 13:32:29 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -87,6 +87,9 @@ typedef struct CallInfo {
87 struct { /* only for Lua functions */ 87 struct { /* only for Lua functions */
88 int tailcalls; /* number of tail calls lost under this entry */ 88 int tailcalls; /* number of tail calls lost under this entry */
89 } l; 89 } l;
90 struct { /* only for C functions */
91 lua_CFunction cont; /* continuation in case of yields */
92 } c;
90 } u; 93 } u;
91} CallInfo; 94} CallInfo;
92 95
@@ -160,7 +163,7 @@ struct lua_State {
160 CallInfo *base_ci; /* array of CallInfo's */ 163 CallInfo *base_ci; /* array of CallInfo's */
161 int stacksize; 164 int stacksize;
162 int size_ci; /* size of array `base_ci' */ 165 int size_ci; /* size of array `base_ci' */
163 unsigned short baseCcalls; /* number of nested C calls when resuming */ 166 unsigned short nny; /* number of non-yieldable calls in stack */
164 lu_byte hookmask; 167 lu_byte hookmask;
165 lu_byte allowhook; 168 lu_byte allowhook;
166 int basehookcount; 169 int basehookcount;
diff --git a/ltablib.c b/ltablib.c
index ab83c0c8..7296fb38 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltablib.c,v 1.43 2008/02/14 16:03:27 roberto Exp roberto $ 2** $Id: ltablib.c,v 1.44 2008/04/07 18:43:00 roberto Exp roberto $
3** Library for Table Manipulation 3** Library for Table Manipulation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -36,20 +36,28 @@ static int foreachi (lua_State *L) {
36} 36}
37 37
38 38
39static int foreach (lua_State *L) { 39static int foreachcont (lua_State *L) {
40 luaL_checktype(L, 1, LUA_TTABLE); 40 for (;;) {
41 luaL_checktype(L, 2, LUA_TFUNCTION);
42 lua_pushnil(L); /* first key */
43 while (lua_next(L, 1)) {
44 lua_pushvalue(L, 2); /* function */
45 lua_pushvalue(L, -3); /* key */
46 lua_pushvalue(L, -3); /* value */
47 lua_call(L, 2, 1);
48 if (!lua_isnil(L, -1)) 41 if (!lua_isnil(L, -1))
49 return 1; 42 return 1;
50 lua_pop(L, 2); /* remove value and result */ 43 lua_pop(L, 2); /* remove value and result */
44 if (lua_next(L, 1) == 0) /* no more elements? */
45 return 0;
46 lua_pushvalue(L, 2); /* function */
47 lua_pushvalue(L, -3); /* key */
48 lua_pushvalue(L, -3); /* value */
49 lua_callcont(L, 2, 1, &foreachcont);
51 } 50 }
52 return 0; 51}
52
53
54static int foreach (lua_State *L) {
55 luaL_checktype(L, 1, LUA_TTABLE);
56 luaL_checktype(L, 2, LUA_TFUNCTION);
57 lua_pushnil(L); /* first key */
58 lua_pushnil(L); /* first value */
59 lua_pushnil(L); /* first "return" */
60 return foreachcont(L);
53} 61}
54 62
55 63
diff --git a/lua.h b/lua.h
index 82101882..13d067a5 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.231 2008/08/13 14:08:49 roberto Exp roberto $ 2** $Id: lua.h,v 1.232 2009/02/18 17:20:56 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** Lua.org, PUC-Rio, Brazil (http://www.lua.org) 4** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
5** See Copyright Notice at the end of this file 5** See Copyright Notice at the end of this file
@@ -203,7 +203,9 @@ LUA_API int (lua_setfenv) (lua_State *L, int idx);
203/* 203/*
204** 'load' and 'call' functions (load and run Lua code) 204** 'load' and 'call' functions (load and run Lua code)
205*/ 205*/
206LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); 206LUA_API void (lua_callcont) (lua_State *L, int nargs, int nresults,
207 lua_CFunction cont);
208
207LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); 209LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
208LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); 210LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
209LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, 211LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
@@ -281,6 +283,8 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
281 283
282#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) 284#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
283 285
286#define lua_call(L,n,r) lua_callcont(L, (n), (r), NULL);
287
284 288
285 289
286/* 290/*
diff --git a/lvm.c b/lvm.c
index 2b54266f..494b40cd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.82 2009/03/02 16:34:23 roberto Exp roberto $ 2** $Id: lvm.c,v 2.83 2009/03/04 13:32:29 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -79,17 +79,14 @@ static void traceexec (lua_State *L) {
79static void callTM (lua_State *L, const TValue *f, const TValue *p1, 79static void callTM (lua_State *L, const TValue *f, const TValue *p1,
80 const TValue *p2, TValue *p3, int hasres) { 80 const TValue *p2, TValue *p3, int hasres) {
81 ptrdiff_t result = savestack(L, p3); 81 ptrdiff_t result = savestack(L, p3);
82 int oldbase = L->baseCcalls;
83 setobj2s(L, L->top++, f); /* push function */ 82 setobj2s(L, L->top++, f); /* push function */
84 setobj2s(L, L->top++, p1); /* 1st argument */ 83 setobj2s(L, L->top++, p1); /* 1st argument */
85 setobj2s(L, L->top++, p2); /* 2nd argument */ 84 setobj2s(L, L->top++, p2); /* 2nd argument */
86 if (!hasres) /* no result? 'p3' is third argument */ 85 if (!hasres) /* no result? 'p3' is third argument */
87 setobj2s(L, L->top++, p3); /* 3th argument */ 86 setobj2s(L, L->top++, p3); /* 3th argument */
88 luaD_checkstack(L, 0); 87 luaD_checkstack(L, 0);
89 if (isLua(L->ci)) /* metamethod invoked from a Lua function? */ 88 /* metamethod may yield only when called from Lua code */
90 L->baseCcalls++; /* allow it to yield */ 89 luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
91 luaD_call(L, L->top - (4 - hasres), hasres);
92 L->baseCcalls = oldbase;
93 if (hasres) { /* if has result, move it to its place */ 90 if (hasres) { /* if has result, move it to its place */
94 p3 = restorestack(L, result); 91 p3 = restorestack(L, result);
95 setobjs2s(L, p3, --L->top); 92 setobjs2s(L, p3, --L->top);
@@ -356,6 +353,61 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
356} 353}
357 354
358 355
356/*
357** finish execution of an opcode interrupted by an yield
358*/
359void luaV_finishOp (lua_State *L) {
360 Instruction inst = *(L->savedpc - 1); /* interrupted instruction */
361 switch (GET_OPCODE(inst)) { /* finish its execution */
362 case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
363 case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
364 case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: {
365 setobjs2s(L, L->base + GETARG_A(inst), --L->top);
366 break;
367 }
368 case OP_LE: case OP_LT: case OP_EQ: {
369 int res = !l_isfalse(L->top - 1);
370 L->top--;
371 /* metamethod should not be called when operand is K */
372 lua_assert(!ISK(GETARG_B(inst)));
373 if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */
374 ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE)))
375 res = !res; /* invert result */
376 lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP);
377 if (res != GETARG_A(inst)) /* condition failed? */
378 L->savedpc++; /* skip jump instruction */
379 break;
380 }
381 case OP_CONCAT: {
382 StkId top = L->top - 1; /* top when __concat was called */
383 int last = cast_int(top - L->base) - 2; /* last element and ... */
384 int b = GETARG_B(inst); /* ... first element to concatenate */
385 int total = last - b + 1; /* number of elements to concatenate */
386 setobj2s(L, top - 2, top); /* put TM result in proper position */
387 L->top = L->ci->top; /* correct top */
388 if (total > 1) /* are there elements to concat? */
389 luaV_concat(L, total, last); /* concat them (may yield again) */
390 /* move final result to final position */
391 setobj2s(L, L->base + GETARG_A(inst), L->base + b);
392 break;
393 }
394 case OP_TFORCALL: {
395 lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP);
396 L->top = L->ci->top; /* correct top */
397 break;
398 }
399 case OP_CALL: {
400 if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */
401 L->top = L->ci->top; /* adjust results */
402 break;
403 }
404 case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE:
405 break;
406 default: lua_assert(0);
407 }
408}
409
410
359 411
360/* 412/*
361** some macros for common tasks in `luaV_execute' 413** some macros for common tasks in `luaV_execute'
@@ -672,11 +724,9 @@ void luaV_execute (lua_State *L) {
672 setobjs2s(L, cb+2, ra+2); 724 setobjs2s(L, cb+2, ra+2);
673 setobjs2s(L, cb+1, ra+1); 725 setobjs2s(L, cb+1, ra+1);
674 setobjs2s(L, cb, ra); 726 setobjs2s(L, cb, ra);
675 L->baseCcalls++; /* allow yields */
676 L->top = cb + 3; /* func. + 2 args (state and index) */ 727 L->top = cb + 3; /* func. + 2 args (state and index) */
677 Protect(luaD_call(L, cb, GETARG_C(i))); 728 Protect(luaD_call(L, cb, GETARG_C(i), 1));
678 L->top = L->ci->top; 729 L->top = L->ci->top;
679 L->baseCcalls--;
680 i = *(L->savedpc++); /* go to next instruction */ 730 i = *(L->savedpc++); /* go to next instruction */
681 ra = RA(i); 731 ra = RA(i);
682 lua_assert(GET_OPCODE(i) == OP_TFORLOOP); 732 lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
@@ -725,8 +775,8 @@ void luaV_execute (lua_State *L) {
725 ncl = luaF_newLclosure(L, nup, cl->env); 775 ncl = luaF_newLclosure(L, nup, cl->env);
726 ncl->l.p = p; 776 ncl->l.p = p;
727 setclvalue(L, ra, ncl); 777 setclvalue(L, ra, ncl);
728 for (j=0; j<nup; j++, L->savedpc++) { 778 for (j=0; j<nup; j++) {
729 Instruction u = *L->savedpc; 779 Instruction u = *L->savedpc++;
730 if (GET_OPCODE(u) == OP_GETUPVAL) 780 if (GET_OPCODE(u) == OP_GETUPVAL)
731 ncl->l.upvals[j] = cl->upvals[GETARG_B(u)]; 781 ncl->l.upvals[j] = cl->upvals[GETARG_B(u)];
732 else { 782 else {
diff --git a/lvm.h b/lvm.h
index 8a3ae994..2d68f406 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 2.6 2007/02/09 13:04:52 roberto Exp roberto $ 2** $Id: lvm.h,v 2.7 2008/08/26 13:27:42 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -32,6 +32,7 @@ LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
32 StkId val); 32 StkId val);
33LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, 33LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
34 StkId val); 34 StkId val);
35LUAI_FUNC void luaV_finishOp (lua_State *L);
35LUAI_FUNC void luaV_execute (lua_State *L); 36LUAI_FUNC void luaV_execute (lua_State *L);
36LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); 37LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);
37 38