diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-11 18:27:41 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-11 18:27:41 -0200 |
| commit | 6272c843dee7544bf319afbac85e8064fa1f3a4b (patch) | |
| tree | b6b36f35516fe87ec3b29fb404a0091472894767 | |
| parent | 5d14ce612baf55c4f019842947388b44f8732d34 (diff) | |
| download | lua-6272c843dee7544bf319afbac85e8064fa1f3a4b.tar.gz lua-6272c843dee7544bf319afbac85e8064fa1f3a4b.tar.bz2 lua-6272c843dee7544bf319afbac85e8064fa1f3a4b.zip | |
`yield' passes its arguments to `resume'
Diffstat (limited to '')
| -rw-r--r-- | lbaselib.c | 35 | ||||
| -rw-r--r-- | ldo.c | 46 |
2 files changed, 47 insertions, 34 deletions
| @@ -415,6 +415,14 @@ static int luaB_tostring (lua_State *L) { | |||
| 415 | static int luaB_resume (lua_State *L) { | 415 | static int luaB_resume (lua_State *L) { |
| 416 | lua_State *co = (lua_State *)lua_touserdata(L, lua_upvalueindex(1)); | 416 | lua_State *co = (lua_State *)lua_touserdata(L, lua_upvalueindex(1)); |
| 417 | lua_resume(L, co); | 417 | lua_resume(L, co); |
| 418 | return lua_gettop(L); | ||
| 419 | } | ||
| 420 | |||
| 421 | |||
| 422 | |||
| 423 | static int gc_coroutine (lua_State *L) { | ||
| 424 | lua_State *co = (lua_State *)lua_touserdata(L, 1); | ||
| 425 | lua_closethread(L, co); | ||
| 418 | return 0; | 426 | return 0; |
| 419 | } | 427 | } |
| 420 | 428 | ||
| @@ -422,22 +430,30 @@ static int luaB_resume (lua_State *L) { | |||
| 422 | static int luaB_coroutine (lua_State *L) { | 430 | static int luaB_coroutine (lua_State *L) { |
| 423 | lua_State *NL; | 431 | lua_State *NL; |
| 424 | int ref; | 432 | int ref; |
| 425 | luaL_check_type(L, 1, LUA_TFUNCTION); | 433 | int i; |
| 434 | int n = lua_gettop(L); | ||
| 435 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, | ||
| 436 | "Lua function expected"); | ||
| 426 | NL = lua_newthread(L, 0); | 437 | NL = lua_newthread(L, 0); |
| 427 | if (NL == NULL) lua_error(L, "unable to create new thread"); | 438 | if (NL == NULL) lua_error(L, "unable to create new thread"); |
| 428 | /* move function from L to NL */ | 439 | /* move function and arguments from L to NL */ |
| 429 | ref = lua_ref(L, 1); | 440 | for (i=0; i<n; i++) { |
| 430 | lua_getref(NL, ref); | 441 | ref = lua_ref(L, 1); |
| 431 | lua_unref(L, ref); | 442 | lua_getref(NL, ref); |
| 432 | lua_cobegin(NL, 0); | 443 | lua_insert(NL, 1); |
| 444 | lua_unref(L, ref); | ||
| 445 | } | ||
| 446 | lua_cobegin(NL, n-1); | ||
| 433 | lua_newuserdatabox(L, NL); | 447 | lua_newuserdatabox(L, NL); |
| 448 | lua_getstr(L, LUA_REGISTRYINDEX, "Coroutine"); | ||
| 449 | lua_seteventtable(L, -2); | ||
| 434 | lua_pushcclosure(L, luaB_resume, 1); | 450 | lua_pushcclosure(L, luaB_resume, 1); |
| 435 | return 1; | 451 | return 1; |
| 436 | } | 452 | } |
| 437 | 453 | ||
| 438 | 454 | ||
| 439 | static int luaB_yield (lua_State *L) { | 455 | static int luaB_yield (lua_State *L) { |
| 440 | return lua_yield(L, 0); | 456 | return lua_yield(L, lua_gettop(L)); |
| 441 | } | 457 | } |
| 442 | 458 | ||
| 443 | 459 | ||
| @@ -683,6 +699,11 @@ LUALIB_API int lua_baselibopen (lua_State *L) { | |||
| 683 | lua_newtable(L); | 699 | lua_newtable(L); |
| 684 | lua_pushcclosure(L, luaB_require, 1); | 700 | lua_pushcclosure(L, luaB_require, 1); |
| 685 | lua_setglobal(L, "require"); | 701 | lua_setglobal(L, "require"); |
| 702 | /* create metatable for coroutines */ | ||
| 703 | lua_newtable(L); | ||
| 704 | lua_pushcfunction(L, gc_coroutine); | ||
| 705 | lua_setstr(L, -2, "gc"); | ||
| 706 | lua_setstr(L, LUA_REGISTRYINDEX, "Coroutine"); | ||
| 686 | return 0; | 707 | return 0; |
| 687 | } | 708 | } |
| 688 | 709 | ||
| @@ -29,9 +29,6 @@ | |||
| 29 | #include "lzio.h" | 29 | #include "lzio.h" |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | /* space to handle stack overflow errors */ | ||
| 33 | #define EXTRA_STACK (2*LUA_MINSTACK) | ||
| 34 | |||
| 35 | 32 | ||
| 36 | static void restore_stack_limit (lua_State *L) { | 33 | static void restore_stack_limit (lua_State *L) { |
| 37 | StkId limit = L->stack+(L->stacksize-EXTRA_STACK)-1; | 34 | StkId limit = L->stack+(L->stacksize-EXTRA_STACK)-1; |
| @@ -40,21 +37,6 @@ static void restore_stack_limit (lua_State *L) { | |||
| 40 | } | 37 | } |
| 41 | 38 | ||
| 42 | 39 | ||
| 43 | void luaD_init (lua_State *L, int stacksize) { | ||
| 44 | stacksize += EXTRA_STACK; | ||
| 45 | L->stack = luaM_newvector(L, stacksize, TObject); | ||
| 46 | L->stacksize = stacksize; | ||
| 47 | L->top = L->stack + RESERVED_STACK_PREFIX; | ||
| 48 | restore_stack_limit(L); | ||
| 49 | luaM_reallocvector(L, L->base_ci, 0, 20, CallInfo); | ||
| 50 | L->ci = L->base_ci; | ||
| 51 | L->ci->base = L->top; | ||
| 52 | L->ci->savedpc = NULL; | ||
| 53 | L->size_ci = 20; | ||
| 54 | L->end_ci = L->base_ci + L->size_ci; | ||
| 55 | } | ||
| 56 | |||
| 57 | |||
| 58 | void luaD_stackerror (lua_State *L) { | 40 | void luaD_stackerror (lua_State *L) { |
| 59 | if (L->stack_last == L->stack+L->stacksize-1) { | 41 | if (L->stack_last == L->stack+L->stacksize-1) { |
| 60 | /* overflow while handling overflow */ | 42 | /* overflow while handling overflow */ |
| @@ -231,15 +213,21 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
| 231 | 213 | ||
| 232 | 214 | ||
| 233 | LUA_API void lua_cobegin (lua_State *L, int nargs) { | 215 | LUA_API void lua_cobegin (lua_State *L, int nargs) { |
| 234 | StkId func; | ||
| 235 | lua_lock(L); | 216 | lua_lock(L); |
| 236 | func = L->top - (nargs+1); /* coroutine main function */ | 217 | luaD_precall(L, L->top - (nargs+1)); |
| 237 | if (luaD_precall(L, func) != NULL) | ||
| 238 | luaD_error(L, "coroutine started with a C function"); | ||
| 239 | lua_unlock(L); | 218 | lua_unlock(L); |
| 240 | } | 219 | } |
| 241 | 220 | ||
| 242 | 221 | ||
| 222 | static void resume_results (lua_State *L, lua_State *from, int numresults) { | ||
| 223 | while (numresults) { | ||
| 224 | setobj(L->top, from->top - numresults); | ||
| 225 | numresults--; | ||
| 226 | incr_top; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | |||
| 243 | LUA_API void lua_resume (lua_State *L, lua_State *co) { | 231 | LUA_API void lua_resume (lua_State *L, lua_State *co) { |
| 244 | StkId firstResult; | 232 | StkId firstResult; |
| 245 | lua_lock(L); | 233 | lua_lock(L); |
| @@ -248,10 +236,13 @@ LUA_API void lua_resume (lua_State *L, lua_State *co) { | |||
| 248 | lua_assert(co->errorJmp == NULL); | 236 | lua_assert(co->errorJmp == NULL); |
| 249 | co->errorJmp = L->errorJmp; | 237 | co->errorJmp = L->errorJmp; |
| 250 | firstResult = luaV_execute(co); | 238 | firstResult = luaV_execute(co); |
| 251 | if (firstResult != NULL) /* `return'? */ | 239 | if (firstResult != NULL) { /* `return'? */ |
| 252 | luaD_poscall(co, LUA_MULTRET, firstResult); /* ends this coroutine */ | 240 | resume_results(L, co, co->top - firstResult); |
| 241 | luaD_poscall(co, 0, firstResult); /* ends this coroutine */ | ||
| 242 | } | ||
| 253 | else { /* `yield' */ | 243 | else { /* `yield' */ |
| 254 | int nresults = GETARG_C(*((co->ci-1)->savedpc - 1)) - 1; | 244 | int nresults = GETARG_C(*((co->ci-1)->savedpc - 1)) - 1; |
| 245 | resume_results(L, co, co->ci->yield_results); | ||
| 255 | luaD_poscall(co, nresults, co->top); /* complete it */ | 246 | luaD_poscall(co, nresults, co->top); /* complete it */ |
| 256 | if (nresults >= 0) co->top = co->ci->top; | 247 | if (nresults >= 0) co->top = co->ci->top; |
| 257 | } | 248 | } |
| @@ -264,10 +255,11 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
| 264 | CallInfo *ci; | 255 | CallInfo *ci; |
| 265 | int ibase; | 256 | int ibase; |
| 266 | lua_lock(L); | 257 | lua_lock(L); |
| 267 | ci = L->ci - 1; /* call info of calling function */ | 258 | ci = L->ci; |
| 268 | if (ci->pc == NULL) | 259 | if (ci_func(ci-1)->c.isC) |
| 269 | luaD_error(L, "cannot `yield' a C function"); | 260 | luaD_error(L, "cannot `yield' a C function"); |
| 270 | ibase = L->top - ci->base; | 261 | ci->yield_results = nresults; /* very dirty trick! */ |
| 262 | ibase = L->top - (ci-1)->base; | ||
| 271 | lua_unlock(L); | 263 | lua_unlock(L); |
| 272 | return ibase; | 264 | return ibase; |
| 273 | } | 265 | } |
