summaryrefslogtreecommitdiff
path: root/src/lvm.c
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2000-11-06 12:00:00 +0000
committerrepogen <>2000-11-06 12:00:00 +0000
commit8cb71cb5548e3138e5d4e4744f52c79d9fafb116 (patch)
tree25859eb162c67eafc46866e0ec3a9a7ebf93157a /src/lvm.c
parentb7610da5fed99f59ac73ae452da8839a0f2c1bda (diff)
downloadlua-github-4.0.tar.gz
Lua 4.04.0
Diffstat (limited to 'src/lvm.c')
-rw-r--r--src/lvm.c1023
1 files changed, 549 insertions, 474 deletions
diff --git a/src/lvm.c b/src/lvm.c
index 670642b9..63e42efb 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -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;
+ }
}
-