diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 30 |
1 files changed, 18 insertions, 12 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.3 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.4 2004/05/10 17:50:51 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 | */ |
@@ -219,7 +219,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
219 | } | 219 | } |
220 | 220 | ||
221 | 221 | ||
222 | StkId luaD_precall (lua_State *L, StkId func) { | 222 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
223 | LClosure *cl; | 223 | LClosure *cl; |
224 | ptrdiff_t funcr = savestack(L, func); | 224 | ptrdiff_t funcr = savestack(L, func); |
225 | if (!ttisfunction(func)) /* `func' is not a function? */ | 225 | if (!ttisfunction(func)) /* `func' is not a function? */ |
@@ -239,10 +239,11 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
239 | ci->top = L->base + p->maxstacksize; | 239 | ci->top = L->base + p->maxstacksize; |
240 | ci->u.l.savedpc = p->code; /* starting point */ | 240 | ci->u.l.savedpc = p->code; /* starting point */ |
241 | ci->u.l.tailcalls = 0; | 241 | ci->u.l.tailcalls = 0; |
242 | ci->nresults = nresults; | ||
242 | for (st = L->top; st < ci->top; st++) | 243 | for (st = L->top; st < ci->top; st++) |
243 | setnilvalue(st); | 244 | setnilvalue(st); |
244 | L->top = ci->top; | 245 | L->top = ci->top; |
245 | return NULL; | 246 | return PCRLUA; |
246 | } | 247 | } |
247 | else { /* if is a C function, call it */ | 248 | else { /* if is a C function, call it */ |
248 | CallInfo *ci; | 249 | CallInfo *ci; |
@@ -256,7 +257,14 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
256 | lua_unlock(L); | 257 | lua_unlock(L); |
257 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ | 258 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ |
258 | lua_lock(L); | 259 | lua_lock(L); |
259 | return L->top - n; | 260 | if (n >= 0) { /* no yielding? */ |
261 | luaD_poscall(L, nresults, L->top - n); | ||
262 | return PCRC; | ||
263 | } | ||
264 | else { | ||
265 | ci->nresults = nresults; | ||
266 | return PCRYIELD; | ||
267 | } | ||
260 | } | 268 | } |
261 | } | 269 | } |
262 | 270 | ||
@@ -297,17 +305,16 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | |||
297 | ** function position. | 305 | ** function position. |
298 | */ | 306 | */ |
299 | void luaD_call (lua_State *L, StkId func, int nResults) { | 307 | void luaD_call (lua_State *L, StkId func, int nResults) { |
300 | StkId firstResult; | ||
301 | if (++L->nCcalls >= LUA_MAXCCALLS) { | 308 | if (++L->nCcalls >= LUA_MAXCCALLS) { |
302 | if (L->nCcalls == LUA_MAXCCALLS) | 309 | if (L->nCcalls == LUA_MAXCCALLS) |
303 | luaG_runerror(L, "C stack overflow"); | 310 | luaG_runerror(L, "C stack overflow"); |
304 | else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) | 311 | else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) |
305 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 312 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ |
306 | } | 313 | } |
307 | firstResult = luaD_precall(L, func); | 314 | if (luaD_precall(L, func, nResults) == PCRLUA) { /* is a Lua function? */ |
308 | if (firstResult == NULL) /* is a Lua function? */ | 315 | StkId firstResult = luaV_execute(L, 1); /* call it */ |
309 | firstResult = luaV_execute(L, 1); /* call it */ | 316 | luaD_poscall(L, nResults, firstResult); |
310 | luaD_poscall(L, nResults, firstResult); | 317 | } |
311 | L->nCcalls--; | 318 | L->nCcalls--; |
312 | luaC_checkGC(L); | 319 | luaC_checkGC(L); |
313 | } | 320 | } |
@@ -319,15 +326,14 @@ static void resume (lua_State *L, void *ud) { | |||
319 | CallInfo *ci = L->ci; | 326 | CallInfo *ci = L->ci; |
320 | if (!L->isSuspended) { | 327 | if (!L->isSuspended) { |
321 | lua_assert(ci == L->base_ci && nargs < L->top - L->base); | 328 | lua_assert(ci == L->base_ci && nargs < L->top - L->base); |
322 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | 329 | luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */ |
323 | } | 330 | } |
324 | else { /* resuming from previous yield */ | 331 | else { /* resuming from previous yield */ |
325 | if (!f_isLua(ci)) { /* `common' yield? */ | 332 | if (!f_isLua(ci)) { /* `common' yield? */ |
326 | /* finish interrupted execution of `OP_CALL' */ | 333 | /* finish interrupted execution of `OP_CALL' */ |
327 | int nresults; | 334 | int nresults = ci->nresults; |
328 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 335 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
329 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 336 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
330 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | ||
331 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ | 337 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ |
332 | if (nresults >= 0) L->top = L->ci->top; | 338 | if (nresults >= 0) L->top = L->ci->top; |
333 | } /* else yielded inside a hook: just continue its execution */ | 339 | } /* else yielded inside a hook: just continue its execution */ |