lua/lvm.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 17 Dec 2013 22:16:27 -0500
changeset 0 d7ee4e2ed49d
permissions -rw-r--r--
Initial work. Goes far enough to decrypt and correctly verify the master key.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     1
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     2
** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     3
** Lua virtual machine
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     4
** See Copyright Notice in lua.h
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     5
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     6
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     7
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     8
#include <stdio.h>
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     9
#include <stdlib.h>
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    10
#include <string.h>
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    11
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    12
#define lvm_c
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    13
#define LUA_CORE
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    14
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    15
#include "lua.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    16
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    17
#include "ldebug.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    18
#include "ldo.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    19
#include "lfunc.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    20
#include "lgc.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    21
#include "lobject.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    22
#include "lopcodes.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    23
#include "lstate.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    24
#include "lstring.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    25
#include "ltable.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    26
#include "ltm.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    27
#include "lvm.h"
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    28
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    29
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    30
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    31
/* limit for table tag-method chains (to avoid loops) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    32
#define MAXTAGLOOP	100
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    33
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    34
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    35
const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    36
  lua_Number num;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    37
  if (ttisnumber(obj)) return obj;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    38
  if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    39
    setnvalue(n, num);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    40
    return n;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    41
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    42
  else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    43
    return NULL;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    44
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    45
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    46
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    47
int luaV_tostring (lua_State *L, StkId obj) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    48
  if (!ttisnumber(obj))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    49
    return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    50
  else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    51
    char s[LUAI_MAXNUMBER2STR];
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    52
    lua_Number n = nvalue(obj);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    53
    int l = lua_number2str(s, n);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    54
    setsvalue2s(L, obj, luaS_newlstr(L, s, l));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    55
    return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    56
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    57
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    58
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    59
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    60
static void traceexec (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    61
  CallInfo *ci = L->ci;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    62
  lu_byte mask = L->hookmask;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    63
  int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    64
  if (counthook)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    65
    resethookcount(L);  /* reset count */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    66
  if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    67
    ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    68
    return;  /* do not call hook again (VM yielded, so it did not move) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    69
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    70
  if (counthook)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    71
    luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    72
  if (mask & LUA_MASKLINE) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    73
    Proto *p = ci_func(ci)->p;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    74
    int npc = pcRel(ci->u.l.savedpc, p);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    75
    int newline = getfuncline(p, npc);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    76
    if (npc == 0 ||  /* call linehook when enter a new function, */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    77
        ci->u.l.savedpc <= L->oldpc ||  /* when jump back (loop), or when */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    78
        newline != getfuncline(p, pcRel(L->oldpc, p)))  /* enter a new line */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    79
      luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    80
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    81
  L->oldpc = ci->u.l.savedpc;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    82
  if (L->status == LUA_YIELD) {  /* did hook yield? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    83
    if (counthook)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    84
      L->hookcount = 1;  /* undo decrement to zero */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    85
    ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    86
    ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    87
    ci->func = L->top - 1;  /* protect stack below results */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    88
    luaD_throw(L, LUA_YIELD);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    89
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    90
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    91
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    92
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    93
static void callTM (lua_State *L, const TValue *f, const TValue *p1,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    94
                    const TValue *p2, TValue *p3, int hasres) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    95
  ptrdiff_t result = savestack(L, p3);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    96
  setobj2s(L, L->top++, f);  /* push function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    97
  setobj2s(L, L->top++, p1);  /* 1st argument */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    98
  setobj2s(L, L->top++, p2);  /* 2nd argument */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    99
  if (!hasres)  /* no result? 'p3' is third argument */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   100
    setobj2s(L, L->top++, p3);  /* 3rd argument */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   101
  /* metamethod may yield only when called from Lua code */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   102
  luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   103
  if (hasres) {  /* if has result, move it to its place */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   104
    p3 = restorestack(L, result);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   105
    setobjs2s(L, p3, --L->top);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   106
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   107
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   108
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   109
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   110
void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   111
  int loop;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   112
  for (loop = 0; loop < MAXTAGLOOP; loop++) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   113
    const TValue *tm;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   114
    if (ttistable(t)) {  /* `t' is a table? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   115
      Table *h = hvalue(t);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   116
      const TValue *res = luaH_get(h, key); /* do a primitive get */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   117
      if (!ttisnil(res) ||  /* result is not nil? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   118
          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   119
        setobj2s(L, val, res);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   120
        return;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   121
      }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   122
      /* else will try the tag method */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   123
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   124
    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   125
      luaG_typeerror(L, t, "index");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   126
    if (ttisfunction(tm)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   127
      callTM(L, tm, t, key, val, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   128
      return;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   129
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   130
    t = tm;  /* else repeat with 'tm' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   131
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   132
  luaG_runerror(L, "loop in gettable");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   133
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   134
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   135
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   136
void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   137
  int loop;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   138
  for (loop = 0; loop < MAXTAGLOOP; loop++) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   139
    const TValue *tm;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   140
    if (ttistable(t)) {  /* `t' is a table? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   141
      Table *h = hvalue(t);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   142
      TValue *oldval = cast(TValue *, luaH_get(h, key));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   143
      /* if previous value is not nil, there must be a previous entry
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   144
         in the table; moreover, a metamethod has no relevance */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   145
      if (!ttisnil(oldval) ||
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   146
         /* previous value is nil; must check the metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   147
         ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   148
         /* no metamethod; is there a previous entry in the table? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   149
         (oldval != luaO_nilobject ||
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   150
         /* no previous entry; must create one. (The next test is
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   151
            always true; we only need the assignment.) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   152
         (oldval = luaH_newkey(L, h, key), 1)))) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   153
        /* no metamethod and (now) there is an entry with given key */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   154
        setobj2t(L, oldval, val);  /* assign new value to that entry */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   155
        invalidateTMcache(h);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   156
        luaC_barrierback(L, obj2gco(h), val);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   157
        return;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   158
      }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   159
      /* else will try the metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   160
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   161
    else  /* not a table; check metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   162
      if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   163
        luaG_typeerror(L, t, "index");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   164
    /* there is a metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   165
    if (ttisfunction(tm)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   166
      callTM(L, tm, t, key, val, 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   167
      return;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   168
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   169
    t = tm;  /* else repeat with 'tm' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   170
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   171
  luaG_runerror(L, "loop in settable");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   172
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   173
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   174
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   175
static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   176
                       StkId res, TMS event) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   177
  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   178
  if (ttisnil(tm))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   179
    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   180
  if (ttisnil(tm)) return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   181
  callTM(L, tm, p1, p2, res, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   182
  return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   183
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   184
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   185
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   186
static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   187
                                  TMS event) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   188
  const TValue *tm1 = fasttm(L, mt1, event);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   189
  const TValue *tm2;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   190
  if (tm1 == NULL) return NULL;  /* no metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   191
  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   192
  tm2 = fasttm(L, mt2, event);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   193
  if (tm2 == NULL) return NULL;  /* no metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   194
  if (luaV_rawequalobj(tm1, tm2))  /* same metamethods? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   195
    return tm1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   196
  return NULL;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   197
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   198
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   199
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   200
static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   201
                         TMS event) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   202
  if (!call_binTM(L, p1, p2, L->top, event))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   203
    return -1;  /* no metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   204
  else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   205
    return !l_isfalse(L->top);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   206
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   207
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   208
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   209
static int l_strcmp (const TString *ls, const TString *rs) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   210
  const char *l = getstr(ls);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   211
  size_t ll = ls->tsv.len;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   212
  const char *r = getstr(rs);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   213
  size_t lr = rs->tsv.len;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   214
  for (;;) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   215
    int temp = strcoll(l, r);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   216
    if (temp != 0) return temp;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   217
    else {  /* strings are equal up to a `\0' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   218
      size_t len = strlen(l);  /* index of first `\0' in both strings */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   219
      if (len == lr)  /* r is finished? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   220
        return (len == ll) ? 0 : 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   221
      else if (len == ll)  /* l is finished? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   222
        return -1;  /* l is smaller than r (because r is not finished) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   223
      /* both strings longer than `len'; go on comparing (after the `\0') */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   224
      len++;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   225
      l += len; ll -= len; r += len; lr -= len;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   226
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   227
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   228
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   229
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   230
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   231
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   232
  int res;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   233
  if (ttisnumber(l) && ttisnumber(r))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   234
    return luai_numlt(L, nvalue(l), nvalue(r));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   235
  else if (ttisstring(l) && ttisstring(r))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   236
    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   237
  else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   238
    luaG_ordererror(L, l, r);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   239
  return res;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   240
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   241
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   242
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   243
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   244
  int res;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   245
  if (ttisnumber(l) && ttisnumber(r))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   246
    return luai_numle(L, nvalue(l), nvalue(r));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   247
  else if (ttisstring(l) && ttisstring(r))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   248
    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   249
  else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0)  /* first try `le' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   250
    return res;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   251
  else if ((res = call_orderTM(L, r, l, TM_LT)) < 0)  /* else try `lt' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   252
    luaG_ordererror(L, l, r);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   253
  return !res;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   254
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   255
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   256
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   257
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   258
** equality of Lua values. L == NULL means raw equality (no metamethods)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   259
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   260
int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   261
  const TValue *tm;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   262
  lua_assert(ttisequal(t1, t2));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   263
  switch (ttype(t1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   264
    case LUA_TNIL: return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   265
    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   266
    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   267
    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   268
    case LUA_TLCF: return fvalue(t1) == fvalue(t2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   269
    case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   270
    case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   271
    case LUA_TUSERDATA: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   272
      if (uvalue(t1) == uvalue(t2)) return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   273
      else if (L == NULL) return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   274
      tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   275
      break;  /* will try TM */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   276
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   277
    case LUA_TTABLE: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   278
      if (hvalue(t1) == hvalue(t2)) return 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   279
      else if (L == NULL) return 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   280
      tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   281
      break;  /* will try TM */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   282
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   283
    default:
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   284
      lua_assert(iscollectable(t1));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   285
      return gcvalue(t1) == gcvalue(t2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   286
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   287
  if (tm == NULL) return 0;  /* no TM? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   288
  callTM(L, tm, t1, t2, L->top, 1);  /* call TM */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   289
  return !l_isfalse(L->top);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   290
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   291
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   292
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   293
void luaV_concat (lua_State *L, int total) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   294
  lua_assert(total >= 2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   295
  do {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   296
    StkId top = L->top;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   297
    int n = 2;  /* number of elements handled in this pass (at least 2) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   298
    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   299
      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   300
        luaG_concaterror(L, top-2, top-1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   301
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   302
    else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   303
      (void)tostring(L, top - 2);  /* result is first operand */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   304
    else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   305
      setobjs2s(L, top - 2, top - 1);  /* result is second op. */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   306
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   307
    else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   308
      /* at least two non-empty string values; get as many as possible */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   309
      size_t tl = tsvalue(top-1)->len;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   310
      char *buffer;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   311
      int i;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   312
      /* collect total length */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   313
      for (i = 1; i < total && tostring(L, top-i-1); i++) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   314
        size_t l = tsvalue(top-i-1)->len;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   315
        if (l >= (MAX_SIZET/sizeof(char)) - tl)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   316
          luaG_runerror(L, "string length overflow");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   317
        tl += l;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   318
      }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   319
      buffer = luaZ_openspace(L, &G(L)->buff, tl);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   320
      tl = 0;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   321
      n = i;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   322
      do {  /* concat all strings */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   323
        size_t l = tsvalue(top-i)->len;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   324
        memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   325
        tl += l;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   326
      } while (--i > 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   327
      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   328
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   329
    total -= n-1;  /* got 'n' strings to create 1 new */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   330
    L->top -= n-1;  /* popped 'n' strings and pushed one */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   331
  } while (total > 1);  /* repeat until only 1 result left */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   332
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   333
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   334
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   335
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   336
  const TValue *tm;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   337
  switch (ttypenv(rb)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   338
    case LUA_TTABLE: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   339
      Table *h = hvalue(rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   340
      tm = fasttm(L, h->metatable, TM_LEN);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   341
      if (tm) break;  /* metamethod? break switch to call it */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   342
      setnvalue(ra, cast_num(luaH_getn(h)));  /* else primitive len */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   343
      return;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   344
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   345
    case LUA_TSTRING: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   346
      setnvalue(ra, cast_num(tsvalue(rb)->len));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   347
      return;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   348
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   349
    default: {  /* try metamethod */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   350
      tm = luaT_gettmbyobj(L, rb, TM_LEN);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   351
      if (ttisnil(tm))  /* no metamethod? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   352
        luaG_typeerror(L, rb, "get length of");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   353
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   354
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   355
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   356
  callTM(L, tm, rb, rb, ra, 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   357
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   358
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   359
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   360
void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   361
                 const TValue *rc, TMS op) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   362
  TValue tempb, tempc;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   363
  const TValue *b, *c;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   364
  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   365
      (c = luaV_tonumber(rc, &tempc)) != NULL) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   366
    lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   367
    setnvalue(ra, res);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   368
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   369
  else if (!call_binTM(L, rb, rc, ra, op))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   370
    luaG_aritherror(L, rb, rc);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   371
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   372
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   373
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   374
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   375
** check whether cached closure in prototype 'p' may be reused, that is,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   376
** whether there is a cached closure with the same upvalues needed by
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   377
** new closure to be created.
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   378
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   379
static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   380
  Closure *c = p->cache;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   381
  if (c != NULL) {  /* is there a cached closure? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   382
    int nup = p->sizeupvalues;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   383
    Upvaldesc *uv = p->upvalues;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   384
    int i;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   385
    for (i = 0; i < nup; i++) {  /* check whether it has right upvalues */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   386
      TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   387
      if (c->l.upvals[i]->v != v)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   388
        return NULL;  /* wrong upvalue; cannot reuse closure */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   389
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   390
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   391
  return c;  /* return cached closure (or NULL if no cached closure) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   392
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   393
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   394
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   395
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   396
** create a new Lua closure, push it in the stack, and initialize
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   397
** its upvalues. Note that the call to 'luaC_barrierproto' must come
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   398
** before the assignment to 'p->cache', as the function needs the
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   399
** original value of that field.
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   400
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   401
static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   402
                         StkId ra) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   403
  int nup = p->sizeupvalues;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   404
  Upvaldesc *uv = p->upvalues;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   405
  int i;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   406
  Closure *ncl = luaF_newLclosure(L, nup);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   407
  ncl->l.p = p;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   408
  setclLvalue(L, ra, ncl);  /* anchor new closure in stack */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   409
  for (i = 0; i < nup; i++) {  /* fill in its upvalues */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   410
    if (uv[i].instack)  /* upvalue refers to local variable? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   411
      ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   412
    else  /* get upvalue from enclosing function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   413
      ncl->l.upvals[i] = encup[uv[i].idx];
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   414
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   415
  luaC_barrierproto(L, p, ncl);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   416
  p->cache = ncl;  /* save it on cache for reuse */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   417
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   418
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   419
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   420
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   421
** finish execution of an opcode interrupted by an yield
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   422
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   423
void luaV_finishOp (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   424
  CallInfo *ci = L->ci;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   425
  StkId base = ci->u.l.base;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   426
  Instruction inst = *(ci->u.l.savedpc - 1);  /* interrupted instruction */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   427
  OpCode op = GET_OPCODE(inst);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   428
  switch (op) {  /* finish its execution */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   429
    case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   430
    case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   431
    case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   432
      setobjs2s(L, base + GETARG_A(inst), --L->top);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   433
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   434
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   435
    case OP_LE: case OP_LT: case OP_EQ: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   436
      int res = !l_isfalse(L->top - 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   437
      L->top--;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   438
      /* metamethod should not be called when operand is K */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   439
      lua_assert(!ISK(GETARG_B(inst)));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   440
      if (op == OP_LE &&  /* "<=" using "<" instead? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   441
          ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   442
        res = !res;  /* invert result */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   443
      lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   444
      if (res != GETARG_A(inst))  /* condition failed? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   445
        ci->u.l.savedpc++;  /* skip jump instruction */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   446
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   447
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   448
    case OP_CONCAT: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   449
      StkId top = L->top - 1;  /* top when 'call_binTM' was called */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   450
      int b = GETARG_B(inst);      /* first element to concatenate */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   451
      int total = cast_int(top - 1 - (base + b));  /* yet to concatenate */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   452
      setobj2s(L, top - 2, top);  /* put TM result in proper position */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   453
      if (total > 1) {  /* are there elements to concat? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   454
        L->top = top - 1;  /* top is one after last element (at top-2) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   455
        luaV_concat(L, total);  /* concat them (may yield again) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   456
      }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   457
      /* move final result to final position */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   458
      setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   459
      L->top = ci->top;  /* restore top */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   460
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   461
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   462
    case OP_TFORCALL: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   463
      lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   464
      L->top = ci->top;  /* correct top */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   465
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   466
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   467
    case OP_CALL: {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   468
      if (GETARG_C(inst) - 1 >= 0)  /* nresults >= 0? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   469
        L->top = ci->top;  /* adjust results */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   470
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   471
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   472
    case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   473
      break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   474
    default: lua_assert(0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   475
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   476
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   477
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   478
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   479
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   480
/*
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   481
** some macros for common tasks in `luaV_execute'
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   482
*/
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   483
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   484
#if !defined luai_runtimecheck
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   485
#define luai_runtimecheck(L, c)		/* void */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   486
#endif
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   487
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   488
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   489
#define RA(i)	(base+GETARG_A(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   490
/* to be used after possible stack reallocation */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   491
#define RB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   492
#define RC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   493
#define RKB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   494
	ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   495
#define RKC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   496
	ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   497
#define KBx(i)  \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   498
  (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   499
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   500
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   501
/* execute a jump instruction */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   502
#define dojump(ci,i,e) \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   503
  { int a = GETARG_A(i); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   504
    if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   505
    ci->u.l.savedpc += GETARG_sBx(i) + e; }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   506
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   507
/* for test instructions, execute the jump instruction that follows it */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   508
#define donextjump(ci)	{ i = *ci->u.l.savedpc; dojump(ci, i, 1); }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   509
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   510
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   511
#define Protect(x)	{ {x;}; base = ci->u.l.base; }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   512
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   513
#define checkGC(L,c)  \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   514
  Protect( luaC_condGC(L,{L->top = (c);  /* limit of live values */ \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   515
                          luaC_step(L); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   516
                          L->top = ci->top;})  /* restore top */ \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   517
           luai_threadyield(L); )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   518
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   519
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   520
#define arith_op(op,tm) { \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   521
        TValue *rb = RKB(i); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   522
        TValue *rc = RKC(i); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   523
        if (ttisnumber(rb) && ttisnumber(rc)) { \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   524
          lua_Number nb = nvalue(rb), nc = nvalue(rc); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   525
          setnvalue(ra, op(L, nb, nc)); \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   526
        } \
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   527
        else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   528
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   529
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   530
#define vmdispatch(o)	switch(o)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   531
#define vmcase(l,b)	case l: {b}  break;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   532
#define vmcasenb(l,b)	case l: {b}		/* nb = no break */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   533
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   534
void luaV_execute (lua_State *L) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   535
  CallInfo *ci = L->ci;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   536
  LClosure *cl;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   537
  TValue *k;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   538
  StkId base;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   539
 newframe:  /* reentry point when frame changes (call/return) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   540
  lua_assert(ci == L->ci);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   541
  cl = clLvalue(ci->func);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   542
  k = cl->p->k;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   543
  base = ci->u.l.base;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   544
  /* main loop of interpreter */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   545
  for (;;) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   546
    Instruction i = *(ci->u.l.savedpc++);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   547
    StkId ra;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   548
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   549
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   550
      Protect(traceexec(L));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   551
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   552
    /* WARNING: several calls may realloc the stack and invalidate `ra' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   553
    ra = RA(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   554
    lua_assert(base == ci->u.l.base);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   555
    lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   556
    vmdispatch (GET_OPCODE(i)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   557
      vmcase(OP_MOVE,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   558
        setobjs2s(L, ra, RB(i));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   559
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   560
      vmcase(OP_LOADK,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   561
        TValue *rb = k + GETARG_Bx(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   562
        setobj2s(L, ra, rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   563
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   564
      vmcase(OP_LOADKX,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   565
        TValue *rb;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   566
        lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   567
        rb = k + GETARG_Ax(*ci->u.l.savedpc++);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   568
        setobj2s(L, ra, rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   569
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   570
      vmcase(OP_LOADBOOL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   571
        setbvalue(ra, GETARG_B(i));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   572
        if (GETARG_C(i)) ci->u.l.savedpc++;  /* skip next instruction (if C) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   573
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   574
      vmcase(OP_LOADNIL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   575
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   576
        do {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   577
          setnilvalue(ra++);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   578
        } while (b--);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   579
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   580
      vmcase(OP_GETUPVAL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   581
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   582
        setobj2s(L, ra, cl->upvals[b]->v);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   583
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   584
      vmcase(OP_GETTABUP,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   585
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   586
        Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   587
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   588
      vmcase(OP_GETTABLE,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   589
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   590
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   591
      vmcase(OP_SETTABUP,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   592
        int a = GETARG_A(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   593
        Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   594
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   595
      vmcase(OP_SETUPVAL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   596
        UpVal *uv = cl->upvals[GETARG_B(i)];
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   597
        setobj(L, uv->v, ra);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   598
        luaC_barrier(L, uv, ra);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   599
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   600
      vmcase(OP_SETTABLE,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   601
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   602
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   603
      vmcase(OP_NEWTABLE,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   604
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   605
        int c = GETARG_C(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   606
        Table *t = luaH_new(L);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   607
        sethvalue(L, ra, t);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   608
        if (b != 0 || c != 0)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   609
          luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   610
        checkGC(L, ra + 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   611
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   612
      vmcase(OP_SELF,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   613
        StkId rb = RB(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   614
        setobjs2s(L, ra+1, rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   615
        Protect(luaV_gettable(L, rb, RKC(i), ra));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   616
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   617
      vmcase(OP_ADD,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   618
        arith_op(luai_numadd, TM_ADD);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   619
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   620
      vmcase(OP_SUB,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   621
        arith_op(luai_numsub, TM_SUB);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   622
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   623
      vmcase(OP_MUL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   624
        arith_op(luai_nummul, TM_MUL);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   625
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   626
      vmcase(OP_DIV,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   627
        arith_op(luai_numdiv, TM_DIV);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   628
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   629
      vmcase(OP_MOD,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   630
        arith_op(luai_nummod, TM_MOD);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   631
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   632
      vmcase(OP_POW,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   633
        arith_op(luai_numpow, TM_POW);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   634
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   635
      vmcase(OP_UNM,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   636
        TValue *rb = RB(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   637
        if (ttisnumber(rb)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   638
          lua_Number nb = nvalue(rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   639
          setnvalue(ra, luai_numunm(L, nb));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   640
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   641
        else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   642
          Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   643
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   644
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   645
      vmcase(OP_NOT,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   646
        TValue *rb = RB(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   647
        int res = l_isfalse(rb);  /* next assignment may change this value */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   648
        setbvalue(ra, res);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   649
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   650
      vmcase(OP_LEN,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   651
        Protect(luaV_objlen(L, ra, RB(i)));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   652
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   653
      vmcase(OP_CONCAT,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   654
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   655
        int c = GETARG_C(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   656
        StkId rb;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   657
        L->top = base + c + 1;  /* mark the end of concat operands */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   658
        Protect(luaV_concat(L, c - b + 1));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   659
        ra = RA(i);  /* 'luav_concat' may invoke TMs and move the stack */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   660
        rb = b + base;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   661
        setobjs2s(L, ra, rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   662
        checkGC(L, (ra >= rb ? ra + 1 : rb));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   663
        L->top = ci->top;  /* restore top */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   664
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   665
      vmcase(OP_JMP,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   666
        dojump(ci, i, 0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   667
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   668
      vmcase(OP_EQ,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   669
        TValue *rb = RKB(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   670
        TValue *rc = RKC(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   671
        Protect(
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   672
          if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   673
            ci->u.l.savedpc++;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   674
          else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   675
            donextjump(ci);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   676
        )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   677
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   678
      vmcase(OP_LT,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   679
        Protect(
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   680
          if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   681
            ci->u.l.savedpc++;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   682
          else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   683
            donextjump(ci);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   684
        )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   685
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   686
      vmcase(OP_LE,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   687
        Protect(
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   688
          if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   689
            ci->u.l.savedpc++;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   690
          else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   691
            donextjump(ci);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   692
        )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   693
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   694
      vmcase(OP_TEST,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   695
        if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   696
            ci->u.l.savedpc++;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   697
          else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   698
          donextjump(ci);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   699
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   700
      vmcase(OP_TESTSET,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   701
        TValue *rb = RB(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   702
        if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   703
          ci->u.l.savedpc++;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   704
        else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   705
          setobjs2s(L, ra, rb);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   706
          donextjump(ci);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   707
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   708
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   709
      vmcase(OP_CALL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   710
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   711
        int nresults = GETARG_C(i) - 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   712
        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   713
        if (luaD_precall(L, ra, nresults)) {  /* C function? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   714
          if (nresults >= 0) L->top = ci->top;  /* adjust results */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   715
          base = ci->u.l.base;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   716
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   717
        else {  /* Lua function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   718
          ci = L->ci;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   719
          ci->callstatus |= CIST_REENTRY;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   720
          goto newframe;  /* restart luaV_execute over new Lua function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   721
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   722
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   723
      vmcase(OP_TAILCALL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   724
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   725
        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   726
        lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   727
        if (luaD_precall(L, ra, LUA_MULTRET))  /* C function? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   728
          base = ci->u.l.base;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   729
        else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   730
          /* tail call: put called frame (n) in place of caller one (o) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   731
          CallInfo *nci = L->ci;  /* called frame */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   732
          CallInfo *oci = nci->previous;  /* caller frame */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   733
          StkId nfunc = nci->func;  /* called function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   734
          StkId ofunc = oci->func;  /* caller function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   735
          /* last stack slot filled by 'precall' */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   736
          StkId lim = nci->u.l.base + getproto(nfunc)->numparams;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   737
          int aux;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   738
          /* close all upvalues from previous call */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   739
          if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   740
          /* move new frame into old one */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   741
          for (aux = 0; nfunc + aux < lim; aux++)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   742
            setobjs2s(L, ofunc + aux, nfunc + aux);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   743
          oci->u.l.base = ofunc + (nci->u.l.base - nfunc);  /* correct base */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   744
          oci->top = L->top = ofunc + (L->top - nfunc);  /* correct top */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   745
          oci->u.l.savedpc = nci->u.l.savedpc;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   746
          oci->callstatus |= CIST_TAIL;  /* function was tail called */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   747
          ci = L->ci = oci;  /* remove new frame */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   748
          lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   749
          goto newframe;  /* restart luaV_execute over new Lua function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   750
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   751
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   752
      vmcasenb(OP_RETURN,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   753
        int b = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   754
        if (b != 0) L->top = ra+b-1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   755
        if (cl->p->sizep > 0) luaF_close(L, base);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   756
        b = luaD_poscall(L, ra);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   757
        if (!(ci->callstatus & CIST_REENTRY))  /* 'ci' still the called one */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   758
          return;  /* external invocation: return */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   759
        else {  /* invocation via reentry: continue execution */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   760
          ci = L->ci;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   761
          if (b) L->top = ci->top;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   762
          lua_assert(isLua(ci));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   763
          lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   764
          goto newframe;  /* restart luaV_execute over new Lua function */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   765
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   766
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   767
      vmcase(OP_FORLOOP,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   768
        lua_Number step = nvalue(ra+2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   769
        lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   770
        lua_Number limit = nvalue(ra+1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   771
        if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   772
                                   : luai_numle(L, limit, idx)) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   773
          ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   774
          setnvalue(ra, idx);  /* update internal index... */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   775
          setnvalue(ra+3, idx);  /* ...and external index */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   776
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   777
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   778
      vmcase(OP_FORPREP,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   779
        const TValue *init = ra;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   780
        const TValue *plimit = ra+1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   781
        const TValue *pstep = ra+2;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   782
        if (!tonumber(init, ra))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   783
          luaG_runerror(L, LUA_QL("for") " initial value must be a number");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   784
        else if (!tonumber(plimit, ra+1))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   785
          luaG_runerror(L, LUA_QL("for") " limit must be a number");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   786
        else if (!tonumber(pstep, ra+2))
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   787
          luaG_runerror(L, LUA_QL("for") " step must be a number");
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   788
        setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   789
        ci->u.l.savedpc += GETARG_sBx(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   790
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   791
      vmcasenb(OP_TFORCALL,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   792
        StkId cb = ra + 3;  /* call base */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   793
        setobjs2s(L, cb+2, ra+2);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   794
        setobjs2s(L, cb+1, ra+1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   795
        setobjs2s(L, cb, ra);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   796
        L->top = cb + 3;  /* func. + 2 args (state and index) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   797
        Protect(luaD_call(L, cb, GETARG_C(i), 1));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   798
        L->top = ci->top;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   799
        i = *(ci->u.l.savedpc++);  /* go to next instruction */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   800
        ra = RA(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   801
        lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   802
        goto l_tforloop;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   803
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   804
      vmcase(OP_TFORLOOP,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   805
        l_tforloop:
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   806
        if (!ttisnil(ra + 1)) {  /* continue loop? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   807
          setobjs2s(L, ra, ra + 1);  /* save control variable */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   808
           ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   809
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   810
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   811
      vmcase(OP_SETLIST,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   812
        int n = GETARG_B(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   813
        int c = GETARG_C(i);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   814
        int last;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   815
        Table *h;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   816
        if (n == 0) n = cast_int(L->top - ra) - 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   817
        if (c == 0) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   818
          lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   819
          c = GETARG_Ax(*ci->u.l.savedpc++);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   820
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   821
        luai_runtimecheck(L, ttistable(ra));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   822
        h = hvalue(ra);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   823
        last = ((c-1)*LFIELDS_PER_FLUSH) + n;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   824
        if (last > h->sizearray)  /* needs more space? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   825
          luaH_resizearray(L, h, last);  /* pre-allocate it at once */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   826
        for (; n > 0; n--) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   827
          TValue *val = ra+n;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   828
          luaH_setint(L, h, last--, val);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   829
          luaC_barrierback(L, obj2gco(h), val);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   830
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   831
        L->top = ci->top;  /* correct top (in case of previous open call) */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   832
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   833
      vmcase(OP_CLOSURE,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   834
        Proto *p = cl->p->p[GETARG_Bx(i)];
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   835
        Closure *ncl = getcached(p, cl->upvals, base);  /* cached closure */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   836
        if (ncl == NULL)  /* no match? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   837
          pushclosure(L, p, cl->upvals, base, ra);  /* create a new one */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   838
        else
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   839
          setclLvalue(L, ra, ncl);  /* push cashed closure */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   840
        checkGC(L, ra + 1);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   841
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   842
      vmcase(OP_VARARG,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   843
        int b = GETARG_B(i) - 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   844
        int j;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   845
        int n = cast_int(base - ci->func) - cl->p->numparams - 1;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   846
        if (b < 0) {  /* B == 0? */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   847
          b = n;  /* get all var. arguments */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   848
          Protect(luaD_checkstack(L, n));
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   849
          ra = RA(i);  /* previous call may change the stack */
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   850
          L->top = ra + n;
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   851
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   852
        for (j = 0; j < b; j++) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   853
          if (j < n) {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   854
            setobjs2s(L, ra + j, base - n + j);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   855
          }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   856
          else {
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   857
            setnilvalue(ra + j);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   858
          }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   859
        }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   860
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   861
      vmcase(OP_EXTRAARG,
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   862
        lua_assert(0);
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   863
      )
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   864
    }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   865
  }
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   866
}
d7ee4e2ed49d Initial work.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   867