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 /ldo.c | |
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).
Diffstat (limited to 'ldo.c')
-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 */ |