summaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-11-06 17:08:00 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-11-06 17:08:00 -0200
commit118347d8c3b83ea0291918e81c5367937316fabb (patch)
treeb77d5b6e03d9ae20841bd80a50cc56237bdf16f5 /ldo.c
parent6820da509686ce06fdb3de58856056476f55f534 (diff)
downloadlua-118347d8c3b83ea0291918e81c5367937316fabb.tar.gz
lua-118347d8c3b83ea0291918e81c5367937316fabb.tar.bz2
lua-118347d8c3b83ea0291918e81c5367937316fabb.zip
new API for coroutines
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c97
1 files changed, 38 insertions, 59 deletions
diff --git a/ldo.c b/ldo.c
index 9ae6a116..19968f32 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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
47static void seterrorobj (lua_State *L, int errcode) { 47static 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
301LUA_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
308static 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
317static void resume (lua_State *L, void *ud) { 302static 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
340LUA_API int lua_resume (lua_State *L, lua_State *co) { 329LUA_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}