diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-12-10 16:20:07 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-12-10 16:20:07 -0200 |
| commit | 2bb19ccf08381c7755015dfa61e2eb4675637c78 (patch) | |
| tree | d5a26b1a026834987746e3e07fa688a91c0b87e8 | |
| parent | 64d5df77721da0183360d50da8d68663526bfa6a (diff) | |
| download | lua-2bb19ccf08381c7755015dfa61e2eb4675637c78.tar.gz lua-2bb19ccf08381c7755015dfa61e2eb4675637c78.tar.bz2 lua-2bb19ccf08381c7755015dfa61e2eb4675637c78.zip | |
reordering of some functions + cleaner way to code lua_resume/resume +
small bug in lua_resume (in case of calling errors lua_resume should
remove only new arguments from the stack and push error message).
| -rw-r--r-- | ldo.c | 110 |
1 files changed, 55 insertions, 55 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.74 2009/11/27 15:37:59 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.75 2009/12/08 18:59:24 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 | */ |
| @@ -59,9 +59,7 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
| 59 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | 59 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); |
| 60 | break; | 60 | break; |
| 61 | } | 61 | } |
| 62 | case LUA_ERRSYNTAX: | 62 | default: { |
| 63 | case LUA_ERRGCMM: | ||
| 64 | case LUA_ERRRUN: { | ||
| 65 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ | 63 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ |
| 66 | break; | 64 | break; |
| 67 | } | 65 | } |
| @@ -405,33 +403,67 @@ static void unroll (lua_State *L, void *ud) { | |||
| 405 | 403 | ||
| 406 | 404 | ||
| 407 | /* | 405 | /* |
| 408 | ** data to be passed to 'resume' by 'lua_resume' | 406 | ** check whether thread has a suspended protected call |
| 409 | */ | 407 | */ |
| 410 | struct ResumeData { | 408 | static CallInfo *findpcall (lua_State *L) { |
| 411 | StkId firstArg; /* stack index of first argument */ | 409 | CallInfo *ci; |
| 412 | int recover; /* should try to recover in case of errors */ | 410 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ |
| 413 | }; | 411 | if (ci->callstatus & CIST_YPCALL) |
| 412 | return ci; | ||
| 413 | } | ||
| 414 | return NULL; /* no pending pcall */ | ||
| 415 | } | ||
| 416 | |||
| 417 | |||
| 418 | static int recover (lua_State *L, int status) { | ||
| 419 | StkId oldtop; | ||
| 420 | CallInfo *ci = findpcall(L); | ||
| 421 | if (ci == NULL) return 0; /* no recovery point */ | ||
| 422 | /* "finish" luaD_pcall */ | ||
| 423 | oldtop = restorestack(L, ci->u.c.oldtop); | ||
| 424 | luaF_close(L, oldtop); | ||
| 425 | luaD_seterrorobj(L, status, oldtop); | ||
| 426 | L->ci = ci; | ||
| 427 | L->allowhook = ci->u.c.old_allowhook; | ||
| 428 | L->nny = 0; /* should be zero to be yieldable */ | ||
| 429 | luaD_shrinkstack(L); | ||
| 430 | L->errfunc = ci->u.c.old_errfunc; | ||
| 431 | ci->callstatus |= CIST_STAT; /* call has error status */ | ||
| 432 | ci->u.c.status = status; /* (here it is) */ | ||
| 433 | return 1; /* continue running the coroutine */ | ||
| 434 | } | ||
| 435 | |||
| 436 | |||
| 437 | /* | ||
| 438 | ** signal an error in the call to 'resume', not in the execution of the | ||
| 439 | ** coroutine itself. (Such errors should not be handled by any coroutine | ||
| 440 | ** error hanlder and should not kill the coroutine.) | ||
| 441 | */ | ||
| 442 | static void resume_error (lua_State *L, const char *msg, StkId firstArg) { | ||
| 443 | L->top = firstArg; /* remove args from the stack */ | ||
| 444 | setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ | ||
| 445 | incr_top(L); | ||
| 446 | luaD_throw(L, -1); /* jump back to 'lua_resume' */ | ||
| 447 | } | ||
| 414 | 448 | ||
| 415 | 449 | ||
| 416 | /* | 450 | /* |
| 417 | ** do the work for 'lua_resume' in protected mode | 451 | ** do the work for 'lua_resume' in protected mode |
| 418 | */ | 452 | */ |
| 419 | static void resume (lua_State *L, void *ud) { | 453 | static void resume (lua_State *L, void *ud) { |
| 420 | struct ResumeData *rd = cast(struct ResumeData *, ud); | 454 | StkId firstArg = cast(StkId, ud); |
| 421 | CallInfo *ci = L->ci; | 455 | CallInfo *ci = L->ci; |
| 422 | if (G(L)->nCcalls >= LUAI_MAXCCALLS) | 456 | if (G(L)->nCcalls >= LUAI_MAXCCALLS) |
| 423 | luaG_runerror(L, "C stack overflow"); | 457 | resume_error(L, "C stack overflow", firstArg); |
| 424 | if (L->status == LUA_OK) { /* may be starting a coroutine */ | 458 | if (L->status == LUA_OK) { /* may be starting a coroutine */ |
| 425 | if (ci != &L->base_ci) { /* not in base level? */ | 459 | if (ci != &L->base_ci) /* not in base level? */ |
| 426 | rd->recover = 0; /* thread may not be running as a coroutine */ | 460 | resume_error(L, "cannot resume non-suspended coroutine", firstArg); |
| 427 | luaG_runerror(L, "cannot resume non-suspended coroutine"); | ||
| 428 | } | ||
| 429 | /* coroutine is in base level; start running it */ | 461 | /* coroutine is in base level; start running it */ |
| 430 | if (!luaD_precall(L, rd->firstArg - 1, LUA_MULTRET)) /* Lua function? */ | 462 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ |
| 431 | luaV_execute(L); /* call it */ | 463 | luaV_execute(L); /* call it */ |
| 432 | } | 464 | } |
| 433 | else if (L->status != LUA_YIELD) | 465 | else if (L->status != LUA_YIELD) |
| 434 | luaG_runerror(L, "cannot resume dead coroutine"); | 466 | resume_error(L, "cannot resume dead coroutine", firstArg); |
| 435 | else { /* resuming from previous yield */ | 467 | else { /* resuming from previous yield */ |
| 436 | L->status = LUA_OK; | 468 | L->status = LUA_OK; |
| 437 | if (isLua(ci)) /* yielded inside a hook? */ | 469 | if (isLua(ci)) /* yielded inside a hook? */ |
| @@ -446,58 +478,26 @@ static void resume (lua_State *L, void *ud) { | |||
| 446 | n = (*ci->u.c.k)(L); /* call continuation */ | 478 | n = (*ci->u.c.k)(L); /* call continuation */ |
| 447 | lua_lock(L); | 479 | lua_lock(L); |
| 448 | api_checknelems(L, n); | 480 | api_checknelems(L, n); |
| 449 | rd->firstArg = L->top - n; /* yield results come from continuation */ | 481 | firstArg = L->top - n; /* yield results come from continuation */ |
| 450 | } | 482 | } |
| 451 | G(L)->nCcalls--; /* finish 'luaD_call' */ | 483 | G(L)->nCcalls--; /* finish 'luaD_call' */ |
| 452 | luaD_poscall(L, rd->firstArg); /* finish 'luaD_precall' */ | 484 | luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ |
| 453 | } | 485 | } |
| 454 | unroll(L, NULL); | 486 | unroll(L, NULL); |
| 455 | } | 487 | } |
| 456 | } | 488 | } |
| 457 | 489 | ||
| 458 | 490 | ||
| 459 | /* | ||
| 460 | ** check whether thread has a suspended protected call | ||
| 461 | */ | ||
| 462 | static CallInfo *findpcall (lua_State *L) { | ||
| 463 | CallInfo *ci; | ||
| 464 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ | ||
| 465 | if (ci->callstatus & CIST_YPCALL) | ||
| 466 | return ci; | ||
| 467 | } | ||
| 468 | return NULL; /* no pending pcall */ | ||
| 469 | } | ||
| 470 | |||
| 471 | |||
| 472 | static int recover (lua_State *L, int status) { | ||
| 473 | StkId oldtop; | ||
| 474 | CallInfo *ci = findpcall(L); | ||
| 475 | if (ci == NULL) return 0; /* no recovery point */ | ||
| 476 | /* "finish" luaD_pcall */ | ||
| 477 | oldtop = restorestack(L, ci->u.c.oldtop); | ||
| 478 | luaF_close(L, oldtop); | ||
| 479 | luaD_seterrorobj(L, status, oldtop); | ||
| 480 | L->ci = ci; | ||
| 481 | L->allowhook = ci->u.c.old_allowhook; | ||
| 482 | L->nny = 0; /* should be zero to be yieldable */ | ||
| 483 | luaD_shrinkstack(L); | ||
| 484 | L->errfunc = ci->u.c.old_errfunc; | ||
| 485 | ci->callstatus |= CIST_STAT; /* call has error status */ | ||
| 486 | ci->u.c.status = status; /* (here it is) */ | ||
| 487 | return 1; /* continue running the coroutine */ | ||
| 488 | } | ||
| 489 | |||
| 490 | |||
| 491 | LUA_API int lua_resume (lua_State *L, int nargs) { | 491 | LUA_API int lua_resume (lua_State *L, int nargs) { |
| 492 | struct ResumeData rd; | ||
| 493 | int status; | 492 | int status; |
| 494 | lua_lock(L); | 493 | lua_lock(L); |
| 495 | luai_userstateresume(L, nargs); | 494 | luai_userstateresume(L, nargs); |
| 496 | ++G(L)->nCcalls; /* count resume */ | 495 | ++G(L)->nCcalls; /* count resume */ |
| 497 | L->nny = 0; /* allow yields */ | 496 | L->nny = 0; /* allow yields */ |
| 498 | rd.firstArg = L->top - nargs; rd.recover = 1; | 497 | status = luaD_rawrunprotected(L, resume, L->top - nargs); |
| 499 | status = luaD_rawrunprotected(L, resume, &rd); | 498 | if (status == -1) /* error calling 'lua_resume'? */ |
| 500 | if (rd.recover) { | 499 | status = LUA_ERRRUN; |
| 500 | else { /* yield or regular error */ | ||
| 501 | while (status != LUA_OK && status != LUA_YIELD) { /* error? */ | 501 | while (status != LUA_OK && status != LUA_YIELD) { /* error? */ |
| 502 | if (recover(L, status)) /* recover point? */ | 502 | if (recover(L, status)) /* recover point? */ |
| 503 | status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ | 503 | status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ |
