** finish execution of an opcode interrupted by an yield */
| 482 | ** finish execution of an opcode interrupted by an yield |
| 483 | */ |
| 484 | void luaV_finishOp (lua_State *L) { |
| 485 | CallInfo *ci = L->ci; |
| 486 | StkId base = ci->u.l.base; |
| 487 | Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ |
| 488 | OpCode op = GET_OPCODE(inst); |
| 489 | switch (op) { /* finish its execution */ |
| 490 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: |
| 491 | case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: |
| 492 | case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { |
| 493 | setobjs2s(L, base + GETARG_A(inst), --L->top); |
| 494 | break; |
| 495 | } |
| 496 | case OP_LE: case OP_LT: case OP_EQ: { |
| 497 | int res = !l_isfalse(L->top - 1); |
| 498 | L->top--; |
| 499 | /* metamethod should not be called when operand is K */ |
| 500 | lua_assert(!ISK(GETARG_B(inst))); |
| 501 | if (op == OP_LE && /* "<=" using "<" instead? */ |
| 502 | ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) |
| 503 | res = !res; /* invert result */ |
| 504 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); |
| 505 | if (res != GETARG_A(inst)) /* condition failed? */ |
| 506 | ci->u.l.savedpc++; /* skip jump instruction */ |
| 507 | break; |
| 508 | } |
| 509 | case OP_CONCAT: { |
| 510 | StkId top = L->top - 1; /* top when 'call_binTM' was called */ |
| 511 | int b = GETARG_B(inst); /* first element to concatenate */ |
| 512 | int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ |
| 513 | setobj2s(L, top - 2, top); /* put TM result in proper position */ |
| 514 | if (total > 1) { /* are there elements to concat? */ |
| 515 | L->top = top - 1; /* top is one after last element (at top-2) */ |
| 516 | luaV_concat(L, total); /* concat them (may yield again) */ |
| 517 | } |
| 518 | /* move final result to final position */ |
| 519 | setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); |
| 520 | L->top = ci->top; /* restore top */ |
| 521 | break; |
| 522 | } |
| 523 | case OP_TFORCALL: { |
| 524 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); |
| 525 | L->top = ci->top; /* correct top */ |
| 526 | break; |
| 527 | } |
| 528 | case OP_CALL: { |
| 529 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ |
| 530 | L->top = ci->top; /* adjust results */ |
| 531 | break; |
| 532 | } |
| 533 | case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: |
| 534 | break; |
| 535 | default: lua_assert(0); |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | |
| 540 |
no test coverage detected