/* ** Executes the given Lua function. Parameters are between [base,top). ** Returns n such that the the results are between [n,top). */ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { const Proto *const tf = cl->f.l; StkId top; /* keep top local, for performance */ const Instruction *pc = tf->code; TString **const kstr = tf->kstr; const lua_Hook linehook = L->linehook; infovalue(base-1)->pc = &pc; luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK); if (tf->is_vararg) /* varargs? */ adjust_varargs(L, base, tf->numparams); else luaD_adjusttop(L, base, tf->numparams); top = L->top; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; if (linehook) traceexec(L, base, top, linehook); switch (GET_OPCODE(i)) { case OP_END: { L->top = top; return top; } case OP_RETURN: { L->top = top; return base+GETARG_U(i); } case OP_CALL: { int nres = GETARG_B(i); if (nres == MULT_RET) nres = LUA_MULTRET; L->top = top; luaD_call(L, base+GETARG_A(i), nres); top = L->top; break; } case OP_TAILCALL: { L->top = top; luaD_call(L, base+GETARG_A(i), LUA_MULTRET); return base+GETARG_B(i); } case OP_PUSHNIL: { int n = GETARG_U(i); LUA_ASSERT(n>0, "invalid argument"); do { ttype(top++) = LUA_TNIL; } while (--n > 0); break; } case OP_POP: { top -= GETARG_U(i); break; } case OP_PUSHINT: { ttype(top) = LUA_TNUMBER; nvalue(top) = (Number)GETARG_S(i); top++; break; } case OP_PUSHSTRING: { ttype(top) = LUA_TSTRING; tsvalue(top) = kstr[GETARG_U(i)]; top++; break; } case OP_PUSHNUM: { ttype(top) = LUA_TNUMBER; nvalue(top) = tf->knum[GETARG_U(i)]; top++; break; } case OP_PUSHNEGNUM: { ttype(top) = LUA_TNUMBER; nvalue(top) = -tf->knum[GETARG_U(i)]; top++; break; } case OP_PUSHUPVALUE: { *top++ = cl->upvalue[GETARG_U(i)]; break; } case OP_GETLOCAL: { *top++ = *(base+GETARG_U(i)); break; } case OP_GETGLOBAL: { L->top = top; *top = *luaV_getglobal(L, kstr[GETARG_U(i)]); top++; break; } case OP_GETTABLE: { L->top = top; top--; *(top-1) = *luaV_gettable(L, top-1); break; } case OP_GETDOTTED: { ttype(top) = LUA_TSTRING; tsvalue(top) = kstr[GETARG_U(i)]; L->top = top+1; *(top-1) = *luaV_gettable(L, top-1); break; } case OP_GETINDEXED: { *top = *(base+GETARG_U(i)); L->top = top+1; *(top-1) = *luaV_gettable(L, top-1); break; } case OP_PUSHSELF: { TObject receiver; receiver = *(top-1); ttype(top) = LUA_TSTRING; tsvalue(top++) = kstr[GETARG_U(i)]; L->top = top; *(top-2) = *luaV_gettable(L, top-2); *(top-1) = receiver; break; } case OP_CREATETABLE: { L->top = top; luaC_checkGC(L); hvalue(top) = luaH_new(L, GETARG_U(i)); ttype(top) = LUA_TTABLE; top++; break; } case OP_SETLOCAL: { *(base+GETARG_U(i)) = *(--top); break; } case OP_SETGLOBAL: { L->top = top; luaV_setglobal(L, kstr[GETARG_U(i)]); top--; break; } case OP_SETTABLE: { StkId t = top-GETARG_A(i); L->top = top; luaV_settable(L, t, t+1); top -= GETARG_B(i); /* pop values */ break; } case OP_SETLIST: { int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; int n = GETARG_B(i); Hash *arr = hvalue(top-n-1); L->top = top-n; /* final value of `top' (in case of errors) */ for (; n; n--) *luaH_setint(L, arr, n+aux) = *(--top); break; } case OP_SETMAP: { int n = GETARG_U(i); StkId finaltop = top-2*n; Hash *arr = hvalue(finaltop-1); L->top = finaltop; /* final value of `top' (in case of errors) */ for (; n; n--) { top-=2; *luaH_set(L, arr, top) = *(top+1); } break; } case OP_ADD: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_ADD); else nvalue(top-2) += nvalue(top-1); top--; break; } case OP_ADDI: { if (tonumber(top-1)) { ttype(top) = LUA_TNUMBER; nvalue(top) = (Number)GETARG_S(i); call_arith(L, top+1, TM_ADD); } else nvalue(top-1) += (Number)GETARG_S(i); break; } case OP_SUB: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_SUB); else nvalue(top-2) -= nvalue(top-1); top--; break; } case OP_MULT: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_MUL); else nvalue(top-2) *= nvalue(top-1); top--; break; } case OP_DIV: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_DIV); else nvalue(top-2) /= nvalue(top-1); top--; break; } case OP_POW: { if (!call_binTM(L, top, TM_POW)) lua_error(L, "undefined operation"); top--; break; } case OP_CONCAT: { int n = GETARG_U(i); luaV_strconc(L, n, top); top -= n-1; L->top = top; luaC_checkGC(L); break; } case OP_MINUS: { if (tonumber(top-1)) { ttype(top) = LUA_TNIL; call_arith(L, top+1, TM_UNM); } else nvalue(top-1) = -nvalue(top-1); break; } case OP_NOT: { ttype(top-1) = (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; nvalue(top-1) = 1; break; } case OP_JMPNE: { top -= 2; if (!luaO_equalObj(top, top+1)) dojump(pc, i); break; } case OP_JMPEQ: { top -= 2; if (luaO_equalObj(top, top+1)) dojump(pc, i); break; } case OP_JMPLT: { top -= 2; if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); break; } case OP_JMPLE: { /* a <= b === !(b<a) */ top -= 2; if (!luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); break; } case OP_JMPGT: { /* a > b === (b<a) */ top -= 2; if (luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); break; } case OP_JMPGE: { /* a >= b === !(a<b) */ top -= 2; if (!luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); break; } case OP_JMPT: { if (ttype(--top) != LUA_TNIL) dojump(pc, i); break; } case OP_JMPF: { if (ttype(--top) == LUA_TNIL) dojump(pc, i); break; } case OP_JMPONT: { if (ttype(top-1) == LUA_TNIL) top--; else dojump(pc, i); break; } case OP_JMPONF: { if (ttype(top-1) != LUA_TNIL) top--; else dojump(pc, i); break; } case OP_JMP: { dojump(pc, i); break; } case OP_PUSHNILJMP: { ttype(top++) = LUA_TNIL; pc++; break; } case OP_FORPREP: { if (tonumber(top-1)) lua_error(L, "`for' step must be a number"); if (tonumber(top-2)) lua_error(L, "`for' limit must be a number"); if (tonumber(top-3)) lua_error(L, "`for' initial value must be a number"); if (nvalue(top-1) > 0 ? nvalue(top-3) > nvalue(top-2) : nvalue(top-3) < nvalue(top-2)) { /* `empty' loop? */ top -= 3; /* remove control variables */ dojump(pc, i); /* jump to loop end */ } break; } case OP_FORLOOP: { LUA_ASSERT(ttype(top-1) == LUA_TNUMBER, "invalid step"); LUA_ASSERT(ttype(top-2) == LUA_TNUMBER, "invalid limit"); if (ttype(top-3) != LUA_TNUMBER) lua_error(L, "`for' index must be a number"); nvalue(top-3) += nvalue(top-1); /* increment index */ if (nvalue(top-1) > 0 ? nvalue(top-3) > nvalue(top-2) : nvalue(top-3) < nvalue(top-2)) top -= 3; /* end loop: remove control variables */ else dojump(pc, i); /* repeat loop */ break; } case OP_LFORPREP: { Node *node; if (ttype(top-1) != LUA_TTABLE) lua_error(L, "`for' table must be a table"); node = luaH_next(L, hvalue(top-1), &luaO_nilobject); if (node == NULL) { /* `empty' loop? */ top--; /* remove table */ dojump(pc, i); /* jump to loop end */ } else { top += 2; /* index,value */ *(top-2) = *key(node); *(top-1) = *val(node); } break; } case OP_LFORLOOP: { Node *node; LUA_ASSERT(ttype(top-3) == LUA_TTABLE, "invalid table"); node = luaH_next(L, hvalue(top-3), top-2); if (node == NULL) /* end loop? */ top -= 3; /* remove table, key, and value */ else { *(top-2) = *key(node); *(top-1) = *val(node); dojump(pc, i); /* repeat loop */ } break; } case OP_CLOSURE: { L->top = top; luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i)); top = L->top; luaC_checkGC(L); break; } } } }
LUA_API void lua_setglobal (lua_State *L, const char *name) { StkId top = L->top; luaV_setglobal(L, luaS_new(L, name)); L->top = top-1; /* remove element from the top */ }
/* ** Execute the given opcode, until a RET. Parameters are between ** [stack+base,top). Returns n such that the the results are between ** [stack+n,top). */ StkId luaV_execute (struct CallInfo *ci) { /* Save index in case CallInfo array is realloc'd */ int32 ci_index = ci - L->base_ci; struct Stack *S = &L->stack; /* to optimize */ Closure *cl; TProtoFunc *tf; StkId base; Byte *pc; TObject *consts; newfunc: cl = L->ci->c; tf = L->ci->tf; base = L->ci->base; if (S->top-S->stack > base && ttype(S->stack+base) == LUA_T_LINE) base++; pc = L->ci->pc; consts = tf->consts; while (1) { int32 aux; switch ((OpCode)(aux = *pc++)) { case PUSHNIL0: ttype(S->top++) = LUA_T_NIL; break; case PUSHNIL: aux = *pc++; do { ttype(S->top++) = LUA_T_NIL; } while (aux--); break; case PUSHNUMBER: aux = *pc++; goto pushnumber; case PUSHNUMBERW: aux = next_word(pc); goto pushnumber; case PUSHNUMBER0: case PUSHNUMBER1: case PUSHNUMBER2: aux -= PUSHNUMBER0; pushnumber: ttype(S->top) = LUA_T_NUMBER; nvalue(S->top) = (real)aux; S->top++; break; case PUSHLOCAL: aux = *pc++; goto pushlocal; case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7: aux -= PUSHLOCAL0; pushlocal: *S->top++ = *((S->stack+base) + aux); break; case GETGLOBALW: aux = next_word(pc); goto getglobal; case GETGLOBAL: aux = *pc++; goto getglobal; case GETGLOBAL0: case GETGLOBAL1: case GETGLOBAL2: case GETGLOBAL3: case GETGLOBAL4: case GETGLOBAL5: case GETGLOBAL6: case GETGLOBAL7: aux -= GETGLOBAL0; getglobal: luaV_getglobal(tsvalue(&consts[aux])); break; case GETTABLE: luaV_gettable(); break; case GETDOTTEDW: aux = next_word(pc); goto getdotted; case GETDOTTED: aux = *pc++; goto getdotted; case GETDOTTED0: case GETDOTTED1: case GETDOTTED2: case GETDOTTED3: case GETDOTTED4: case GETDOTTED5: case GETDOTTED6: case GETDOTTED7: aux -= GETDOTTED0; getdotted: *S->top++ = consts[aux]; luaV_gettable(); break; case PUSHSELFW: aux = next_word(pc); goto pushself; case PUSHSELF: aux = *pc++; goto pushself; case PUSHSELF0: case PUSHSELF1: case PUSHSELF2: case PUSHSELF3: case PUSHSELF4: case PUSHSELF5: case PUSHSELF6: case PUSHSELF7: aux -= PUSHSELF0; pushself: { TObject receiver = *(S->top-1); *S->top++ = consts[aux]; luaV_gettable(); *S->top++ = receiver; break; } case PUSHCONSTANTW: aux = next_word(pc); goto pushconstant; case PUSHCONSTANT: aux = *pc++; goto pushconstant; case PUSHCONSTANT0: case PUSHCONSTANT1: case PUSHCONSTANT2: case PUSHCONSTANT3: case PUSHCONSTANT4: case PUSHCONSTANT5: case PUSHCONSTANT6: case PUSHCONSTANT7: aux -= PUSHCONSTANT0; pushconstant: *S->top++ = consts[aux]; break; case PUSHUPVALUE: aux = *pc++; goto pushupvalue; case PUSHUPVALUE0: case PUSHUPVALUE1: aux -= PUSHUPVALUE0; pushupvalue: *S->top++ = cl->consts[aux+1]; break; case SETLOCAL: aux = *pc++; goto setlocal; case SETLOCAL0: case SETLOCAL1: case SETLOCAL2: case SETLOCAL3: case SETLOCAL4: case SETLOCAL5: case SETLOCAL6: case SETLOCAL7: aux -= SETLOCAL0; setlocal: *((S->stack+base) + aux) = *(--S->top); break; case SETGLOBALW: aux = next_word(pc); goto setglobal; case SETGLOBAL: aux = *pc++; goto setglobal; case SETGLOBAL0: case SETGLOBAL1: case SETGLOBAL2: case SETGLOBAL3: case SETGLOBAL4: case SETGLOBAL5: case SETGLOBAL6: case SETGLOBAL7: aux -= SETGLOBAL0; setglobal: luaV_setglobal(tsvalue(&consts[aux])); break; case SETTABLE0: luaV_settable(S->top-3, 1); break; case SETTABLE: luaV_settable(S->top-3-(*pc++), 2); break; case SETLISTW: aux = next_word(pc); aux *= LFIELDS_PER_FLUSH; goto setlist; case SETLIST: aux = *(pc++) * LFIELDS_PER_FLUSH; goto setlist; case SETLIST0: aux = 0; setlist: { int32 n = *(pc++); TObject *arr = S->top-n-1; for (; n; n--) { ttype(S->top) = LUA_T_NUMBER; nvalue(S->top) = (real)(n+aux); *(luaH_set(avalue(arr), S->top)) = *(S->top-1); S->top--; } break; } case SETMAP0: aux = 0; goto setmap; case SETMAP: aux = *pc++; setmap: { TObject *arr = S->top-(2*aux)-3; do { *(luaH_set(avalue(arr), S->top-2)) = *(S->top-1); S->top-=2; } while (aux--); break; } case POP: aux = *pc++; goto pop; case POP0: case POP1: aux -= POP0; pop: S->top -= (aux+1); break; case CREATEARRAYW: aux = next_word(pc); goto createarray; case CREATEARRAY0: case CREATEARRAY1: aux -= CREATEARRAY0; goto createarray; case CREATEARRAY: aux = *pc++; createarray: luaC_checkGC(); avalue(S->top) = luaH_new(aux); ttype(S->top) = LUA_T_ARRAY; S->top++; break; case EQOP: case NEQOP: { int32 res = luaO_equalObj(S->top-2, S->top-1); S->top--; if (aux == NEQOP) res = !res; ttype(S->top-1) = res ? LUA_T_NUMBER : LUA_T_NIL; nvalue(S->top-1) = 1; break; } case LTOP: comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT); break; case LEOP: comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE); break; case GTOP: comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT); break; case GEOP: comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE); break; case ADDOP: { TObject *l = S->top-2; TObject *r = S->top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_ADD); else { nvalue(l) += nvalue(r); --S->top; } break; } case SUBOP: { TObject *l = S->top-2; TObject *r = S->top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_SUB); else { nvalue(l) -= nvalue(r); --S->top; } break; } case MULTOP: { TObject *l = S->top-2; TObject *r = S->top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_MUL); else { nvalue(l) *= nvalue(r); --S->top; } break; } case DIVOP: { TObject *l = S->top-2; TObject *r = S->top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_DIV); else { nvalue(l) /= nvalue(r); --S->top; } break; } case POWOP: call_binTM(IM_POW, "undefined operation"); break; case CONCOP: { TObject *l = S->top-2; TObject *r = S->top-1; if (tostring(l) || tostring(r)) call_binTM(IM_CONCAT, "unexpected type for concatenation"); else { tsvalue(l) = strconc(tsvalue(l), tsvalue(r)); --S->top; } luaC_checkGC(); break; } case MINUSOP: if (tonumber(S->top-1)) { ttype(S->top) = LUA_T_NIL; S->top++; call_arith(IM_UNM); } else nvalue(S->top-1) = - nvalue(S->top-1); break; case NOTOP: ttype(S->top-1) = (ttype(S->top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; nvalue(S->top-1) = 1; break; case ONTJMPW: aux = next_word(pc); goto ontjmp; case ONTJMP: aux = *pc++; ontjmp: if (ttype(S->top-1) != LUA_T_NIL) pc += aux; else S->top--; break; case ONFJMPW: aux = next_word(pc); goto onfjmp; case ONFJMP: aux = *pc++; onfjmp: if (ttype(S->top-1) == LUA_T_NIL) pc += aux; else S->top--; break; case JMPW: aux = next_word(pc); goto jmp; case JMP: aux = *pc++; jmp: pc += aux; break; case IFFJMPW: aux = next_word(pc); goto iffjmp; case IFFJMP: aux = *pc++; iffjmp: if (ttype(--S->top) == LUA_T_NIL) pc += aux; break; case IFTUPJMPW: aux = next_word(pc); goto iftupjmp; case IFTUPJMP: aux = *pc++; iftupjmp: if (ttype(--S->top) != LUA_T_NIL) pc -= aux; break; case IFFUPJMPW: aux = next_word(pc); goto iffupjmp; case IFFUPJMP: aux = *pc++; iffupjmp: if (ttype(--S->top) == LUA_T_NIL) pc -= aux; break; case CLOSURE: aux = *pc++; goto closure; case CLOSURE0: aux = 0; goto closure; case CLOSURE1: aux = 1; closure: luaV_closure(aux); luaC_checkGC(); break; case CALLFUNC: aux = *pc++; goto callfunc; case CALLFUNC0: case CALLFUNC1: aux -= CALLFUNC0; callfunc: { StkId newBase = (S->top-S->stack)-(*pc++); TObject *func = S->stack+newBase-1; L->ci->pc = pc; if (ttype(func) == LUA_T_PROTO || (ttype(func) == LUA_T_CLOSURE && ttype(&clvalue(func)->consts[0]) == LUA_T_PROTO)) { /* Calling another Lua function */ luaD_precall(func, newBase, aux); ttype(func) = (ttype(func) == LUA_T_PROTO) ? LUA_T_PMARK : LUA_T_CLMARK; goto newfunc; } luaD_call(newBase, aux); if (L->Tstate != RUN) { if (ci_index > 1) /* C functions detected by break_here */ lua_error("Cannot yield through method call"); return -1; } break; } case ENDCODE: S->top = S->stack + base; /* goes through */ case RETCODE: { StkId firstResult = (base + ((aux==RETCODE) ? *pc : 0)); if (lua_callhook) luaD_callHook(base, NULL, 1); /* If returning from the original stack frame, terminate */ if (L->ci == L->base_ci + ci_index) return firstResult; luaD_postret(firstResult); goto newfunc; } case SETLINEW: aux = next_word(pc); goto setline; case SETLINE: aux = *pc++; setline: if ((S->stack+base-1)->ttype != LUA_T_LINE) { /* open space for LINE value */ luaD_openstack((S->top-S->stack)-base); base++; (S->stack+base-1)->ttype = LUA_T_LINE; } (S->stack+base-1)->value.i = aux; if (lua_linehook) luaD_lineHook(aux); break; #ifdef DEBUG default: LUA_INTERNALERROR("opcode doesn't match"); #endif } } }
void lua_setglobal (char *name) { checkCparams(1); luaD_checkstack(2); /* may need that to call T.M. */ luaV_setglobal(luaS_new(name)); }
StkId luaV_execute(lua_Task *task) { if (!task->some_flag) { luaD_checkstack((*task->pc++) + EXTRA_STACK); if (*task->pc < ZEROVARARG) { luaD_adjusttop(task->base + *(task->pc++)); } else { luaC_checkGC(); adjust_varargs(task->base + (*task->pc++) - ZEROVARARG); } task->some_flag = 1; } lua_state->state_counter2++; while (1) { switch ((OpCode)(task->aux = *task->pc++)) { case PUSHNIL0: ttype(task->S->top++) = LUA_T_NIL; break; case PUSHNIL: task->aux = *task->pc++; do { ttype(task->S->top++) = LUA_T_NIL; } while (task->aux--); break; case PUSHNUMBER: task->aux = *task->pc++; goto pushnumber; case PUSHNUMBERW: task->aux = next_word(task->pc); goto pushnumber; case PUSHNUMBER0: case PUSHNUMBER1: case PUSHNUMBER2: task->aux -= PUSHNUMBER0; pushnumber: ttype(task->S->top) = LUA_T_NUMBER; nvalue(task->S->top) = (float)task->aux; task->S->top++; break; case PUSHLOCAL: task->aux = *task->pc++; goto pushlocal; case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7: task->aux -= PUSHLOCAL0; pushlocal: *task->S->top++ = *((task->S->stack + task->base) + task->aux); break; case GETGLOBALW: task->aux = next_word(task->pc); goto getglobal; case GETGLOBAL: task->aux = *task->pc++; goto getglobal; case GETGLOBAL0: case GETGLOBAL1: case GETGLOBAL2: case GETGLOBAL3: case GETGLOBAL4: case GETGLOBAL5: case GETGLOBAL6: case GETGLOBAL7: task->aux -= GETGLOBAL0; getglobal: luaV_getglobal(tsvalue(&task->consts[task->aux])); break; case GETTABLE: luaV_gettable(); break; case GETDOTTEDW: task->aux = next_word(task->pc); goto getdotted; case GETDOTTED: task->aux = *task->pc++; goto getdotted; case GETDOTTED0: case GETDOTTED1: case GETDOTTED2: case GETDOTTED3: case GETDOTTED4: case GETDOTTED5: case GETDOTTED6: case GETDOTTED7: task->aux -= GETDOTTED0; getdotted: *task->S->top++ = task->consts[task->aux]; luaV_gettable(); break; case PUSHSELFW: task->aux = next_word(task->pc); goto pushself; case PUSHSELF: task->aux = *task->pc++; goto pushself; case PUSHSELF0: case PUSHSELF1: case PUSHSELF2: case PUSHSELF3: case PUSHSELF4: case PUSHSELF5: case PUSHSELF6: case PUSHSELF7: task->aux -= PUSHSELF0; pushself: { TObject receiver = *(task->S->top - 1); *task->S->top++ = task->consts[task->aux]; luaV_gettable(); *task->S->top++ = receiver; break; } case PUSHCONSTANTW: task->aux = next_word(task->pc); goto pushconstant; case PUSHCONSTANT: task->aux = *task->pc++; goto pushconstant; case PUSHCONSTANT0: case PUSHCONSTANT1: case PUSHCONSTANT2: case PUSHCONSTANT3: case PUSHCONSTANT4: case PUSHCONSTANT5: case PUSHCONSTANT6: case PUSHCONSTANT7: task->aux -= PUSHCONSTANT0; pushconstant: *task->S->top++ = task->consts[task->aux]; break; case PUSHUPVALUE: task->aux = *task->pc++; goto pushupvalue; case PUSHUPVALUE0: case PUSHUPVALUE1: task->aux -= PUSHUPVALUE0; pushupvalue: *task->S->top++ = task->cl->consts[task->aux + 1]; break; case SETLOCAL: task->aux = *task->pc++; goto setlocal; case SETLOCAL0: case SETLOCAL1: case SETLOCAL2: case SETLOCAL3: case SETLOCAL4: case SETLOCAL5: case SETLOCAL6: case SETLOCAL7: task->aux -= SETLOCAL0; setlocal: *((task->S->stack + task->base) + task->aux) = *(--task->S->top); break; case SETGLOBALW: task->aux = next_word(task->pc); goto setglobal; case SETGLOBAL: task->aux = *task->pc++; goto setglobal; case SETGLOBAL0: case SETGLOBAL1: case SETGLOBAL2: case SETGLOBAL3: case SETGLOBAL4: case SETGLOBAL5: case SETGLOBAL6: case SETGLOBAL7: task->aux -= SETGLOBAL0; setglobal: luaV_setglobal(tsvalue(&task->consts[task->aux])); break; case SETTABLE0: luaV_settable(task->S->top - 3, 1); break; case SETTABLE: luaV_settable(task->S->top - 3 - (*task->pc++), 2); break; case SETLISTW: task->aux = next_word(task->pc); task->aux *= LFIELDS_PER_FLUSH; goto setlist; case SETLIST: task->aux = *(task->pc++) * LFIELDS_PER_FLUSH; goto setlist; case SETLIST0: task->aux = 0; setlist: { int32 n = *(task->pc++); TObject *arr = task->S->top - n - 1; for (; n; n--) { ttype(task->S->top) = LUA_T_NUMBER; nvalue(task->S->top) = (float)(n + task->aux); *(luaH_set(avalue(arr), task->S->top)) = *(task->S->top - 1); task->S->top--; } break; } case SETMAP0: task->aux = 0; goto setmap; case SETMAP: task->aux = *task->pc++; setmap: { TObject *arr = task->S->top - (2 * task->aux) - 3; do { *(luaH_set(avalue(arr), task->S->top - 2)) = *(task->S->top - 1); task->S->top -= 2; } while (task->aux--); break; } case POP: task->aux = *task->pc++; goto pop; case POP0: case POP1: task->aux -= POP0; pop: task->S->top -= (task->aux + 1); break; case CREATEARRAYW: task->aux = next_word(task->pc); goto createarray; case CREATEARRAY0: case CREATEARRAY1: task->aux -= CREATEARRAY0; goto createarray; case CREATEARRAY: task->aux = *task->pc++; createarray: luaC_checkGC(); avalue(task->S->top) = luaH_new(task->aux); ttype(task->S->top) = LUA_T_ARRAY; task->S->top++; break; case EQOP: case NEQOP: { int32 res = luaO_equalObj(task->S->top - 2, task->S->top - 1); task->S->top--; if (task->aux == NEQOP) res = !res; ttype(task->S->top - 1) = res ? LUA_T_NUMBER : LUA_T_NIL; nvalue(task->S->top - 1) = 1; break; } case LTOP: comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT); break; case LEOP: comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE); break; case GTOP: comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT); break; case GEOP: comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE); break; case ADDOP: { TObject *l = task->S->top - 2; TObject *r = task->S->top - 1; if (tonumber(r) || tonumber(l)) call_arith(IM_ADD); else { nvalue(l) += nvalue(r); --task->S->top; } break; } case SUBOP: { TObject *l = task->S->top - 2; TObject *r = task->S->top - 1; if (tonumber(r) || tonumber(l)) call_arith(IM_SUB); else { nvalue(l) -= nvalue(r); --task->S->top; } break; } case MULTOP: { TObject *l = task->S->top - 2; TObject *r = task->S->top - 1; if (tonumber(r) || tonumber(l)) call_arith(IM_MUL); else { nvalue(l) *= nvalue(r); --task->S->top; } break; } case DIVOP: { TObject *l = task->S->top - 2; TObject *r = task->S->top - 1; if (tonumber(r) || tonumber(l)) call_arith(IM_DIV); else { nvalue(l) /= nvalue(r); --task->S->top; } break; } case POWOP: call_arith(IM_POW); break; case CONCOP: { TObject *l = task->S->top - 2; TObject *r = task->S->top - 1; if (tostring(l) || tostring(r)) call_binTM(IM_CONCAT, "unexpected type for concatenation"); else { tsvalue(l) = strconc(svalue(l), svalue(r)); --task->S->top; } luaC_checkGC(); break; } case MINUSOP: if (tonumber(task->S->top - 1)) { ttype(task->S->top) = LUA_T_NIL; task->S->top++; call_arith(IM_UNM); } else nvalue(task->S->top - 1) = -nvalue(task->S->top - 1); break; case NOTOP: ttype(task->S->top - 1) = (ttype(task->S->top - 1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; nvalue(task->S->top - 1) = 1; break; case ONTJMPW: task->aux = next_word(task->pc); goto ontjmp; case ONTJMP: task->aux = *task->pc++; ontjmp: if (ttype(task->S->top - 1) != LUA_T_NIL) task->pc += task->aux; else task->S->top--; break; case ONFJMPW: task->aux = next_word(task->pc); goto onfjmp; case ONFJMP: task->aux = *task->pc++; onfjmp: if (ttype(task->S->top - 1) == LUA_T_NIL) task->pc += task->aux; else task->S->top--; break; case JMPW: task->aux = next_word(task->pc); goto jmp; case JMP: task->aux = *task->pc++; jmp: task->pc += task->aux; break; case IFFJMPW: task->aux = next_word(task->pc); goto iffjmp; case IFFJMP: task->aux = *task->pc++; iffjmp: if (ttype(--task->S->top) == LUA_T_NIL) task->pc += task->aux; break; case IFTUPJMPW: task->aux = next_word(task->pc); goto iftupjmp; case IFTUPJMP: task->aux = *task->pc++; iftupjmp: if (ttype(--task->S->top) != LUA_T_NIL) task->pc -= task->aux; break; case IFFUPJMPW: task->aux = next_word(task->pc); goto iffupjmp; case IFFUPJMP: task->aux = *task->pc++; iffupjmp: if (ttype(--task->S->top) == LUA_T_NIL) task->pc -= task->aux; break; case CLOSURE: task->aux = *task->pc++; goto closure; case CLOSURE0: case CLOSURE1: task->aux -= CLOSURE0; closure: luaV_closure(task->aux); luaC_checkGC(); break; case CALLFUNC: task->aux = *task->pc++; goto callfunc; case CALLFUNC0: case CALLFUNC1: task->aux -= CALLFUNC0; callfunc: lua_state->state_counter2--; return -((task->S->top - task->S->stack) - (*task->pc++)); case ENDCODE: task->S->top = task->S->stack + task->base; // goes through case RETCODE: lua_state->state_counter2--; return (task->base + ((task->aux == 123) ? *task->pc : 0)); case SETLINEW: task->aux = next_word(task->pc); goto setline; case SETLINE: task->aux = *task->pc++; setline: if ((task->S->stack + task->base - 1)->ttype != LUA_T_LINE) { // open space for LINE value */ luaD_openstack((task->S->top - task->S->stack) - task->base); task->base++; (task->S->stack + task->base - 1)->ttype = LUA_T_LINE; } (task->S->stack + task->base - 1)->value.i = task->aux; if (lua_linehook) luaD_lineHook(task->aux); break; #ifdef LUA_DEBUG default: LUA_INTERNALERROR("internal error - opcode doesn't match"); #endif } } }