misc/liblua/lcode.c
author unc0rr
Thu, 21 Feb 2013 22:43:00 +0400
changeset 8541 0cd63b963330
parent 2812 0a24853de796
child 10017 de822cd3df3a
permissions -rw-r--r--
Try to prevent hedgehogs number in team desync
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2812
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     1
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     2
** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     3
** Code generator for Lua
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     4
** See Copyright Notice in lua.h
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     5
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     6
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     7
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     8
#include <stdlib.h>
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     9
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    10
#define lcode_c
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    11
#define LUA_CORE
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    12
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    13
#include "lua.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    14
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    15
#include "lcode.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    16
#include "ldebug.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    17
#include "ldo.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    18
#include "lgc.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    19
#include "llex.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    20
#include "lmem.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    21
#include "lobject.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    22
#include "lopcodes.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    23
#include "lparser.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    24
#include "ltable.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    25
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    26
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    27
#define hasjumps(e)	((e)->t != (e)->f)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    28
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    29
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    30
static int isnumeral(expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    31
  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    32
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    33
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    34
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    35
void luaK_nil (FuncState *fs, int from, int n) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    36
  Instruction *previous;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    37
  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    38
    if (fs->pc == 0) {  /* function start? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    39
      if (from >= fs->nactvar)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    40
        return;  /* positions are already clean */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    41
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    42
    else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    43
      previous = &fs->f->code[fs->pc-1];
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    44
      if (GET_OPCODE(*previous) == OP_LOADNIL) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    45
        int pfrom = GETARG_A(*previous);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    46
        int pto = GETARG_B(*previous);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    47
        if (pfrom <= from && from <= pto+1) {  /* can connect both? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    48
          if (from+n-1 > pto)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    49
            SETARG_B(*previous, from+n-1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    50
          return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    51
        }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    52
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    53
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    54
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    55
  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    56
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    57
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    58
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    59
int luaK_jump (FuncState *fs) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    60
  int jpc = fs->jpc;  /* save list of jumps to here */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    61
  int j;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    62
  fs->jpc = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    63
  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    64
  luaK_concat(fs, &j, jpc);  /* keep them on hold */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    65
  return j;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    66
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    67
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    68
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    69
void luaK_ret (FuncState *fs, int first, int nret) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    70
  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    71
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    72
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    73
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    74
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    75
  luaK_codeABC(fs, op, A, B, C);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    76
  return luaK_jump(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    77
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    78
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    79
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    80
static void fixjump (FuncState *fs, int pc, int dest) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    81
  Instruction *jmp = &fs->f->code[pc];
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    82
  int offset = dest-(pc+1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    83
  lua_assert(dest != NO_JUMP);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    84
  if (abs(offset) > MAXARG_sBx)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    85
    luaX_syntaxerror(fs->ls, "control structure too long");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    86
  SETARG_sBx(*jmp, offset);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    87
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    88
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    89
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    90
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    91
** returns current `pc' and marks it as a jump target (to avoid wrong
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    92
** optimizations with consecutive instructions not in the same basic block).
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    93
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    94
int luaK_getlabel (FuncState *fs) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    95
  fs->lasttarget = fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    96
  return fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    97
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    98
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    99
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   100
static int getjump (FuncState *fs, int pc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   101
  int offset = GETARG_sBx(fs->f->code[pc]);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   102
  if (offset == NO_JUMP)  /* point to itself represents end of list */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   103
    return NO_JUMP;  /* end of list */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   104
  else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   105
    return (pc+1)+offset;  /* turn offset into absolute position */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   106
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   107
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   108
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   109
static Instruction *getjumpcontrol (FuncState *fs, int pc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   110
  Instruction *pi = &fs->f->code[pc];
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   111
  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   112
    return pi-1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   113
  else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   114
    return pi;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   115
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   116
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   117
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   118
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   119
** check whether list has any jump that do not produce a value
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   120
** (or produce an inverted value)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   121
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   122
static int need_value (FuncState *fs, int list) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   123
  for (; list != NO_JUMP; list = getjump(fs, list)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   124
    Instruction i = *getjumpcontrol(fs, list);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   125
    if (GET_OPCODE(i) != OP_TESTSET) return 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   126
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   127
  return 0;  /* not found */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   128
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   129
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   130
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   131
static int patchtestreg (FuncState *fs, int node, int reg) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   132
  Instruction *i = getjumpcontrol(fs, node);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   133
  if (GET_OPCODE(*i) != OP_TESTSET)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   134
    return 0;  /* cannot patch other instructions */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   135
  if (reg != NO_REG && reg != GETARG_B(*i))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   136
    SETARG_A(*i, reg);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   137
  else  /* no register to put value or register already has the value */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   138
    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   139
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   140
  return 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   141
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   142
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   143
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   144
static void removevalues (FuncState *fs, int list) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   145
  for (; list != NO_JUMP; list = getjump(fs, list))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   146
      patchtestreg(fs, list, NO_REG);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   147
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   148
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   149
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   150
static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   151
                          int dtarget) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   152
  while (list != NO_JUMP) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   153
    int next = getjump(fs, list);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   154
    if (patchtestreg(fs, list, reg))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   155
      fixjump(fs, list, vtarget);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   156
    else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   157
      fixjump(fs, list, dtarget);  /* jump to default target */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   158
    list = next;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   159
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   160
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   161
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   162
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   163
static void dischargejpc (FuncState *fs) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   164
  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   165
  fs->jpc = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   166
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   167
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   168
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   169
void luaK_patchlist (FuncState *fs, int list, int target) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   170
  if (target == fs->pc)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   171
    luaK_patchtohere(fs, list);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   172
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   173
    lua_assert(target < fs->pc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   174
    patchlistaux(fs, list, target, NO_REG, target);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   175
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   176
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   177
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   178
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   179
void luaK_patchtohere (FuncState *fs, int list) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   180
  luaK_getlabel(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   181
  luaK_concat(fs, &fs->jpc, list);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   182
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   183
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   184
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   185
void luaK_concat (FuncState *fs, int *l1, int l2) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   186
  if (l2 == NO_JUMP) return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   187
  else if (*l1 == NO_JUMP)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   188
    *l1 = l2;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   189
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   190
    int list = *l1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   191
    int next;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   192
    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   193
      list = next;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   194
    fixjump(fs, list, l2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   195
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   196
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   197
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   198
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   199
void luaK_checkstack (FuncState *fs, int n) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   200
  int newstack = fs->freereg + n;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   201
  if (newstack > fs->f->maxstacksize) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   202
    if (newstack >= MAXSTACK)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   203
      luaX_syntaxerror(fs->ls, "function or expression too complex");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   204
    fs->f->maxstacksize = cast_byte(newstack);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   205
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   206
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   207
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   208
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   209
void luaK_reserveregs (FuncState *fs, int n) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   210
  luaK_checkstack(fs, n);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   211
  fs->freereg += n;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   212
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   213
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   214
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   215
static void freereg (FuncState *fs, int reg) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   216
  if (!ISK(reg) && reg >= fs->nactvar) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   217
    fs->freereg--;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   218
    lua_assert(reg == fs->freereg);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   219
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   220
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   221
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   222
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   223
static void freeexp (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   224
  if (e->k == VNONRELOC)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   225
    freereg(fs, e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   226
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   227
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   228
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   229
static int addk (FuncState *fs, TValue *k, TValue *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   230
  lua_State *L = fs->L;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   231
  TValue *idx = luaH_set(L, fs->h, k);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   232
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   233
  int oldsize = f->sizek;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   234
  if (ttisnumber(idx)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   235
    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   236
    return cast_int(nvalue(idx));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   237
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   238
  else {  /* constant not found; create a new entry */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   239
    setnvalue(idx, cast_num(fs->nk));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   240
    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   241
                    MAXARG_Bx, "constant table overflow");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   242
    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   243
    setobj(L, &f->k[fs->nk], v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   244
    luaC_barrier(L, f, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   245
    return fs->nk++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   246
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   247
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   248
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   249
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   250
int luaK_stringK (FuncState *fs, TString *s) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   251
  TValue o;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   252
  setsvalue(fs->L, &o, s);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   253
  return addk(fs, &o, &o);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   254
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   255
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   256
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   257
int luaK_numberK (FuncState *fs, lua_Number r) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   258
  TValue o;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   259
  setnvalue(&o, r);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   260
  return addk(fs, &o, &o);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   261
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   262
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   263
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   264
static int boolK (FuncState *fs, int b) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   265
  TValue o;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   266
  setbvalue(&o, b);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   267
  return addk(fs, &o, &o);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   268
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   269
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   270
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   271
static int nilK (FuncState *fs) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   272
  TValue k, v;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   273
  setnilvalue(&v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   274
  /* cannot use nil as key; instead use table itself to represent nil */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   275
  sethvalue(fs->L, &k, fs->h);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   276
  return addk(fs, &k, &v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   277
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   278
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   279
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   280
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   281
  if (e->k == VCALL) {  /* expression is an open function call? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   282
    SETARG_C(getcode(fs, e), nresults+1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   283
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   284
  else if (e->k == VVARARG) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   285
    SETARG_B(getcode(fs, e), nresults+1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   286
    SETARG_A(getcode(fs, e), fs->freereg);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   287
    luaK_reserveregs(fs, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   288
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   289
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   290
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   291
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   292
void luaK_setoneret (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   293
  if (e->k == VCALL) {  /* expression is an open function call? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   294
    e->k = VNONRELOC;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   295
    e->u.s.info = GETARG_A(getcode(fs, e));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   296
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   297
  else if (e->k == VVARARG) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   298
    SETARG_B(getcode(fs, e), 2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   299
    e->k = VRELOCABLE;  /* can relocate its simple result */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   300
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   301
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   302
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   303
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   304
void luaK_dischargevars (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   305
  switch (e->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   306
    case VLOCAL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   307
      e->k = VNONRELOC;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   308
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   309
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   310
    case VUPVAL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   311
      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   312
      e->k = VRELOCABLE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   313
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   314
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   315
    case VGLOBAL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   316
      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   317
      e->k = VRELOCABLE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   318
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   319
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   320
    case VINDEXED: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   321
      freereg(fs, e->u.s.aux);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   322
      freereg(fs, e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   323
      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   324
      e->k = VRELOCABLE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   325
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   326
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   327
    case VVARARG:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   328
    case VCALL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   329
      luaK_setoneret(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   330
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   331
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   332
    default: break;  /* there is one value available (somewhere) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   333
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   334
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   335
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   336
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   337
static int code_label (FuncState *fs, int A, int b, int jump) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   338
  luaK_getlabel(fs);  /* those instructions may be jump targets */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   339
  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   340
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   341
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   342
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   343
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   344
  luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   345
  switch (e->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   346
    case VNIL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   347
      luaK_nil(fs, reg, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   348
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   349
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   350
    case VFALSE:  case VTRUE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   351
      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   352
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   353
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   354
    case VK: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   355
      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   356
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   357
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   358
    case VKNUM: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   359
      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   360
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   361
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   362
    case VRELOCABLE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   363
      Instruction *pc = &getcode(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   364
      SETARG_A(*pc, reg);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   365
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   366
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   367
    case VNONRELOC: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   368
      if (reg != e->u.s.info)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   369
        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   370
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   371
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   372
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   373
      lua_assert(e->k == VVOID || e->k == VJMP);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   374
      return;  /* nothing to do... */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   375
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   376
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   377
  e->u.s.info = reg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   378
  e->k = VNONRELOC;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   379
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   380
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   381
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   382
static void discharge2anyreg (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   383
  if (e->k != VNONRELOC) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   384
    luaK_reserveregs(fs, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   385
    discharge2reg(fs, e, fs->freereg-1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   386
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   387
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   388
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   389
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   390
static void exp2reg (FuncState *fs, expdesc *e, int reg) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   391
  discharge2reg(fs, e, reg);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   392
  if (e->k == VJMP)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   393
    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   394
  if (hasjumps(e)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   395
    int final;  /* position after whole expression */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   396
    int p_f = NO_JUMP;  /* position of an eventual LOAD false */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   397
    int p_t = NO_JUMP;  /* position of an eventual LOAD true */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   398
    if (need_value(fs, e->t) || need_value(fs, e->f)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   399
      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   400
      p_f = code_label(fs, reg, 0, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   401
      p_t = code_label(fs, reg, 1, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   402
      luaK_patchtohere(fs, fj);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   403
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   404
    final = luaK_getlabel(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   405
    patchlistaux(fs, e->f, final, reg, p_f);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   406
    patchlistaux(fs, e->t, final, reg, p_t);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   407
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   408
  e->f = e->t = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   409
  e->u.s.info = reg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   410
  e->k = VNONRELOC;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   411
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   412
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   413
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   414
void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   415
  luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   416
  freeexp(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   417
  luaK_reserveregs(fs, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   418
  exp2reg(fs, e, fs->freereg - 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   419
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   420
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   421
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   422
int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   423
  luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   424
  if (e->k == VNONRELOC) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   425
    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   426
    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   427
      exp2reg(fs, e, e->u.s.info);  /* put value on it */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   428
      return e->u.s.info;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   429
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   430
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   431
  luaK_exp2nextreg(fs, e);  /* default */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   432
  return e->u.s.info;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   433
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   434
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   435
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   436
void luaK_exp2val (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   437
  if (hasjumps(e))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   438
    luaK_exp2anyreg(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   439
  else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   440
    luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   441
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   442
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   443
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   444
int luaK_exp2RK (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   445
  luaK_exp2val(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   446
  switch (e->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   447
    case VKNUM:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   448
    case VTRUE:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   449
    case VFALSE:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   450
    case VNIL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   451
      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   452
        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   453
                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   454
                                        boolK(fs, (e->k == VTRUE));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   455
        e->k = VK;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   456
        return RKASK(e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   457
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   458
      else break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   459
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   460
    case VK: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   461
      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   462
        return RKASK(e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   463
      else break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   464
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   465
    default: break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   466
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   467
  /* not a constant in the right range: put it in a register */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   468
  return luaK_exp2anyreg(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   469
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   470
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   471
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   472
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   473
  switch (var->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   474
    case VLOCAL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   475
      freeexp(fs, ex);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   476
      exp2reg(fs, ex, var->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   477
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   478
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   479
    case VUPVAL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   480
      int e = luaK_exp2anyreg(fs, ex);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   481
      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   482
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   483
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   484
    case VGLOBAL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   485
      int e = luaK_exp2anyreg(fs, ex);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   486
      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   487
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   488
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   489
    case VINDEXED: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   490
      int e = luaK_exp2RK(fs, ex);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   491
      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   492
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   493
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   494
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   495
      lua_assert(0);  /* invalid var kind to store */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   496
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   497
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   498
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   499
  freeexp(fs, ex);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   500
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   501
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   502
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   503
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   504
  int func;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   505
  luaK_exp2anyreg(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   506
  freeexp(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   507
  func = fs->freereg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   508
  luaK_reserveregs(fs, 2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   509
  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   510
  freeexp(fs, key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   511
  e->u.s.info = func;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   512
  e->k = VNONRELOC;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   513
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   514
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   515
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   516
static void invertjump (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   517
  Instruction *pc = getjumpcontrol(fs, e->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   518
  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   519
                                           GET_OPCODE(*pc) != OP_TEST);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   520
  SETARG_A(*pc, !(GETARG_A(*pc)));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   521
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   522
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   523
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   524
static int jumponcond (FuncState *fs, expdesc *e, int cond) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   525
  if (e->k == VRELOCABLE) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   526
    Instruction ie = getcode(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   527
    if (GET_OPCODE(ie) == OP_NOT) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   528
      fs->pc--;  /* remove previous OP_NOT */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   529
      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   530
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   531
    /* else go through */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   532
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   533
  discharge2anyreg(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   534
  freeexp(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   535
  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   536
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   537
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   538
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   539
void luaK_goiftrue (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   540
  int pc;  /* pc of last jump */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   541
  luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   542
  switch (e->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   543
    case VK: case VKNUM: case VTRUE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   544
      pc = NO_JUMP;  /* always true; do nothing */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   545
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   546
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   547
    case VFALSE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   548
      pc = luaK_jump(fs);  /* always jump */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   549
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   550
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   551
    case VJMP: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   552
      invertjump(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   553
      pc = e->u.s.info;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   554
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   555
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   556
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   557
      pc = jumponcond(fs, e, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   558
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   559
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   560
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   561
  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   562
  luaK_patchtohere(fs, e->t);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   563
  e->t = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   564
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   565
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   566
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   567
static void luaK_goiffalse (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   568
  int pc;  /* pc of last jump */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   569
  luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   570
  switch (e->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   571
    case VNIL: case VFALSE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   572
      pc = NO_JUMP;  /* always false; do nothing */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   573
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   574
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   575
    case VTRUE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   576
      pc = luaK_jump(fs);  /* always jump */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   577
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   578
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   579
    case VJMP: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   580
      pc = e->u.s.info;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   581
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   582
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   583
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   584
      pc = jumponcond(fs, e, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   585
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   586
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   587
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   588
  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   589
  luaK_patchtohere(fs, e->f);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   590
  e->f = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   591
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   592
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   593
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   594
static void codenot (FuncState *fs, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   595
  luaK_dischargevars(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   596
  switch (e->k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   597
    case VNIL: case VFALSE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   598
      e->k = VTRUE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   599
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   600
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   601
    case VK: case VKNUM: case VTRUE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   602
      e->k = VFALSE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   603
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   604
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   605
    case VJMP: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   606
      invertjump(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   607
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   608
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   609
    case VRELOCABLE:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   610
    case VNONRELOC: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   611
      discharge2anyreg(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   612
      freeexp(fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   613
      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   614
      e->k = VRELOCABLE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   615
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   616
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   617
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   618
      lua_assert(0);  /* cannot happen */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   619
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   620
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   621
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   622
  /* interchange true and false lists */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   623
  { int temp = e->f; e->f = e->t; e->t = temp; }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   624
  removevalues(fs, e->f);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   625
  removevalues(fs, e->t);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   626
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   627
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   628
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   629
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   630
  t->u.s.aux = luaK_exp2RK(fs, k);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   631
  t->k = VINDEXED;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   632
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   633
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   634
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   635
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   636
  lua_Number v1, v2, r;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   637
  if (!isnumeral(e1) || !isnumeral(e2)) return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   638
  v1 = e1->u.nval;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   639
  v2 = e2->u.nval;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   640
  switch (op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   641
    case OP_ADD: r = luai_numadd(v1, v2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   642
    case OP_SUB: r = luai_numsub(v1, v2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   643
    case OP_MUL: r = luai_nummul(v1, v2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   644
    case OP_DIV:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   645
      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   646
      r = luai_numdiv(v1, v2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   647
    case OP_MOD:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   648
      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   649
      r = luai_nummod(v1, v2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   650
    case OP_POW: r = luai_numpow(v1, v2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   651
    case OP_UNM: r = luai_numunm(v1); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   652
    case OP_LEN: return 0;  /* no constant folding for 'len' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   653
    default: lua_assert(0); r = 0; break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   654
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   655
  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   656
  e1->u.nval = r;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   657
  return 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   658
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   659
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   660
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   661
static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   662
  if (constfolding(op, e1, e2))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   663
    return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   664
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   665
    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   666
    int o1 = luaK_exp2RK(fs, e1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   667
    if (o1 > o2) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   668
      freeexp(fs, e1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   669
      freeexp(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   670
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   671
    else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   672
      freeexp(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   673
      freeexp(fs, e1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   674
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   675
    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   676
    e1->k = VRELOCABLE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   677
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   678
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   679
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   680
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   681
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   682
                                                          expdesc *e2) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   683
  int o1 = luaK_exp2RK(fs, e1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   684
  int o2 = luaK_exp2RK(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   685
  freeexp(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   686
  freeexp(fs, e1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   687
  if (cond == 0 && op != OP_EQ) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   688
    int temp;  /* exchange args to replace by `<' or `<=' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   689
    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   690
    cond = 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   691
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   692
  e1->u.s.info = condjump(fs, op, cond, o1, o2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   693
  e1->k = VJMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   694
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   695
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   696
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   697
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   698
  expdesc e2;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   699
  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   700
  switch (op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   701
    case OPR_MINUS: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   702
      if (!isnumeral(e))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   703
        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   704
      codearith(fs, OP_UNM, e, &e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   705
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   706
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   707
    case OPR_NOT: codenot(fs, e); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   708
    case OPR_LEN: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   709
      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   710
      codearith(fs, OP_LEN, e, &e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   711
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   712
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   713
    default: lua_assert(0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   714
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   715
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   716
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   717
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   718
void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   719
  switch (op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   720
    case OPR_AND: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   721
      luaK_goiftrue(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   722
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   723
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   724
    case OPR_OR: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   725
      luaK_goiffalse(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   726
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   727
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   728
    case OPR_CONCAT: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   729
      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   730
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   731
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   732
    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   733
    case OPR_MOD: case OPR_POW: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   734
      if (!isnumeral(v)) luaK_exp2RK(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   735
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   736
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   737
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   738
      luaK_exp2RK(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   739
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   740
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   741
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   742
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   743
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   744
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   745
void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   746
  switch (op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   747
    case OPR_AND: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   748
      lua_assert(e1->t == NO_JUMP);  /* list must be closed */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   749
      luaK_dischargevars(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   750
      luaK_concat(fs, &e2->f, e1->f);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   751
      *e1 = *e2;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   752
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   753
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   754
    case OPR_OR: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   755
      lua_assert(e1->f == NO_JUMP);  /* list must be closed */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   756
      luaK_dischargevars(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   757
      luaK_concat(fs, &e2->t, e1->t);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   758
      *e1 = *e2;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   759
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   760
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   761
    case OPR_CONCAT: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   762
      luaK_exp2val(fs, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   763
      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   764
        lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   765
        freeexp(fs, e1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   766
        SETARG_B(getcode(fs, e2), e1->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   767
        e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   768
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   769
      else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   770
        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   771
        codearith(fs, OP_CONCAT, e1, e2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   772
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   773
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   774
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   775
    case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   776
    case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   777
    case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   778
    case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   779
    case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   780
    case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   781
    case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   782
    case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   783
    case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   784
    case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   785
    case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   786
    case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   787
    default: lua_assert(0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   788
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   789
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   790
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   791
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   792
void luaK_fixline (FuncState *fs, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   793
  fs->f->lineinfo[fs->pc - 1] = line;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   794
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   795
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   796
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   797
static int luaK_code (FuncState *fs, Instruction i, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   798
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   799
  dischargejpc(fs);  /* `pc' will change */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   800
  /* put new instruction in code array */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   801
  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   802
                  MAX_INT, "code size overflow");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   803
  f->code[fs->pc] = i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   804
  /* save corresponding line information */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   805
  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   806
                  MAX_INT, "code size overflow");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   807
  f->lineinfo[fs->pc] = line;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   808
  return fs->pc++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   809
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   810
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   811
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   812
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   813
  lua_assert(getOpMode(o) == iABC);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   814
  lua_assert(getBMode(o) != OpArgN || b == 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   815
  lua_assert(getCMode(o) != OpArgN || c == 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   816
  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   817
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   818
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   819
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   820
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   821
  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   822
  lua_assert(getCMode(o) == OpArgN);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   823
  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   824
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   825
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   826
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   827
void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   828
  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   829
  int b = (tostore == LUA_MULTRET) ? 0 : tostore;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   830
  lua_assert(tostore != 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   831
  if (c <= MAXARG_C)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   832
    luaK_codeABC(fs, OP_SETLIST, base, b, c);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   833
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   834
    luaK_codeABC(fs, OP_SETLIST, base, b, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   835
    luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   836
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   837
  fs->freereg = base + 1;  /* free registers with list values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   838
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   839