diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-06 17:08:00 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-06 17:08:00 -0200 |
commit | 118347d8c3b83ea0291918e81c5367937316fabb (patch) | |
tree | b77d5b6e03d9ae20841bd80a50cc56237bdf16f5 /ldo.c | |
parent | 6820da509686ce06fdb3de58856056476f55f534 (diff) | |
download | lua-118347d8c3b83ea0291918e81c5367937316fabb.tar.gz lua-118347d8c3b83ea0291918e81c5367937316fabb.tar.bz2 lua-118347d8c3b83ea0291918e81c5367937316fabb.zip |
new API for coroutines
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 97 |
1 files changed, 38 insertions, 59 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.196 2002/10/09 13:42:01 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.197 2002/10/25 20:05:28 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 | */ |
@@ -44,22 +44,23 @@ struct lua_longjmp { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | 46 | ||
47 | static void seterrorobj (lua_State *L, int errcode) { | 47 | static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { |
48 | switch (errcode) { | 48 | switch (errcode) { |
49 | case LUA_ERRMEM: { | 49 | case LUA_ERRMEM: { |
50 | setsvalue(L->top, luaS_new(L, MEMERRMSG)); | 50 | setsvalue(oldtop, luaS_new(L, MEMERRMSG)); |
51 | break; | 51 | break; |
52 | } | 52 | } |
53 | case LUA_ERRERR: { | 53 | case LUA_ERRERR: { |
54 | setsvalue(L->top, luaS_new(L, "error in error handling")); | 54 | setsvalue(oldtop, luaS_new(L, "error in error handling")); |
55 | break; | 55 | break; |
56 | } | 56 | } |
57 | case LUA_ERRSYNTAX: | 57 | case LUA_ERRSYNTAX: |
58 | case LUA_ERRRUN: { | 58 | case LUA_ERRRUN: { |
59 | return; /* error message already on top */ | 59 | setobj(oldtop, L->top - 1); /* error message on current top */ |
60 | break; | ||
60 | } | 61 | } |
61 | } | 62 | } |
62 | L->top++; | 63 | L->top = oldtop + 1; |
63 | } | 64 | } |
64 | 65 | ||
65 | 66 | ||
@@ -298,67 +299,46 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
298 | } | 299 | } |
299 | 300 | ||
300 | 301 | ||
301 | LUA_API void lua_cobegin (lua_State *L, int nargs) { | ||
302 | lua_lock(L); | ||
303 | luaD_precall(L, L->top - (nargs+1)); | ||
304 | lua_unlock(L); | ||
305 | } | ||
306 | |||
307 | |||
308 | static void move_results (lua_State *L, TObject *from, TObject *to) { | ||
309 | while (from < to) { | ||
310 | setobj(L->top, from); | ||
311 | from++; | ||
312 | incr_top(L); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | |||
317 | static void resume (lua_State *L, void *ud) { | 302 | static void resume (lua_State *L, void *ud) { |
318 | StkId firstResult; | 303 | StkId firstResult; |
304 | int nargs = *cast(int *, ud); | ||
319 | CallInfo *ci = L->ci; | 305 | CallInfo *ci = L->ci; |
320 | if (ci->state & CI_C) { /* not first time (i.e. inside a yield)? */ | 306 | if (ci == L->base_ci) { /* no activation record? */ |
307 | if (nargs >= L->top - L->ci->base) | ||
308 | luaG_runerror(L, "cannot resume dead coroutine"); | ||
309 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | ||
310 | } | ||
311 | else if (ci->state && CI_YIELD) { /* inside a yield? */ | ||
321 | /* finish interrupted execution of `OP_CALL' */ | 312 | /* finish interrupted execution of `OP_CALL' */ |
322 | int nresults; | 313 | int nresults; |
323 | lua_assert((ci-1)->state & CI_SAVEDPC); | 314 | lua_assert((ci-1)->state & CI_SAVEDPC); |
324 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 315 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
325 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 316 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
326 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | 317 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; |
327 | luaD_poscall(L, nresults, L->top); /* complete it */ | 318 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ |
328 | if (nresults >= 0) L->top = L->ci->top; | 319 | if (nresults >= 0) L->top = L->ci->top; |
329 | } | 320 | } |
321 | else | ||
322 | luaG_runerror(L, "cannot resume non-suspended coroutine"); | ||
330 | firstResult = luaV_execute(L); | 323 | firstResult = luaV_execute(L); |
331 | if (firstResult == NULL) /* yield? */ | 324 | if (firstResult != NULL) /* return? */ |
332 | *cast(int *, ud) = L->ci->u.c.yield_results; | ||
333 | else { /* return */ | ||
334 | *cast(int *, ud) = L->top - firstResult; | ||
335 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ | 325 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ |
336 | } | ||
337 | } | 326 | } |
338 | 327 | ||
339 | 328 | ||
340 | LUA_API int lua_resume (lua_State *L, lua_State *co) { | 329 | LUA_API int lua_resume (lua_State *L, int nargs) { |
341 | CallInfo *ci; | ||
342 | int numres; | ||
343 | int status; | 330 | int status; |
331 | int old_allowhooks; | ||
344 | lua_lock(L); | 332 | lua_lock(L); |
345 | ci = co->ci; | 333 | old_allowhooks = allowhook(L); |
346 | if (ci == co->base_ci) { /* no activation record? ?? */ | 334 | lua_assert(L->errfunc == 0); |
347 | luaO_pushfstring(L, "cannot resume dead thread"); | 335 | status = luaD_rawrunprotected(L, resume, &nargs); |
348 | status = LUA_ERRRUN; | 336 | if (status != 0) { |
349 | } | 337 | L->ci = L->base_ci; /* `kill' thread (??) */ |
350 | else if (co->errorJmp != NULL) { /* ?? */ | 338 | seterrorobj(L, status, L->ci->base); |
351 | luaO_pushfstring(L, "cannot resume active thread"); | 339 | luaF_close(L, L->top); /* close eventual pending closures */ |
352 | status = LUA_ERRRUN; | 340 | setallowhook(L, old_allowhooks); |
353 | } | 341 | restore_stack_limit(L); |
354 | else { | ||
355 | status = luaD_rawrunprotected(co, resume, &numres); | ||
356 | if (status == 0) | ||
357 | move_results(L, co->top - numres, co->top); | ||
358 | else { | ||
359 | setobj(L->top++, co->top - 1); /* move error message to other stack */ | ||
360 | co->ci = co->base_ci; /* `kill' thread */ | ||
361 | } | ||
362 | } | 342 | } |
363 | lua_unlock(L); | 343 | lua_unlock(L); |
364 | return status; | 344 | return status; |
@@ -372,7 +352,12 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
372 | if ((ci-1)->state & CI_C) | 352 | if ((ci-1)->state & CI_C) |
373 | luaG_runerror(L, "cannot yield a C function"); | 353 | luaG_runerror(L, "cannot yield a C function"); |
374 | lua_assert(ci->state & CI_C); /* current function is not Lua */ | 354 | lua_assert(ci->state & CI_C); /* current function is not Lua */ |
375 | ci->u.c.yield_results = nresults; | 355 | if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ |
356 | int i; | ||
357 | for (i=0; i<nresults; i++) /* move down results */ | ||
358 | setobj(ci->base + i, L->top - nresults + i); | ||
359 | L->top = ci->base + nresults; | ||
360 | } | ||
376 | lua_unlock(L); | 361 | lua_unlock(L); |
377 | return -1; | 362 | return -1; |
378 | } | 363 | } |
@@ -405,12 +390,8 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) { | |||
405 | c.nresults = nresults; | 390 | c.nresults = nresults; |
406 | status = luaD_rawrunprotected(L, &f_call, &c); | 391 | status = luaD_rawrunprotected(L, &f_call, &c); |
407 | if (status != 0) { /* an error occurred? */ | 392 | if (status != 0) { /* an error occurred? */ |
408 | StkId err; /* error msg. position */ | 393 | StkId oldtop = restorestack(L, old_top) - (nargs+1); |
409 | seterrorobj(L, status); | 394 | seterrorobj(L, status, oldtop); |
410 | err = L->top - 1; | ||
411 | /* remove parameters and func from the stack */ | ||
412 | L->top = restorestack(L, old_top) - (nargs+1); | ||
413 | setobj(L->top++, err); /* copy error message to corrected top */ | ||
414 | luaF_close(L, L->top); /* close eventual pending closures */ | 395 | luaF_close(L, L->top); /* close eventual pending closures */ |
415 | L->ci = restoreci(L, old_ci); | 396 | L->ci = restoreci(L, old_ci); |
416 | setallowhook(L, old_allowhooks); | 397 | setallowhook(L, old_allowhooks); |
@@ -461,9 +442,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { | |||
461 | } | 442 | } |
462 | else { /* error */ | 443 | else { /* error */ |
463 | StkId oldtop = restorestack(L, oldtopr); | 444 | StkId oldtop = restorestack(L, oldtopr); |
464 | seterrorobj(L, status); | 445 | seterrorobj(L, status, oldtop); |
465 | setobj(oldtop, L->top - 1); /* copy error message to old top */ | ||
466 | L->top = oldtop+1; | ||
467 | } | 446 | } |
468 | return status; | 447 | return status; |
469 | } | 448 | } |