diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-11-06 10:43:51 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-11-06 10:43:51 -0200 |
commit | b47209849321b17e2037bfa46abf530e69bcc869 (patch) | |
tree | 1915a213b71e70c7cdbc405b260ccdef48bedf21 /ldo.c | |
parent | 84b3daebbd09b334db0fa125700ffdb1d326c4f6 (diff) | |
download | lua-b47209849321b17e2037bfa46abf530e69bcc869.tar.gz lua-b47209849321b17e2037bfa46abf530e69bcc869.tar.bz2 lua-b47209849321b17e2037bfa46abf530e69bcc869.zip |
concat TM can yield
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 32 |
1 files changed, 21 insertions, 11 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.49 2008/10/28 16:53:16 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.50 2008/10/30 15:39:30 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 | */ |
@@ -390,7 +390,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
390 | static void unroll (lua_State *L) { | 390 | static void unroll (lua_State *L) { |
391 | for (;;) { | 391 | for (;;) { |
392 | Instruction inst; | 392 | Instruction inst; |
393 | luaV_execute(L); /* execute up to higher C 'boundary' */ | 393 | luaV_execute(L); /* execute down to higher C 'boundary' */ |
394 | if (L->ci == L->base_ci) { /* stack is empty? */ | 394 | if (L->ci == L->base_ci) { /* stack is empty? */ |
395 | lua_assert(L->baseCcalls == G(L)->nCcalls); | 395 | lua_assert(L->baseCcalls == G(L)->nCcalls); |
396 | return; /* coroutine finished normally */ | 396 | return; /* coroutine finished normally */ |
@@ -405,27 +405,38 @@ static void unroll (lua_State *L) { | |||
405 | break; | 405 | break; |
406 | } | 406 | } |
407 | case OP_LE: case OP_LT: case OP_EQ: { | 407 | case OP_LE: case OP_LT: case OP_EQ: { |
408 | int res; | 408 | int res = !l_isfalse(L->top - 1); |
409 | L->top--; | 409 | L->top--; |
410 | res = !l_isfalse(L->top); | 410 | /* metamethod should not be called when operand is K */ |
411 | /* cannot call metamethod with K operand */ | ||
412 | lua_assert(!ISK(GETARG_B(inst))); | 411 | lua_assert(!ISK(GETARG_B(inst))); |
413 | if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ | 412 | if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ |
414 | ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) | 413 | ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) |
415 | res = !res; /* invert result */ | 414 | res = !res; /* invert result */ |
416 | lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); | 415 | lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); |
417 | if (res == GETARG_A(inst)) | 416 | if (res != GETARG_A(inst)) /* condition failed? */ |
418 | L->savedpc += GETARG_sBx(*L->savedpc); /* jump */ | 417 | L->savedpc++; /* skip jump instruction */ |
419 | L->savedpc++; /* skip jump instruction */ | ||
420 | break; | 418 | break; |
421 | } | 419 | } |
422 | case OP_SETGLOBAL: case OP_SETTABLE: | 420 | case OP_CONCAT: { |
423 | break; /* nothing to be done */ | 421 | StkId top = L->top - 1; /* top when __concat was called */ |
422 | int last = cast_int(top - L->base) - 2; /* last element and ... */ | ||
423 | int b = GETARG_B(inst); /* ... first element to concatenate */ | ||
424 | int total = last - b + 1; /* number of elements to concatenate */ | ||
425 | setobj2s(L, top - 2, top); /* put TM result in proper position */ | ||
426 | L->top = L->ci->top; /* correct top */ | ||
427 | if (total > 1) /* are there elements to concat? */ | ||
428 | luaV_concat(L, total, last); /* concat them (may yield again) */ | ||
429 | /* move final result to final position */ | ||
430 | setobj2s(L, L->base + GETARG_A(inst), L->base + b); | ||
431 | continue; | ||
432 | } | ||
424 | case OP_TFORCALL: { | 433 | case OP_TFORCALL: { |
425 | lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); | 434 | lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); |
426 | L->top = L->ci->top; /* correct top */ | 435 | L->top = L->ci->top; /* correct top */ |
427 | break; | 436 | break; |
428 | } | 437 | } |
438 | case OP_SETGLOBAL: case OP_SETTABLE: | ||
439 | break; /* nothing to be done */ | ||
429 | default: lua_assert(0); | 440 | default: lua_assert(0); |
430 | } | 441 | } |
431 | } | 442 | } |
@@ -500,7 +511,6 @@ LUA_API int lua_resume (lua_State *L, int nargs) { | |||
500 | LUA_API int lua_yield (lua_State *L, int nresults) { | 511 | LUA_API int lua_yield (lua_State *L, int nresults) { |
501 | luai_userstateyield(L, nresults); | 512 | luai_userstateyield(L, nresults); |
502 | lua_lock(L); | 513 | lua_lock(L); |
503 | /*printf("yield: %d - %d\n", G(L)->nCcalls, L->baseCcalls);*/ | ||
504 | if (G(L)->nCcalls > L->baseCcalls) | 514 | if (G(L)->nCcalls > L->baseCcalls) |
505 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); | 515 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); |
506 | L->base = L->top - nresults; /* protect stack slots below */ | 516 | L->base = L->top - nresults; /* protect stack slots below */ |