** finish execution of an opcode interrupted by an yield */
| 421 | ** finish execution of an opcode interrupted by an yield |
| 422 | */ |
| 423 | void luaV_finishOp (lua_State *L) { |
| 424 | CallInfo *ci = L->ci; |
| 425 | StkId base = ci->u.l.base; |
| 426 | Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ |
| 427 | OpCode op = GET_OPCODE(inst); |
| 428 | switch (op) { /* finish its execution */ |
| 429 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: |
| 430 | case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: |
| 431 | case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { |
| 432 | setobjs2s(L, base + GETARG_A(inst), --L->top); |
| 433 | break; |
| 434 | } |
| 435 | case OP_LE: case OP_LT: case OP_EQ: { |
| 436 | int res = !l_isfalse(L->top - 1); |
| 437 | L->top--; |
| 438 | /* metamethod should not be called when operand is K */ |
| 439 | lua_assert(!ISK(GETARG_B(inst))); |
| 440 | if (op == OP_LE && /* "<=" using "<" instead? */ |
| 441 | ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) |
| 442 | res = !res; /* invert result */ |
| 443 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); |
| 444 | if (res != GETARG_A(inst)) /* condition failed? */ |
| 445 | ci->u.l.savedpc++; /* skip jump instruction */ |
| 446 | break; |
| 447 | } |
| 448 | case OP_CONCAT: { |
| 449 | StkId top = L->top - 1; /* top when 'call_binTM' was called */ |
| 450 | int b = GETARG_B(inst); /* first element to concatenate */ |
| 451 | int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ |
| 452 | setobj2s(L, top - 2, top); /* put TM result in proper position */ |
| 453 | if (total > 1) { /* are there elements to concat? */ |
| 454 | L->top = top - 1; /* top is one after last element (at top-2) */ |
| 455 | luaV_concat(L, total); /* concat them (may yield again) */ |
| 456 | } |
| 457 | /* move final result to final position */ |
| 458 | setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); |
| 459 | L->top = ci->top; /* restore top */ |
| 460 | break; |
| 461 | } |
| 462 | case OP_TFORCALL: { |
| 463 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); |
| 464 | L->top = ci->top; /* correct top */ |
| 465 | break; |
| 466 | } |
| 467 | case OP_CALL: { |
| 468 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ |
| 469 | L->top = ci->top; /* adjust results */ |
| 470 | break; |
| 471 | } |
| 472 | case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: |
| 473 | break; |
| 474 | default: lua_assert(0); |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | |
| 479 |
no test coverage detected