** finish execution of an opcode interrupted by an yield */
| 654 | ** finish execution of an opcode interrupted by an yield |
| 655 | */ |
| 656 | void luaV_finishOp (lua_State *L) { |
| 657 | CallInfo *ci = L->ci; |
| 658 | StkId base = ci->u.l.base; |
| 659 | Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ |
| 660 | OpCode op = GET_OPCODE(inst); |
| 661 | switch (op) { /* finish its execution */ |
| 662 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: |
| 663 | case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: |
| 664 | case OP_MOD: case OP_POW: |
| 665 | case OP_UNM: case OP_BNOT: case OP_LEN: |
| 666 | case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { |
| 667 | setobjs2s(L, base + GETARG_A(inst), --L->top); |
| 668 | break; |
| 669 | } |
| 670 | case OP_LE: case OP_LT: case OP_EQ: { |
| 671 | int res = !l_isfalse(L->top - 1); |
| 672 | L->top--; |
| 673 | if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ |
| 674 | lua_assert(op == OP_LE); |
| 675 | ci->callstatus ^= CIST_LEQ; /* clear mark */ |
| 676 | res = !res; /* negate result */ |
| 677 | } |
| 678 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); |
| 679 | if (res != GETARG_A(inst)) /* condition failed? */ |
| 680 | ci->u.l.savedpc++; /* skip jump instruction */ |
| 681 | break; |
| 682 | } |
| 683 | case OP_CONCAT: { |
| 684 | StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ |
| 685 | int b = GETARG_B(inst); /* first element to concatenate */ |
| 686 | int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ |
| 687 | setobj2s(L, top - 2, top); /* put TM result in proper position */ |
| 688 | if (total > 1) { /* are there elements to concat? */ |
| 689 | L->top = top - 1; /* top is one after last element (at top-2) */ |
| 690 | luaV_concat(L, total); /* concat them (may yield again) */ |
| 691 | } |
| 692 | /* move final result to final position */ |
| 693 | setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); |
| 694 | L->top = ci->top; /* restore top */ |
| 695 | break; |
| 696 | } |
| 697 | case OP_TFORCALL: { |
| 698 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); |
| 699 | L->top = ci->top; /* correct top */ |
| 700 | break; |
| 701 | } |
| 702 | case OP_CALL: { |
| 703 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ |
| 704 | L->top = ci->top; /* adjust results */ |
| 705 | break; |
| 706 | } |
| 707 | case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: |
| 708 | break; |
| 709 | default: lua_assert(0); |
| 710 | } |
| 711 | } |
| 712 | |
| 713 |