diff options
author | Lua Team <team@lua.org> | 2000-11-06 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2000-11-06 12:00:00 +0000 |
commit | 8cb71cb5548e3138e5d4e4744f52c79d9fafb116 (patch) | |
tree | 25859eb162c67eafc46866e0ec3a9a7ebf93157a /src/lvm.c | |
parent | b7610da5fed99f59ac73ae452da8839a0f2c1bda (diff) | |
download | lua-github-4.0.tar.gz |
Lua 4.04.0
Diffstat (limited to 'src/lvm.c')
-rw-r--r-- | src/lvm.c | 1023 |
1 files changed, 549 insertions, 474 deletions
@@ -1,28 +1,27 @@ /* -** $Id: lvm.c,v 1.58 1999/06/22 20:37:23 roberto Exp $ +** $Id: lvm.c,v 1.146 2000/10/26 12:47:05 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ -#include <ctype.h> -#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "lauxlib.h" +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" -#include "lmem.h" #include "lobject.h" #include "lopcodes.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" -#include "luadebug.h" #include "lvm.h" @@ -31,605 +30,681 @@ #endif -#define highbyte(x) ((x)<<8) - - -/* Extra stack size to run a function: LUA_T_LINE(1), TM calls(2), ... */ -#define EXTRA_STACK 5 - +/* +** Extra stack size to run a function: +** TAG_LINE(1), NAME(1), TM calls(3) (plus some extra...) +*/ +#define EXTRA_STACK 8 -static TaggedString *strconc (TaggedString *l, TaggedString *r) { - long nl = l->u.s.len; - long nr = r->u.s.len; - char *buffer = luaL_openspace(nl+nr); - memcpy(buffer, l->str, nl); - memcpy(buffer+nl, r->str, nr); - return luaS_newlstr(buffer, nl+nr); -} -int luaV_tonumber (TObject *obj) { /* LUA_NUMBER */ - if (ttype(obj) != LUA_T_STRING) +int luaV_tonumber (TObject *obj) { + if (ttype(obj) != LUA_TSTRING) return 1; else { - double t; - char *e = svalue(obj); - int sig = 1; - while (isspace((unsigned char)*e)) e++; - if (*e == '-') { - e++; - sig = -1; - } - else if (*e == '+') e++; - /* no digit before or after decimal point? */ - if (!isdigit((unsigned char)*e) && !isdigit((unsigned char)*(e+1))) + if (!luaO_str2d(svalue(obj), &nvalue(obj))) return 2; - t = luaO_str2d(e); - if (t<0) return 2; - nvalue(obj) = (real)t*sig; - ttype(obj) = LUA_T_NUMBER; + ttype(obj) = LUA_TNUMBER; return 0; } } -int luaV_tostring (TObject *obj) { /* LUA_NUMBER */ - if (ttype(obj) != LUA_T_NUMBER) +int luaV_tostring (lua_State *L, TObject *obj) { /* LUA_NUMBER */ + if (ttype(obj) != LUA_TNUMBER) return 1; else { - char s[32]; /* 16 digits, signal, point and \0 (+ some extra...) */ - sprintf(s, "%.16g", (double)nvalue(obj)); - tsvalue(obj) = luaS_new(s); - ttype(obj) = LUA_T_STRING; + char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ + lua_number2str(s, nvalue(obj)); /* convert `s' to number */ + tsvalue(obj) = luaS_new(L, s); + ttype(obj) = LUA_TSTRING; return 0; } } -void luaV_setn (Hash *t, int val) { - TObject index, value; - ttype(&index) = LUA_T_STRING; tsvalue(&index) = luaS_new("n"); - ttype(&value) = LUA_T_NUMBER; nvalue(&value) = val; - luaH_set(t, &index, &value); +static void traceexec (lua_State *L, StkId base, StkId top, lua_Hook linehook) { + CallInfo *ci = infovalue(base-1); + int *lineinfo = ci->func->f.l->lineinfo; + int pc = (*ci->pc - ci->func->f.l->code) - 1; + int newline; + if (pc == 0) { /* may be first time? */ + ci->line = 1; + ci->refi = 0; + ci->lastpc = pc+1; /* make sure it will call linehook */ + } + newline = luaG_getline(lineinfo, pc, ci->line, &ci->refi); + /* calls linehook when enters a new line or jumps back (loop) */ + if (newline != ci->line || pc <= ci->lastpc) { + ci->line = newline; + L->top = top; + luaD_lineHook(L, base-2, newline, linehook); + } + ci->lastpc = pc; +} + + +static Closure *luaV_closure (lua_State *L, int nelems) { + Closure *c = luaF_newclosure(L, nelems); + L->top -= nelems; + while (nelems--) + c->upvalue[nelems] = *(L->top+nelems); + clvalue(L->top) = c; + ttype(L->top) = LUA_TFUNCTION; + incr_top; + return c; } -void luaV_closure (int nelems) { - if (nelems > 0) { - struct Stack *S = &L->stack; - Closure *c = luaF_newclosure(nelems); - c->consts[0] = *(S->top-1); - memcpy(&c->consts[1], S->top-(nelems+1), nelems*sizeof(TObject)); - S->top -= nelems; - ttype(S->top-1) = LUA_T_CLOSURE; - (S->top-1)->value.cl = c; - } +void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems) { + Closure *cl = luaV_closure(L, nelems); + cl->f.c = c; + cl->isC = 1; +} + + +void luaV_Lclosure (lua_State *L, Proto *l, int nelems) { + Closure *cl = luaV_closure(L, nelems); + cl->f.l = l; + cl->isC = 0; } /* ** Function to index a table. -** Receives the table at top-2 and the index at top-1. +** Receives the table at `t' and the key at top. */ -void luaV_gettable (void) { - TObject *table = L->stack.top-2; - TObject *im; - if (ttype(table) != LUA_T_ARRAY) { /* not a table, get gettable method */ - im = luaT_getimbyObj(table, IM_GETTABLE); - if (ttype(im) == LUA_T_NIL) - lua_error("indexed expression not a table"); +const TObject *luaV_gettable (lua_State *L, StkId t) { + Closure *tm; + int tg; + if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ + ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ + luaT_gettm(L, tg, TM_GETTABLE) == NULL)) { /* or no TM? */ + /* do a primitive get */ + const TObject *h = luaH_get(L, hvalue(t), L->top-1); + /* result is no nil or there is no `index' tag method? */ + if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(L, tg, TM_INDEX)) == NULL)) + return h; /* return result */ + /* else call `index' tag method */ } - else { /* object is a table... */ - int tg = table->value.a->htag; - im = luaT_getim(tg, IM_GETTABLE); - if (ttype(im) == LUA_T_NIL) { /* and does not have a "gettable" method */ - TObject *h = luaH_get(avalue(table), table+1); - if (ttype(h) == LUA_T_NIL && - (ttype(im=luaT_getim(tg, IM_INDEX)) != LUA_T_NIL)) { - /* result is nil and there is an "index" tag method */ - luaD_callTM(im, 2, 1); /* calls it */ - } - else { - L->stack.top--; - *table = *h; /* "push" result into table position */ - } - return; - } - /* else it has a "gettable" method, go through to next command */ + else { /* try a `gettable' tag method */ + tm = luaT_gettmbyObj(L, t, TM_GETTABLE); + } + if (tm != NULL) { /* is there a tag method? */ + luaD_checkstack(L, 2); + *(L->top+1) = *(L->top-1); /* key */ + *L->top = *t; /* table */ + clvalue(L->top-1) = tm; /* tag method */ + ttype(L->top-1) = LUA_TFUNCTION; + L->top += 2; + luaD_call(L, L->top - 3, 1); + return L->top - 1; /* call result */ + } + else { /* no tag method */ + luaG_typeerror(L, t, "index"); + return NULL; /* to avoid warnings */ } - /* object is not a table, or it has a "gettable" method */ - luaD_callTM(im, 2, 1); } /* -** Receives table at *t, index at *(t+1) and value at top. +** Receives table at `t', key at `key' and value at top. */ -void luaV_settable (TObject *t) { - struct Stack *S = &L->stack; - TObject *im; - if (ttype(t) != LUA_T_ARRAY) { /* not a table, get "settable" method */ - im = luaT_getimbyObj(t, IM_SETTABLE); - if (ttype(im) == LUA_T_NIL) - lua_error("indexed expression not a table"); - } - else { /* object is a table... */ - im = luaT_getim(avalue(t)->htag, IM_SETTABLE); - if (ttype(im) == LUA_T_NIL) { /* and does not have a "settable" method */ - luaH_set(avalue(t), t+1, S->top-1); - S->top--; /* pop value */ - return; +void luaV_settable (lua_State *L, StkId t, StkId key) { + int tg; + if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ + ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ + luaT_gettm(L, tg, TM_SETTABLE) == NULL)) /* or no TM? */ + *luaH_set(L, hvalue(t), key) = *(L->top-1); /* do a primitive set */ + else { /* try a `settable' tag method */ + Closure *tm = luaT_gettmbyObj(L, t, TM_SETTABLE); + if (tm != NULL) { + luaD_checkstack(L, 3); + *(L->top+2) = *(L->top-1); + *(L->top+1) = *key; + *(L->top) = *t; + clvalue(L->top-1) = tm; + ttype(L->top-1) = LUA_TFUNCTION; + L->top += 3; + luaD_call(L, L->top - 4, 0); /* call `settable' tag method */ } - /* else it has a "settable" method, go through to next command */ + else /* no tag method... */ + luaG_typeerror(L, t, "index"); } - /* object is not a table, or it has a "settable" method */ - /* prepare arguments and call the tag method */ - *(S->top+1) = *(L->stack.top-1); - *(S->top) = *(t+1); - *(S->top-1) = *t; - S->top += 2; /* WARNING: caller must assure stack space */ - luaD_callTM(im, 3, 0); } -void luaV_rawsettable (TObject *t) { - if (ttype(t) != LUA_T_ARRAY) - lua_error("indexed expression not a table"); - else { - struct Stack *S = &L->stack; - luaH_set(avalue(t), t+1, S->top-1); - S->top -= 3; +const TObject *luaV_getglobal (lua_State *L, TString *s) { + const TObject *value = luaH_getstr(L->gt, s); + Closure *tm = luaT_gettmbyObj(L, value, TM_GETGLOBAL); + if (tm == NULL) /* is there a tag method? */ + return value; /* default behavior */ + else { /* tag method */ + luaD_checkstack(L, 3); + clvalue(L->top) = tm; + ttype(L->top) = LUA_TFUNCTION; + tsvalue(L->top+1) = s; /* global name */ + ttype(L->top+1) = LUA_TSTRING; + *(L->top+2) = *value; + L->top += 3; + luaD_call(L, L->top - 3, 1); + return L->top - 1; } } -void luaV_getglobal (TaggedString *ts) { - /* WARNING: caller must assure stack space */ - /* only userdata, tables and nil can have getglobal tag methods */ - static char valid_getglobals[] = {1, 0, 0, 1, 0, 0, 1, 0}; /* ORDER LUA_T */ - TObject *value = &ts->u.s.globalval; - if (valid_getglobals[-ttype(value)]) { - TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL); - if (ttype(im) != LUA_T_NIL) { /* is there a tag method? */ - struct Stack *S = &L->stack; - ttype(S->top) = LUA_T_STRING; - tsvalue(S->top) = ts; - S->top++; - *S->top++ = *value; - luaD_callTM(im, 2, 1); - return; +void luaV_setglobal (lua_State *L, TString *s) { + const TObject *oldvalue = luaH_getstr(L->gt, s); + Closure *tm = luaT_gettmbyObj(L, oldvalue, TM_SETGLOBAL); + if (tm == NULL) { /* is there a tag method? */ + if (oldvalue != &luaO_nilobject) { + /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */ + *(TObject *)oldvalue = *(L->top - 1); + } + else { + TObject key; + ttype(&key) = LUA_TSTRING; + tsvalue(&key) = s; + *luaH_set(L, L->gt, &key) = *(L->top - 1); } - /* else no tag method: go through to default behavior */ } - *L->stack.top++ = *value; /* default behavior */ -} - - -void luaV_setglobal (TaggedString *ts) { - TObject *oldvalue = &ts->u.s.globalval; - TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL); - if (ttype(im) == LUA_T_NIL) /* is there a tag method? */ - luaS_rawsetglobal(ts, --L->stack.top); else { - /* WARNING: caller must assure stack space */ - struct Stack *S = &L->stack; - TObject newvalue; - newvalue = *(S->top-1); - ttype(S->top-1) = LUA_T_STRING; - tsvalue(S->top-1) = ts; - *S->top++ = *oldvalue; - *S->top++ = newvalue; - luaD_callTM(im, 3, 0); + luaD_checkstack(L, 3); + *(L->top+2) = *(L->top-1); /* new value */ + *(L->top+1) = *oldvalue; + ttype(L->top) = LUA_TSTRING; + tsvalue(L->top) = s; + clvalue(L->top-1) = tm; + ttype(L->top-1) = LUA_TFUNCTION; + L->top += 3; + luaD_call(L, L->top - 4, 0); } } -static void call_binTM (IMS event, char *msg) -{ - TObject *im = luaT_getimbyObj(L->stack.top-2, event);/* try first operand */ - if (ttype(im) == LUA_T_NIL) { - im = luaT_getimbyObj(L->stack.top-1, event); /* try second operand */ - if (ttype(im) == LUA_T_NIL) { - im = luaT_getim(0, event); /* try a 'global' i.m. */ - if (ttype(im) == LUA_T_NIL) - lua_error(msg); +static int call_binTM (lua_State *L, StkId top, TMS event) { + /* try first operand */ + Closure *tm = luaT_gettmbyObj(L, top-2, event); + L->top = top; + if (tm == NULL) { + tm = luaT_gettmbyObj(L, top-1, event); /* try second operand */ + if (tm == NULL) { + tm = luaT_gettm(L, 0, event); /* try a `global' method */ + if (tm == NULL) + return 0; /* error */ } } - lua_pushstring(luaT_eventname[event]); - luaD_callTM(im, 3, 1); + lua_pushstring(L, luaT_eventname[event]); + luaD_callTM(L, tm, 3, 1); + return 1; } -static void call_arith (IMS event) -{ - call_binTM(event, "unexpected type in arithmetic operation"); +static void call_arith (lua_State *L, StkId top, TMS event) { + if (!call_binTM(L, top, event)) + luaG_binerror(L, top-2, LUA_TNUMBER, "perform arithmetic on"); } -static int luaV_strcomp (char *l, long ll, char *r, long lr) -{ +static int luaV_strcomp (const TString *ls, const TString *rs) { + const char *l = ls->str; + size_t ll = ls->len; + const char *r = rs->str; + size_t lr = rs->len; for (;;) { - long temp = strcoll(l, r); + int temp = strcoll(l, r); if (temp != 0) return temp; - /* strings are equal up to a '\0' */ - temp = strlen(l); /* index of first '\0' in both strings */ - if (temp == ll) /* l is finished? */ - return (temp == lr) ? 0 : -1; /* l is equal or smaller than r */ - else if (temp == lr) /* r is finished? */ - return 1; /* l is greater than r (because l is not finished) */ - /* both strings longer than temp; go on comparing (after the '\0') */ - temp++; - l += temp; ll -= temp; r += temp; lr -= temp; + else { /* strings are equal up to a '\0' */ + size_t len = strlen(l); /* index of first '\0' in both strings */ + if (len == ll) /* l is finished? */ + return (len == lr) ? 0 : -1; /* l is equal or smaller than r */ + else if (len == lr) /* r is finished? */ + return 1; /* l is greater than r (because l is not finished) */ + /* both strings longer than `len'; go on comparing (after the '\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } } } -void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal, - lua_Type ttype_great, IMS op) { - struct Stack *S = &L->stack; - TObject *l = S->top-2; - TObject *r = S->top-1; - real result; - if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER) - result = nvalue(l)-nvalue(r); - else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING) - result = luaV_strcomp(svalue(l), tsvalue(l)->u.s.len, - svalue(r), tsvalue(r)->u.s.len); - else { - call_binTM(op, "unexpected type in comparison"); - return; + +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top) { + if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) + return (nvalue(l) < nvalue(r)); + else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) + return (luaV_strcomp(tsvalue(l), tsvalue(r)) < 0); + else { /* call TM */ + luaD_checkstack(L, 2); + *top++ = *l; + *top++ = *r; + if (!call_binTM(L, top, TM_LT)) + luaG_ordererror(L, top-2); + L->top--; + return (ttype(L->top) != LUA_TNIL); } - S->top--; - nvalue(S->top-1) = 1; - ttype(S->top-1) = (result < 0) ? ttype_less : - (result == 0) ? ttype_equal : ttype_great; } -void luaV_pack (StkId firstel, int nvararg, TObject *tab) { - TObject *firstelem = L->stack.stack+firstel; +void luaV_strconc (lua_State *L, int total, StkId top) { + do { + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (tostring(L, top-2) || tostring(L, top-1)) { + if (!call_binTM(L, top, TM_CONCAT)) + luaG_binerror(L, top-2, LUA_TSTRING, "concat"); + } + else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ + /* at least two string values; get as many as possible */ + lint32 tl = (lint32)tsvalue(top-1)->len + + (lint32)tsvalue(top-2)->len; + char *buffer; + int i; + while (n < total && !tostring(L, top-n-1)) { /* collect total length */ + tl += tsvalue(top-n-1)->len; + n++; + } + if (tl > MAX_SIZET) lua_error(L, "string size overflow"); + buffer = luaO_openspace(L, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, tsvalue(top-i)->str, l); + tl += l; + } + tsvalue(top-n) = luaS_newlstr(L, buffer, tl); + } + total -= n-1; /* got `n' strings to create 1 new */ + top -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void luaV_pack (lua_State *L, StkId firstelem) { int i; - Hash *htab; - if (nvararg < 0) nvararg = 0; - htab = avalue(tab) = luaH_new(nvararg+1); /* +1 for field 'n' */ - ttype(tab) = LUA_T_ARRAY; - for (i=0; i<nvararg; i++) - luaH_setint(htab, i+1, firstelem+i); - luaV_setn(htab, nvararg); /* store counter in field "n" */ + Hash *htab = luaH_new(L, 0); + for (i=0; firstelem+i<L->top; i++) + *luaH_setint(L, htab, i+1) = *(firstelem+i); + /* store counter in field `n' */ + luaH_setstrnum(L, htab, luaS_new(L, "n"), i); + L->top = firstelem; /* remove elements from the stack */ + ttype(L->top) = LUA_TTABLE; + hvalue(L->top) = htab; + incr_top; } -static void adjust_varargs (StkId first_extra_arg) -{ - TObject arg; - luaV_pack(first_extra_arg, - (L->stack.top-L->stack.stack)-first_extra_arg, &arg); - luaD_adjusttop(first_extra_arg); - *L->stack.top++ = arg; +static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { + int nvararg = (L->top-base) - nfixargs; + if (nvararg < 0) + luaD_adjusttop(L, base, nfixargs); + luaV_pack(L, base+nfixargs); } +#define dojump(pc, i) { int d = GETARG_S(i); pc += d; } + /* -** 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). +** Executes the given Lua function. Parameters are between [base,top). +** Returns n such that the the results are between [n,top). */ -StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) { - struct Stack *S = &L->stack; /* to optimize */ - register Byte *pc = tf->code; - TObject *consts = tf->consts; - if (L->callhook) - luaD_callHook(base, tf, 0); - luaD_checkstack((*pc++)+EXTRA_STACK); - if (*pc < ZEROVARARG) - luaD_adjusttop(base+*(pc++)); - else { /* varargs */ - luaC_checkGC(); - adjust_varargs(base+(*pc++)-ZEROVARARG); - } +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 (;;) { - register int aux = 0; - switchentry: - switch ((OpCode)*pc++) { - - case ENDCODE: - S->top = S->stack + base; - goto ret; - - case RETCODE: - base += *pc++; - goto ret; - - case CALL: aux = *pc++; - luaD_calln(*pc++, aux); + 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 TAILCALL: aux = *pc++; - luaD_calln(*pc++, MULT_RET); - base += aux; - goto ret; - - case PUSHNIL: aux = *pc++; + } + 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(S->top++) = LUA_T_NIL; - } while (aux--); + ttype(top++) = LUA_TNIL; + } while (--n > 0); break; - - case POP: aux = *pc++; - S->top -= aux; + } + case OP_POP: { + top -= GETARG_U(i); break; - - case PUSHNUMBERW: aux += highbyte(*pc++); - case PUSHNUMBER: aux += *pc++; - ttype(S->top) = LUA_T_NUMBER; - nvalue(S->top) = aux; - S->top++; + } + case OP_PUSHINT: { + ttype(top) = LUA_TNUMBER; + nvalue(top) = (Number)GETARG_S(i); + top++; break; - - case PUSHNUMBERNEGW: aux += highbyte(*pc++); - case PUSHNUMBERNEG: aux += *pc++; - ttype(S->top) = LUA_T_NUMBER; - nvalue(S->top) = -aux; - S->top++; + } + case OP_PUSHSTRING: { + ttype(top) = LUA_TSTRING; + tsvalue(top) = kstr[GETARG_U(i)]; + top++; break; - - case PUSHCONSTANTW: aux += highbyte(*pc++); - case PUSHCONSTANT: aux += *pc++; - *S->top++ = consts[aux]; + } + case OP_PUSHNUM: { + ttype(top) = LUA_TNUMBER; + nvalue(top) = tf->knum[GETARG_U(i)]; + top++; break; - - case PUSHUPVALUE: aux = *pc++; - *S->top++ = cl->consts[aux+1]; + } + case OP_PUSHNEGNUM: { + ttype(top) = LUA_TNUMBER; + nvalue(top) = -tf->knum[GETARG_U(i)]; + top++; break; - - case PUSHLOCAL: aux = *pc++; - *S->top++ = *((S->stack+base) + aux); + } + case OP_PUSHUPVALUE: { + *top++ = cl->upvalue[GETARG_U(i)]; break; - - case GETGLOBALW: aux += highbyte(*pc++); - case GETGLOBAL: aux += *pc++; - luaV_getglobal(tsvalue(&consts[aux])); + } + case OP_GETLOCAL: { + *top++ = *(base+GETARG_U(i)); break; - - case GETTABLE: - luaV_gettable(); + } + case OP_GETGLOBAL: { + L->top = top; + *top = *luaV_getglobal(L, kstr[GETARG_U(i)]); + top++; break; - - case GETDOTTEDW: aux += highbyte(*pc++); - case GETDOTTED: aux += *pc++; - *S->top++ = consts[aux]; - luaV_gettable(); + } + case OP_GETTABLE: { + L->top = top; + top--; + *(top-1) = *luaV_gettable(L, top-1); break; - - case PUSHSELFW: aux += highbyte(*pc++); - case PUSHSELF: aux += *pc++; { - TObject receiver; - receiver = *(S->top-1); - *S->top++ = consts[aux]; - luaV_gettable(); - *S->top++ = receiver; + } + 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 CREATEARRAYW: aux += highbyte(*pc++); - case CREATEARRAY: aux += *pc++; - luaC_checkGC(); - avalue(S->top) = luaH_new(aux); - ttype(S->top) = LUA_T_ARRAY; - S->top++; + case OP_GETINDEXED: { + *top = *(base+GETARG_U(i)); + L->top = top+1; + *(top-1) = *luaV_gettable(L, top-1); break; - - case SETLOCAL: aux = *pc++; - *((S->stack+base) + aux) = *(--S->top); + } + 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 SETGLOBALW: aux += highbyte(*pc++); - case SETGLOBAL: aux += *pc++; - luaV_setglobal(tsvalue(&consts[aux])); + } + case OP_CREATETABLE: { + L->top = top; + luaC_checkGC(L); + hvalue(top) = luaH_new(L, GETARG_U(i)); + ttype(top) = LUA_TTABLE; + top++; break; - - case SETTABLEPOP: - luaV_settable(S->top-3); - S->top -= 2; /* pop table and index */ + } + case OP_SETLOCAL: { + *(base+GETARG_U(i)) = *(--top); break; - - case SETTABLE: - luaV_settable(S->top-3-(*pc++)); + } + case OP_SETGLOBAL: { + L->top = top; + luaV_setglobal(L, kstr[GETARG_U(i)]); + top--; break; - - case SETLISTW: aux += highbyte(*pc++); - case SETLIST: aux += *pc++; { - int n = *(pc++); - Hash *arr = avalue(S->top-n-1); - aux *= LFIELDS_PER_FLUSH; + } + 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(arr, n+aux, --S->top); + *luaH_setint(L, arr, n+aux) = *(--top); break; } - - case SETMAP: aux = *pc++; { - Hash *arr = avalue(S->top-(2*aux)-3); - do { - luaH_set(arr, S->top-2, S->top-1); - S->top-=2; - } while (aux--); + 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 NEQOP: aux = 1; - case EQOP: { - int res = luaO_equalObj(S->top-2, S->top-1); - if (aux) res = !res; - S->top--; - ttype(S->top-1) = res ? LUA_T_NUMBER : LUA_T_NIL; - nvalue(S->top-1) = 1; + 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 LTOP: - luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT); - break; - - case LEOP: - luaV_comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE); + 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 GTOP: - luaV_comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT); + } + 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 GEOP: - luaV_comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE); + } + 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 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; - } + } + 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 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; - } + case OP_POW: { + if (!call_binTM(L, top, TM_POW)) + lua_error(L, "undefined operation"); + 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; - } + case OP_CONCAT: { + int n = GETARG_U(i); + luaV_strconc(L, n, top); + top -= n-1; + L->top = top; + luaC_checkGC(L); 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; + 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 POWOP: - call_binTM(IM_POW, "undefined operation"); + case OP_NOT: { + ttype(top-1) = + (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; + nvalue(top-1) = 1; 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(); + } + case OP_JMPNE: { + top -= 2; + if (!luaO_equalObj(top, top+1)) dojump(pc, i); 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); + case OP_JMPEQ: { + top -= 2; + if (luaO_equalObj(top, top+1)) dojump(pc, i); 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; + } + case OP_JMPLT: { + top -= 2; + if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); break; - - case ONTJMPW: aux += highbyte(*pc++); - case ONTJMP: aux += *pc++; - if (ttype(S->top-1) != LUA_T_NIL) pc += aux; - else S->top--; + } + case OP_JMPLE: { /* a <= b === !(b<a) */ + top -= 2; + if (!luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); break; - - case ONFJMPW: aux += highbyte(*pc++); - case ONFJMP: aux += *pc++; - if (ttype(S->top-1) == LUA_T_NIL) pc += aux; - else S->top--; + } + case OP_JMPGT: { /* a > b === (b<a) */ + top -= 2; + if (luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); break; - - case JMPW: aux += highbyte(*pc++); - case JMP: aux += *pc++; - pc += aux; + } + case OP_JMPGE: { /* a >= b === !(a<b) */ + top -= 2; + if (!luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); break; - - case IFFJMPW: aux += highbyte(*pc++); - case IFFJMP: aux += *pc++; - if (ttype(--S->top) == LUA_T_NIL) pc += aux; + } + case OP_JMPT: { + if (ttype(--top) != LUA_TNIL) dojump(pc, i); break; - - case IFTUPJMPW: aux += highbyte(*pc++); - case IFTUPJMP: aux += *pc++; - if (ttype(--S->top) != LUA_T_NIL) pc -= aux; + } + case OP_JMPF: { + if (ttype(--top) == LUA_TNIL) dojump(pc, i); break; - - case IFFUPJMPW: aux += highbyte(*pc++); - case IFFUPJMP: aux += *pc++; - if (ttype(--S->top) == LUA_T_NIL) pc -= aux; + } + case OP_JMPONT: { + if (ttype(top-1) == LUA_TNIL) top--; + else dojump(pc, i); break; - - case CLOSUREW: aux += highbyte(*pc++); - case CLOSURE: aux += *pc++; - *S->top++ = consts[aux]; - luaV_closure(*pc++); - luaC_checkGC(); + } + case OP_JMPONF: { + if (ttype(top-1) != LUA_TNIL) top--; + else dojump(pc, i); break; - - case SETLINEW: aux += highbyte(*pc++); - case SETLINE: aux += *pc++; - 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; + } + 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 */ } - (S->stack+base-1)->value.i = aux; - if (L->linehook) - luaD_lineHook(aux); break; - - case LONGARGW: aux += highbyte(*pc++); - case LONGARG: aux += *pc++; - aux = highbyte(highbyte(aux)); - goto switchentry; /* do not reset "aux" */ - - case CHECKSTACK: aux = *pc++; - LUA_ASSERT((S->top-S->stack)-base == aux && S->last >= S->top, - "wrong stack size"); + } + 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; + } } - } ret: - if (L->callhook) - luaD_callHook(0, NULL, 1); - return base; + } } - |