static void adjust_varargs (StkId first_extra_arg) { Object arg; Object *firstelem = stack+first_extra_arg; int nvararg = top-firstelem; int i; if (nvararg < 0) nvararg = 0; avalue(&arg) = lua_createarray(nvararg+1); /* +1 for field 'n' */ tag(&arg) = LUA_T_ARRAY; for (i=0; i<nvararg; i++) { Object index; tag(&index) = LUA_T_NUMBER; nvalue(&index) = i+1; *(lua_hashdefine(avalue(&arg), &index)) = *(firstelem+i); } /* store counter in field "n" */ { Object index, extra; tag(&index) = LUA_T_STRING; tsvalue(&index) = lua_createstring("n"); tag(&extra) = LUA_T_NUMBER; nvalue(&extra) = nvararg; *(lua_hashdefine(avalue(&arg), &index)) = extra; } adjust_top(first_extra_arg); *top = arg; incr_top; }
TaggedString *luaI_createfixedstring (char *name) { TaggedString *ts = lua_createstring(name); if (!ts->marked) ts->marked = 2; /* avoid GC */ return ts; }
/* ** Push an object (tag=string) to stack. */ void lua_pushstring (char *s) { if (s == NULL) tag(top) = LUA_T_NIL; else { tsvalue(top) = lua_createstring(s); tag(top) = LUA_T_STRING; } incr_top; }
/* ** Convert, if possible, to a string tag ** Return 0 in success or not 0 on error. */ static int lua_tostring (Object *obj) { char s[256]; if (tag(obj) != LUA_T_NUMBER) return 1; if ((int) nvalue(obj) == nvalue(obj)) sprintf (s, "%d", (int) nvalue(obj)); else sprintf (s, "%g", nvalue(obj)); tsvalue(obj) = lua_createstring(s); tag(obj) = LUA_T_STRING; return 0; }
/* ** Convert, if possible, to a string ttype ** Return 0 in success or not 0 on error. */ static int lua_tostring (TObject *obj) { if (ttype(obj) != LUA_T_NUMBER) return 1; else { char s[60]; real f = nvalue(obj); int i; if ((real)(-MAX_INT) <= f && f <= (real)MAX_INT && (real)(i=(int)f) == f) sprintf (s, "%d", i); else sprintf (s, "%g", nvalue(obj)); tsvalue(obj) = lua_createstring(s); ttype(obj) = LUA_T_STRING; return 0; } }
/* ** 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). */ static StkId lua_execute (Byte *pc, StkId base) { void* table[] = { &&pushnil, &&push0, &&push1, &&push2, &&pushbyte, &&pushword, &&pushfloat, &&pushstring, &&pushfunction, &&pushlocal0, &&pushlocal1, &&pushlocal2, &&pushlocal3, &&pushlocal4, &&pushlocal5, &&pushlocal6, &&pushlocal7, &&pushlocal8, &&pushlocal9, &&pushlocal, &&pushglobal, &&pushindexed, &&pushself, &&storelocal0, &&storelocal1, &&storelocal2, &&storelocal3, &&storelocal4, &&storelocal5, &&storelocal6, &&storelocal7, &&storelocal8, &&storelocal9, &&storelocal, &&storeglobal, &&storeindexed0, &&storeindexed, &&storelist0, &&storelist, &&storerecord, &&adjust0, &&adjust, &&createarray, &&eqop, &<op, &&leop, &>op, &&geop, &&addop, &&subop, &&multop, &&divop, &&powop, &&concop, &&minusop, &¬op, &&ontjmp, &&onfjmp, &&jmp, &&upjmp, &&iffjmp, &&iffupjmp, &&pop, &&callfunc, &&retcode0, &&retcode, &&setline, &&varargs }; if (lua_callhook) callHook (base, LUA_T_MARK, 0); goto *table[*pc++]; pushnil: tag(top) = LUA_T_NIL; incr_top; goto *table[*pc++]; push0: push1: push2: tag(top) = LUA_T_NUMBER; nvalue(top) = ((OpCode)*(pc-1))-PUSH0; incr_top; goto *table[*pc++]; pushbyte: tag(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; goto *table[*pc++]; pushword: { Word w; get_word(w,pc); tag(top) = LUA_T_NUMBER; nvalue(top) = w; incr_top; } goto *table[*pc++]; pushfloat: { real num; get_float(num,pc); tag(top) = LUA_T_NUMBER; nvalue(top) = num; incr_top; } goto *table[*pc++]; pushstring: { Word w; get_word(w,pc); tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; incr_top; } goto *table[*pc++]; pushfunction: { TFunc *f; get_code(f,pc); luaI_insertfunction(f); /* may take part in GC */ top->tag = LUA_T_FUNCTION; top->value.tf = f; incr_top; } goto *table[*pc++]; pushlocal0: pushlocal1: pushlocal2: pushlocal3: pushlocal4: pushlocal5: pushlocal6: pushlocal7: pushlocal8: pushlocal9: *top = *((stack+base) + (int)(((OpCode)*(pc-1))-PUSHLOCAL0)); incr_top; goto *table[*pc++]; pushlocal: *top = *((stack+base) + (*pc++)); incr_top; goto *table[*pc++]; pushglobal: { Word w; get_word(w,pc); getglobal(w); } goto *table[*pc++]; pushindexed: pushsubscript(); goto *table[*pc++]; pushself: { Object receiver = *(top-1); Word w; get_word(w,pc); tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; incr_top; pushsubscript(); *top = receiver; incr_top; goto *table[*pc++]; } storelocal0: storelocal1: storelocal2: storelocal3: storelocal4: storelocal5: storelocal6: storelocal7: storelocal8: storelocal9: *((stack+base) + (int)(((OpCode)*(pc-1))-STORELOCAL0)) = *(--top); goto *table[*pc++]; storelocal: *((stack+base) + (*pc++)) = *(--top); goto *table[*pc++]; storeglobal: { Word w; get_word(w,pc); s_object(w) = *(--top); } goto *table[*pc++]; storeindexed0: storesubscript(); goto *table[*pc++]; storeindexed: { int n = *pc++; if (tag(top-3-n) != LUA_T_ARRAY) { lua_checkstack(top+2); *(top+1) = *(top-1); *(top) = *(top-2-n); *(top-1) = *(top-3-n); top += 2; callFB(FB_SETTABLE); } else { Object *h = lua_hashdefine (avalue(top-3-n), top-2-n); *h = *(top-1); top--; } } goto *table[*pc++]; storelist0: storelist: { int m, n; Object *arr; if (((OpCode)*(pc-1)) == STORELIST0) m = 0; else m = *(pc++) * FIELDS_PER_FLUSH; n = *(pc++); arr = top-n-1; while (n) { tag(top) = LUA_T_NUMBER; nvalue(top) = n+m; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; } } goto *table[*pc++]; storerecord: { int n = *(pc++); Object *arr = top-n-1; while (n) { Word w; get_word(w,pc); tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; } } goto *table[*pc++]; adjust0: adjust_top(base); goto *table[*pc++]; adjust: adjust_top(base + *(pc++)); goto *table[*pc++]; varargs: adjust_varargs(base + *(pc++)); goto *table[*pc++]; createarray: { Word size; get_word(size,pc); avalue(top) = lua_createarray(size); tag(top) = LUA_T_ARRAY; incr_top; } goto *table[*pc++]; eqop: { int res = lua_equalObj(top-2, top-1); --top; tag(top-1) = res ? LUA_T_NUMBER : LUA_T_NIL; nvalue(top-1) = 1; } goto *table[*pc++]; ltop: comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, "lt"); goto *table[*pc++]; leop: comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, "le"); goto *table[*pc++]; gtop: comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, "gt"); goto *table[*pc++]; geop: comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, "ge"); goto *table[*pc++]; addop: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) call_arith("add"); else { nvalue(l) += nvalue(r); --top; } } goto *table[*pc++]; subop: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) call_arith("sub"); else { nvalue(l) -= nvalue(r); --top; } } goto *table[*pc++]; multop: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) call_arith("mul"); else { nvalue(l) *= nvalue(r); --top; } } goto *table[*pc++]; divop: { Object *l = top-2; Object *r = top-1; if (tonumber(r) || tonumber(l)) call_arith("div"); else { nvalue(l) /= nvalue(r); --top; } } goto *table[*pc++]; powop: call_arith("pow"); goto *table[*pc++]; concop: { Object *l = top-2; Object *r = top-1; if (tostring(r) || tostring(l)) callFB(FB_CONCAT); else { tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); --top; } } goto *table[*pc++]; minusop: if (tonumber(top-1)) { tag(top) = LUA_T_NIL; incr_top; call_arith("unm"); } else nvalue(top-1) = - nvalue(top-1); goto *table[*pc++]; notop: tag(top-1) = (tag(top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; nvalue(top-1) = 1; goto *table[*pc++]; ontjmp: { Word w; get_word(w,pc); if (tag(top-1) != LUA_T_NIL) pc += w; } goto *table[*pc++]; onfjmp: { Word w; get_word(w,pc); if (tag(top-1) == LUA_T_NIL) pc += w; } goto *table[*pc++]; jmp: { Word w; get_word(w,pc); pc += w; } goto *table[*pc++]; upjmp: { Word w; get_word(w,pc); pc -= w; } goto *table[*pc++]; iffjmp: { Word w; get_word(w,pc); top--; if (tag(top) == LUA_T_NIL) pc += w; } goto *table[*pc++]; iffupjmp: { Word w; get_word(w,pc); top--; if (tag(top) == LUA_T_NIL) pc -= w; } goto *table[*pc++]; pop: --top; goto *table[*pc++]; callfunc: { int nParams = *(pc++); int nResults = *(pc++); StkId newBase = (top-stack)-nParams; do_call(newBase, nResults); } goto *table[*pc++]; retcode0: retcode: if (lua_callhook) callHook (base, LUA_T_MARK, 1); return (base + ((((OpCode)*(pc-1))==RETCODE0) ? 0 : *pc)); setline: { Word line; get_word(line,pc); if ((stack+base-1)->tag != LUA_T_LINE) { /* open space for LINE value */ open_stack((top-stack)-base); base++; (stack+base-1)->tag = LUA_T_LINE; } (stack+base-1)->value.i = line; if (lua_linehook) lineHook (line); goto *table[*pc++]; } lua_error ("internal error - opcode doesn't match"); }
/* ** 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). */ static StkId lua_execute (Byte *pc, StkId base) { if (lua_callhook) callHook (base, LUA_T_MARK, 0); while (1) { OpCode opcode; switch (opcode = (OpCode)*pc++) { case PUSHNIL: ttype(top) = LUA_T_NIL; incr_top; break; case PUSH0: case PUSH1: case PUSH2: ttype(top) = LUA_T_NUMBER; nvalue(top) = opcode-PUSH0; incr_top; break; case PUSHBYTE: ttype(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; break; case PUSHWORD: { Word w; get_word(w,pc); ttype(top) = LUA_T_NUMBER; nvalue(top) = w; incr_top; } break; case PUSHFLOAT: { real num; get_float(num,pc); ttype(top) = LUA_T_NUMBER; nvalue(top) = num; incr_top; } break; case PUSHSTRING: { Word w; get_word(w,pc); ttype(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; incr_top; } break; case PUSHFUNCTION: { TFunc *f; get_code(f,pc); luaI_insertfunction(f); /* may take part in GC */ top->ttype = LUA_T_FUNCTION; top->value.tf = f; incr_top; } break; case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8: case PUSHLOCAL9: *top = *((stack+base) + (int)(opcode-PUSHLOCAL0)); incr_top; break; case PUSHLOCAL: *top = *((stack+base) + (*pc++)); incr_top; break; case PUSHGLOBAL: { Word w; get_word(w,pc); getglobal(w); } break; case PUSHINDEXED: pushsubscript(); break; case PUSHSELF: { TObject receiver = *(top-1); Word w; get_word(w,pc); ttype(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; incr_top; pushsubscript(); *top = receiver; incr_top; break; } case STORELOCAL0: case STORELOCAL1: case STORELOCAL2: case STORELOCAL3: case STORELOCAL4: case STORELOCAL5: case STORELOCAL6: case STORELOCAL7: case STORELOCAL8: case STORELOCAL9: *((stack+base) + (int)(opcode-STORELOCAL0)) = *(--top); break; case STORELOCAL: *((stack+base) + (*pc++)) = *(--top); break; case STOREGLOBAL: { Word w; get_word(w,pc); setglobal(w); } break; case STOREINDEXED0: storesubscript(top-3, 1); break; case STOREINDEXED: { int n = *pc++; storesubscript(top-3-n, 2); break; } case STORELIST0: case STORELIST: { int m, n; TObject *arr; if (opcode == STORELIST0) m = 0; else m = *(pc++) * FIELDS_PER_FLUSH; n = *(pc++); arr = top-n-1; while (n) { ttype(top) = LUA_T_NUMBER; nvalue(top) = n+m; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; } } break; case STORERECORD: /* opcode obsolete: supersed by STOREMAP */ { int n = *(pc++); TObject *arr = top-n-1; while (n) { Word w; get_word(w,pc); ttype(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; } } break; case STOREMAP: { int n = *(pc++); TObject *arr = top-(2*n)-1; while (n--) { *(lua_hashdefine (avalue(arr), top-2)) = *(top-1); top-=2; } } break; case ADJUST0: adjust_top(base); break; case ADJUST: { StkId newtop = base + *(pc++); adjust_top(newtop); break; } case VARARGS: adjust_varargs(base + *(pc++)); break; case CREATEARRAY: { Word size; get_word(size,pc); avalue(top) = lua_createarray(size); ttype(top) = LUA_T_ARRAY; incr_top; } break; case EQOP: { int res = lua_equalObj(top-2, top-1); --top; ttype(top-1) = res ? LUA_T_NUMBER : LUA_T_NIL; nvalue(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 = top-2; TObject *r = top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_ADD); else { nvalue(l) += nvalue(r); --top; } } break; case SUBOP: { TObject *l = top-2; TObject *r = top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_SUB); else { nvalue(l) -= nvalue(r); --top; } } break; case MULTOP: { TObject *l = top-2; TObject *r = top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_MUL); else { nvalue(l) *= nvalue(r); --top; } } break; case DIVOP: { TObject *l = top-2; TObject *r = top-1; if (tonumber(r) || tonumber(l)) call_arith(IM_DIV); else { nvalue(l) /= nvalue(r); --top; } } break; case POWOP: call_arith(IM_POW); break; case CONCOP: { TObject *l = top-2; TObject *r = top-1; if (tostring(l) || tostring(r)) call_binTM(IM_CONCAT, "unexpected type for concatenation"); else { tsvalue(l) = lua_createstring(lua_strconc(svalue(l),svalue(r))); --top; } } break; case MINUSOP: if (tonumber(top-1)) { ttype(top) = LUA_T_NIL; incr_top; call_arith(IM_UNM); } else nvalue(top-1) = - nvalue(top-1); break; case NOTOP: ttype(top-1) = (ttype(top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; nvalue(top-1) = 1; break; case ONTJMP: { Word w; get_word(w,pc); if (ttype(top-1) != LUA_T_NIL) pc += w; } break; case ONFJMP: { Word w; get_word(w,pc); if (ttype(top-1) == LUA_T_NIL) pc += w; } break; case JMP: { Word w; get_word(w,pc); pc += w; } break; case UPJMP: { Word w; get_word(w,pc); pc -= w; } break; case IFFJMP: { Word w; get_word(w,pc); top--; if (ttype(top) == LUA_T_NIL) pc += w; } break; case IFFUPJMP: { Word w; get_word(w,pc); top--; if (ttype(top) == LUA_T_NIL) pc -= w; } break; case POP: --top; break; case CALLFUNC: { int nParams = *(pc++); int nResults = *(pc++); StkId newBase = (top-stack)-nParams; do_call(newBase, nResults); } break; case RETCODE0: case RETCODE: if (lua_callhook) callHook (base, LUA_T_MARK, 1); return (base + ((opcode==RETCODE0) ? 0 : *pc)); case SETLINE: { Word line; get_word(line,pc); if ((stack+base-1)->ttype != LUA_T_LINE) { /* open space for LINE value */ open_stack((top-stack)-base); base++; (stack+base-1)->ttype = LUA_T_LINE; } (stack+base-1)->value.i = line; if (lua_linehook) lineHook (line); break; } default: lua_error ("internal error - opcode doesn't match"); } } }