116a5fed65808adf648004b34f98718301d718fa2darylm/*
216a5fed65808adf648004b34f98718301d718fa2darylm** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $
316a5fed65808adf648004b34f98718301d718fa2darylm** Code generator for Lua
416a5fed65808adf648004b34f98718301d718fa2darylm** See Copyright Notice in lua.h
516a5fed65808adf648004b34f98718301d718fa2darylm*/
616a5fed65808adf648004b34f98718301d718fa2darylm
716a5fed65808adf648004b34f98718301d718fa2darylm
816a5fed65808adf648004b34f98718301d718fa2darylm#include <stdlib.h>
916a5fed65808adf648004b34f98718301d718fa2darylm
1016a5fed65808adf648004b34f98718301d718fa2darylm#define lcode_c
1116a5fed65808adf648004b34f98718301d718fa2darylm#define LUA_CORE
1216a5fed65808adf648004b34f98718301d718fa2darylm
1316a5fed65808adf648004b34f98718301d718fa2darylm#include "lua.h"
1416a5fed65808adf648004b34f98718301d718fa2darylm
1516a5fed65808adf648004b34f98718301d718fa2darylm#include "lcode.h"
1616a5fed65808adf648004b34f98718301d718fa2darylm#include "ldebug.h"
1716a5fed65808adf648004b34f98718301d718fa2darylm#include "ldo.h"
1816a5fed65808adf648004b34f98718301d718fa2darylm#include "lgc.h"
1916a5fed65808adf648004b34f98718301d718fa2darylm#include "llex.h"
2016a5fed65808adf648004b34f98718301d718fa2darylm#include "lmem.h"
2116a5fed65808adf648004b34f98718301d718fa2darylm#include "lobject.h"
2216a5fed65808adf648004b34f98718301d718fa2darylm#include "lopcodes.h"
2316a5fed65808adf648004b34f98718301d718fa2darylm#include "lparser.h"
2416a5fed65808adf648004b34f98718301d718fa2darylm#include "lstring.h"
2516a5fed65808adf648004b34f98718301d718fa2darylm#include "ltable.h"
2616a5fed65808adf648004b34f98718301d718fa2darylm#include "lvm.h"
2716a5fed65808adf648004b34f98718301d718fa2darylm
2816a5fed65808adf648004b34f98718301d718fa2darylm
2916a5fed65808adf648004b34f98718301d718fa2darylm#define hasjumps(e) ((e)->t != (e)->f)
3016a5fed65808adf648004b34f98718301d718fa2darylm
3116a5fed65808adf648004b34f98718301d718fa2darylm
3216a5fed65808adf648004b34f98718301d718fa2darylmstatic int isnumeral(expdesc *e) {
3316a5fed65808adf648004b34f98718301d718fa2darylm  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
3416a5fed65808adf648004b34f98718301d718fa2darylm}
3516a5fed65808adf648004b34f98718301d718fa2darylm
3616a5fed65808adf648004b34f98718301d718fa2darylm
3716a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_nil (FuncState *fs, int from, int n) {
3816a5fed65808adf648004b34f98718301d718fa2darylm  Instruction *previous;
3916a5fed65808adf648004b34f98718301d718fa2darylm  int l = from + n - 1;  /* last register to set nil */
4016a5fed65808adf648004b34f98718301d718fa2darylm  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
4116a5fed65808adf648004b34f98718301d718fa2darylm    previous = &fs->f->code[fs->pc-1];
4216a5fed65808adf648004b34f98718301d718fa2darylm    if (GET_OPCODE(*previous) == OP_LOADNIL) {
4316a5fed65808adf648004b34f98718301d718fa2darylm      int pfrom = GETARG_A(*previous);
4416a5fed65808adf648004b34f98718301d718fa2darylm      int pl = pfrom + GETARG_B(*previous);
4516a5fed65808adf648004b34f98718301d718fa2darylm      if ((pfrom <= from && from <= pl + 1) ||
4616a5fed65808adf648004b34f98718301d718fa2darylm          (from <= pfrom && pfrom <= l + 1)) {  /* can connect both? */
4716a5fed65808adf648004b34f98718301d718fa2darylm        if (pfrom < from) from = pfrom;  /* from = min(from, pfrom) */
4816a5fed65808adf648004b34f98718301d718fa2darylm        if (pl > l) l = pl;  /* l = max(l, pl) */
4916a5fed65808adf648004b34f98718301d718fa2darylm        SETARG_A(*previous, from);
5016a5fed65808adf648004b34f98718301d718fa2darylm        SETARG_B(*previous, l - from);
5116a5fed65808adf648004b34f98718301d718fa2darylm        return;
5216a5fed65808adf648004b34f98718301d718fa2darylm      }
5316a5fed65808adf648004b34f98718301d718fa2darylm    }  /* else go through */
5416a5fed65808adf648004b34f98718301d718fa2darylm  }
5516a5fed65808adf648004b34f98718301d718fa2darylm  luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0);  /* else no optimization */
5616a5fed65808adf648004b34f98718301d718fa2darylm}
5716a5fed65808adf648004b34f98718301d718fa2darylm
5816a5fed65808adf648004b34f98718301d718fa2darylm
5916a5fed65808adf648004b34f98718301d718fa2darylmint luaK_jump (FuncState *fs) {
6016a5fed65808adf648004b34f98718301d718fa2darylm  int jpc = fs->jpc;  /* save list of jumps to here */
6116a5fed65808adf648004b34f98718301d718fa2darylm  int j;
6216a5fed65808adf648004b34f98718301d718fa2darylm  fs->jpc = NO_JUMP;
6316a5fed65808adf648004b34f98718301d718fa2darylm  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
6416a5fed65808adf648004b34f98718301d718fa2darylm  luaK_concat(fs, &j, jpc);  /* keep them on hold */
6516a5fed65808adf648004b34f98718301d718fa2darylm  return j;
6616a5fed65808adf648004b34f98718301d718fa2darylm}
6716a5fed65808adf648004b34f98718301d718fa2darylm
6816a5fed65808adf648004b34f98718301d718fa2darylm
6916a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_ret (FuncState *fs, int first, int nret) {
7016a5fed65808adf648004b34f98718301d718fa2darylm  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
7116a5fed65808adf648004b34f98718301d718fa2darylm}
7216a5fed65808adf648004b34f98718301d718fa2darylm
7316a5fed65808adf648004b34f98718301d718fa2darylm
7416a5fed65808adf648004b34f98718301d718fa2darylmstatic int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
7516a5fed65808adf648004b34f98718301d718fa2darylm  luaK_codeABC(fs, op, A, B, C);
7616a5fed65808adf648004b34f98718301d718fa2darylm  return luaK_jump(fs);
7716a5fed65808adf648004b34f98718301d718fa2darylm}
7816a5fed65808adf648004b34f98718301d718fa2darylm
7916a5fed65808adf648004b34f98718301d718fa2darylm
8016a5fed65808adf648004b34f98718301d718fa2darylmstatic void fixjump (FuncState *fs, int pc, int dest) {
8116a5fed65808adf648004b34f98718301d718fa2darylm  Instruction *jmp = &fs->f->code[pc];
8216a5fed65808adf648004b34f98718301d718fa2darylm  int offset = dest-(pc+1);
8316a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(dest != NO_JUMP);
8416a5fed65808adf648004b34f98718301d718fa2darylm  if (abs(offset) > MAXARG_sBx)
8516a5fed65808adf648004b34f98718301d718fa2darylm    luaX_syntaxerror(fs->ls, "control structure too long");
8616a5fed65808adf648004b34f98718301d718fa2darylm  SETARG_sBx(*jmp, offset);
8716a5fed65808adf648004b34f98718301d718fa2darylm}
8816a5fed65808adf648004b34f98718301d718fa2darylm
8916a5fed65808adf648004b34f98718301d718fa2darylm
9016a5fed65808adf648004b34f98718301d718fa2darylm/*
9116a5fed65808adf648004b34f98718301d718fa2darylm** returns current `pc' and marks it as a jump target (to avoid wrong
9216a5fed65808adf648004b34f98718301d718fa2darylm** optimizations with consecutive instructions not in the same basic block).
9316a5fed65808adf648004b34f98718301d718fa2darylm*/
9416a5fed65808adf648004b34f98718301d718fa2darylmint luaK_getlabel (FuncState *fs) {
9516a5fed65808adf648004b34f98718301d718fa2darylm  fs->lasttarget = fs->pc;
9616a5fed65808adf648004b34f98718301d718fa2darylm  return fs->pc;
9716a5fed65808adf648004b34f98718301d718fa2darylm}
9816a5fed65808adf648004b34f98718301d718fa2darylm
9916a5fed65808adf648004b34f98718301d718fa2darylm
10016a5fed65808adf648004b34f98718301d718fa2darylmstatic int getjump (FuncState *fs, int pc) {
10116a5fed65808adf648004b34f98718301d718fa2darylm  int offset = GETARG_sBx(fs->f->code[pc]);
10216a5fed65808adf648004b34f98718301d718fa2darylm  if (offset == NO_JUMP)  /* point to itself represents end of list */
10316a5fed65808adf648004b34f98718301d718fa2darylm    return NO_JUMP;  /* end of list */
10416a5fed65808adf648004b34f98718301d718fa2darylm  else
10516a5fed65808adf648004b34f98718301d718fa2darylm    return (pc+1)+offset;  /* turn offset into absolute position */
10616a5fed65808adf648004b34f98718301d718fa2darylm}
10716a5fed65808adf648004b34f98718301d718fa2darylm
10816a5fed65808adf648004b34f98718301d718fa2darylm
10916a5fed65808adf648004b34f98718301d718fa2darylmstatic Instruction *getjumpcontrol (FuncState *fs, int pc) {
11016a5fed65808adf648004b34f98718301d718fa2darylm  Instruction *pi = &fs->f->code[pc];
11116a5fed65808adf648004b34f98718301d718fa2darylm  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
11216a5fed65808adf648004b34f98718301d718fa2darylm    return pi-1;
11316a5fed65808adf648004b34f98718301d718fa2darylm  else
11416a5fed65808adf648004b34f98718301d718fa2darylm    return pi;
11516a5fed65808adf648004b34f98718301d718fa2darylm}
11616a5fed65808adf648004b34f98718301d718fa2darylm
11716a5fed65808adf648004b34f98718301d718fa2darylm
11816a5fed65808adf648004b34f98718301d718fa2darylm/*
11916a5fed65808adf648004b34f98718301d718fa2darylm** check whether list has any jump that do not produce a value
12016a5fed65808adf648004b34f98718301d718fa2darylm** (or produce an inverted value)
12116a5fed65808adf648004b34f98718301d718fa2darylm*/
12216a5fed65808adf648004b34f98718301d718fa2darylmstatic int need_value (FuncState *fs, int list) {
12316a5fed65808adf648004b34f98718301d718fa2darylm  for (; list != NO_JUMP; list = getjump(fs, list)) {
12416a5fed65808adf648004b34f98718301d718fa2darylm    Instruction i = *getjumpcontrol(fs, list);
12516a5fed65808adf648004b34f98718301d718fa2darylm    if (GET_OPCODE(i) != OP_TESTSET) return 1;
12616a5fed65808adf648004b34f98718301d718fa2darylm  }
12716a5fed65808adf648004b34f98718301d718fa2darylm  return 0;  /* not found */
12816a5fed65808adf648004b34f98718301d718fa2darylm}
12916a5fed65808adf648004b34f98718301d718fa2darylm
13016a5fed65808adf648004b34f98718301d718fa2darylm
13116a5fed65808adf648004b34f98718301d718fa2darylmstatic int patchtestreg (FuncState *fs, int node, int reg) {
13216a5fed65808adf648004b34f98718301d718fa2darylm  Instruction *i = getjumpcontrol(fs, node);
13316a5fed65808adf648004b34f98718301d718fa2darylm  if (GET_OPCODE(*i) != OP_TESTSET)
13416a5fed65808adf648004b34f98718301d718fa2darylm    return 0;  /* cannot patch other instructions */
13516a5fed65808adf648004b34f98718301d718fa2darylm  if (reg != NO_REG && reg != GETARG_B(*i))
13616a5fed65808adf648004b34f98718301d718fa2darylm    SETARG_A(*i, reg);
13716a5fed65808adf648004b34f98718301d718fa2darylm  else  /* no register to put value or register already has the value */
13816a5fed65808adf648004b34f98718301d718fa2darylm    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
13916a5fed65808adf648004b34f98718301d718fa2darylm
14016a5fed65808adf648004b34f98718301d718fa2darylm  return 1;
14116a5fed65808adf648004b34f98718301d718fa2darylm}
14216a5fed65808adf648004b34f98718301d718fa2darylm
14316a5fed65808adf648004b34f98718301d718fa2darylm
14416a5fed65808adf648004b34f98718301d718fa2darylmstatic void removevalues (FuncState *fs, int list) {
14516a5fed65808adf648004b34f98718301d718fa2darylm  for (; list != NO_JUMP; list = getjump(fs, list))
14616a5fed65808adf648004b34f98718301d718fa2darylm      patchtestreg(fs, list, NO_REG);
14716a5fed65808adf648004b34f98718301d718fa2darylm}
14816a5fed65808adf648004b34f98718301d718fa2darylm
14916a5fed65808adf648004b34f98718301d718fa2darylm
15016a5fed65808adf648004b34f98718301d718fa2darylmstatic void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
15116a5fed65808adf648004b34f98718301d718fa2darylm                          int dtarget) {
15216a5fed65808adf648004b34f98718301d718fa2darylm  while (list != NO_JUMP) {
15316a5fed65808adf648004b34f98718301d718fa2darylm    int next = getjump(fs, list);
15416a5fed65808adf648004b34f98718301d718fa2darylm    if (patchtestreg(fs, list, reg))
15516a5fed65808adf648004b34f98718301d718fa2darylm      fixjump(fs, list, vtarget);
15616a5fed65808adf648004b34f98718301d718fa2darylm    else
15716a5fed65808adf648004b34f98718301d718fa2darylm      fixjump(fs, list, dtarget);  /* jump to default target */
15816a5fed65808adf648004b34f98718301d718fa2darylm    list = next;
15916a5fed65808adf648004b34f98718301d718fa2darylm  }
16016a5fed65808adf648004b34f98718301d718fa2darylm}
16116a5fed65808adf648004b34f98718301d718fa2darylm
16216a5fed65808adf648004b34f98718301d718fa2darylm
16316a5fed65808adf648004b34f98718301d718fa2darylmstatic void dischargejpc (FuncState *fs) {
16416a5fed65808adf648004b34f98718301d718fa2darylm  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
16516a5fed65808adf648004b34f98718301d718fa2darylm  fs->jpc = NO_JUMP;
16616a5fed65808adf648004b34f98718301d718fa2darylm}
16716a5fed65808adf648004b34f98718301d718fa2darylm
16816a5fed65808adf648004b34f98718301d718fa2darylm
16916a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_patchlist (FuncState *fs, int list, int target) {
17016a5fed65808adf648004b34f98718301d718fa2darylm  if (target == fs->pc)
17116a5fed65808adf648004b34f98718301d718fa2darylm    luaK_patchtohere(fs, list);
17216a5fed65808adf648004b34f98718301d718fa2darylm  else {
17316a5fed65808adf648004b34f98718301d718fa2darylm    lua_assert(target < fs->pc);
17416a5fed65808adf648004b34f98718301d718fa2darylm    patchlistaux(fs, list, target, NO_REG, target);
17516a5fed65808adf648004b34f98718301d718fa2darylm  }
17616a5fed65808adf648004b34f98718301d718fa2darylm}
17716a5fed65808adf648004b34f98718301d718fa2darylm
17816a5fed65808adf648004b34f98718301d718fa2darylm
17916a5fed65808adf648004b34f98718301d718fa2darylmLUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) {
18016a5fed65808adf648004b34f98718301d718fa2darylm  level++;  /* argument is +1 to reserve 0 as non-op */
18116a5fed65808adf648004b34f98718301d718fa2darylm  while (list != NO_JUMP) {
18216a5fed65808adf648004b34f98718301d718fa2darylm    int next = getjump(fs, list);
18316a5fed65808adf648004b34f98718301d718fa2darylm    lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
18416a5fed65808adf648004b34f98718301d718fa2darylm                (GETARG_A(fs->f->code[list]) == 0 ||
18516a5fed65808adf648004b34f98718301d718fa2darylm                 GETARG_A(fs->f->code[list]) >= level));
18616a5fed65808adf648004b34f98718301d718fa2darylm    SETARG_A(fs->f->code[list], level);
18716a5fed65808adf648004b34f98718301d718fa2darylm    list = next;
18816a5fed65808adf648004b34f98718301d718fa2darylm  }
18916a5fed65808adf648004b34f98718301d718fa2darylm}
19016a5fed65808adf648004b34f98718301d718fa2darylm
19116a5fed65808adf648004b34f98718301d718fa2darylm
19216a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_patchtohere (FuncState *fs, int list) {
19316a5fed65808adf648004b34f98718301d718fa2darylm  luaK_getlabel(fs);
19416a5fed65808adf648004b34f98718301d718fa2darylm  luaK_concat(fs, &fs->jpc, list);
19516a5fed65808adf648004b34f98718301d718fa2darylm}
19616a5fed65808adf648004b34f98718301d718fa2darylm
19716a5fed65808adf648004b34f98718301d718fa2darylm
19816a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_concat (FuncState *fs, int *l1, int l2) {
19916a5fed65808adf648004b34f98718301d718fa2darylm  if (l2 == NO_JUMP) return;
20016a5fed65808adf648004b34f98718301d718fa2darylm  else if (*l1 == NO_JUMP)
20116a5fed65808adf648004b34f98718301d718fa2darylm    *l1 = l2;
20216a5fed65808adf648004b34f98718301d718fa2darylm  else {
20316a5fed65808adf648004b34f98718301d718fa2darylm    int list = *l1;
20416a5fed65808adf648004b34f98718301d718fa2darylm    int next;
20516a5fed65808adf648004b34f98718301d718fa2darylm    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
20616a5fed65808adf648004b34f98718301d718fa2darylm      list = next;
20716a5fed65808adf648004b34f98718301d718fa2darylm    fixjump(fs, list, l2);
20816a5fed65808adf648004b34f98718301d718fa2darylm  }
20916a5fed65808adf648004b34f98718301d718fa2darylm}
21016a5fed65808adf648004b34f98718301d718fa2darylm
21116a5fed65808adf648004b34f98718301d718fa2darylm
21216a5fed65808adf648004b34f98718301d718fa2darylmstatic int luaK_code (FuncState *fs, Instruction i) {
21316a5fed65808adf648004b34f98718301d718fa2darylm  Proto *f = fs->f;
21416a5fed65808adf648004b34f98718301d718fa2darylm  dischargejpc(fs);  /* `pc' will change */
21516a5fed65808adf648004b34f98718301d718fa2darylm  /* put new instruction in code array */
21616a5fed65808adf648004b34f98718301d718fa2darylm  luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
21716a5fed65808adf648004b34f98718301d718fa2darylm                  MAX_INT, "opcodes");
21816a5fed65808adf648004b34f98718301d718fa2darylm  f->code[fs->pc] = i;
21916a5fed65808adf648004b34f98718301d718fa2darylm  /* save corresponding line information */
22016a5fed65808adf648004b34f98718301d718fa2darylm  luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
22116a5fed65808adf648004b34f98718301d718fa2darylm                  MAX_INT, "opcodes");
22216a5fed65808adf648004b34f98718301d718fa2darylm  f->lineinfo[fs->pc] = fs->ls->lastline;
22316a5fed65808adf648004b34f98718301d718fa2darylm  return fs->pc++;
22416a5fed65808adf648004b34f98718301d718fa2darylm}
22516a5fed65808adf648004b34f98718301d718fa2darylm
22616a5fed65808adf648004b34f98718301d718fa2darylm
22716a5fed65808adf648004b34f98718301d718fa2darylmint luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
22816a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(getOpMode(o) == iABC);
22916a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(getBMode(o) != OpArgN || b == 0);
23016a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(getCMode(o) != OpArgN || c == 0);
23116a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
23216a5fed65808adf648004b34f98718301d718fa2darylm  return luaK_code(fs, CREATE_ABC(o, a, b, c));
23316a5fed65808adf648004b34f98718301d718fa2darylm}
23416a5fed65808adf648004b34f98718301d718fa2darylm
23516a5fed65808adf648004b34f98718301d718fa2darylm
23616a5fed65808adf648004b34f98718301d718fa2darylmint luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
23716a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
23816a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(getCMode(o) == OpArgN);
23916a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
24016a5fed65808adf648004b34f98718301d718fa2darylm  return luaK_code(fs, CREATE_ABx(o, a, bc));
24116a5fed65808adf648004b34f98718301d718fa2darylm}
24216a5fed65808adf648004b34f98718301d718fa2darylm
24316a5fed65808adf648004b34f98718301d718fa2darylm
24416a5fed65808adf648004b34f98718301d718fa2darylmstatic int codeextraarg (FuncState *fs, int a) {
24516a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(a <= MAXARG_Ax);
24616a5fed65808adf648004b34f98718301d718fa2darylm  return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
24716a5fed65808adf648004b34f98718301d718fa2darylm}
24816a5fed65808adf648004b34f98718301d718fa2darylm
24916a5fed65808adf648004b34f98718301d718fa2darylm
25016a5fed65808adf648004b34f98718301d718fa2darylmint luaK_codek (FuncState *fs, int reg, int k) {
25116a5fed65808adf648004b34f98718301d718fa2darylm  if (k <= MAXARG_Bx)
25216a5fed65808adf648004b34f98718301d718fa2darylm    return luaK_codeABx(fs, OP_LOADK, reg, k);
25316a5fed65808adf648004b34f98718301d718fa2darylm  else {
25416a5fed65808adf648004b34f98718301d718fa2darylm    int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
25516a5fed65808adf648004b34f98718301d718fa2darylm    codeextraarg(fs, k);
25616a5fed65808adf648004b34f98718301d718fa2darylm    return p;
25716a5fed65808adf648004b34f98718301d718fa2darylm  }
25816a5fed65808adf648004b34f98718301d718fa2darylm}
25916a5fed65808adf648004b34f98718301d718fa2darylm
26016a5fed65808adf648004b34f98718301d718fa2darylm
26116a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_checkstack (FuncState *fs, int n) {
26216a5fed65808adf648004b34f98718301d718fa2darylm  int newstack = fs->freereg + n;
26316a5fed65808adf648004b34f98718301d718fa2darylm  if (newstack > fs->f->maxstacksize) {
26416a5fed65808adf648004b34f98718301d718fa2darylm    if (newstack >= MAXSTACK)
26516a5fed65808adf648004b34f98718301d718fa2darylm      luaX_syntaxerror(fs->ls, "function or expression too complex");
26616a5fed65808adf648004b34f98718301d718fa2darylm    fs->f->maxstacksize = cast_byte(newstack);
26716a5fed65808adf648004b34f98718301d718fa2darylm  }
26816a5fed65808adf648004b34f98718301d718fa2darylm}
26916a5fed65808adf648004b34f98718301d718fa2darylm
27016a5fed65808adf648004b34f98718301d718fa2darylm
27116a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_reserveregs (FuncState *fs, int n) {
27216a5fed65808adf648004b34f98718301d718fa2darylm  luaK_checkstack(fs, n);
27316a5fed65808adf648004b34f98718301d718fa2darylm  fs->freereg += (lu_byte)n;
27416a5fed65808adf648004b34f98718301d718fa2darylm}
27516a5fed65808adf648004b34f98718301d718fa2darylm
27616a5fed65808adf648004b34f98718301d718fa2darylm
27716a5fed65808adf648004b34f98718301d718fa2darylmstatic void freereg (FuncState *fs, int reg) {
27816a5fed65808adf648004b34f98718301d718fa2darylm  if (!ISK(reg) && reg >= fs->nactvar) {
27916a5fed65808adf648004b34f98718301d718fa2darylm    fs->freereg--;
28016a5fed65808adf648004b34f98718301d718fa2darylm    lua_assert(reg == fs->freereg);
28116a5fed65808adf648004b34f98718301d718fa2darylm  }
28216a5fed65808adf648004b34f98718301d718fa2darylm}
28316a5fed65808adf648004b34f98718301d718fa2darylm
28416a5fed65808adf648004b34f98718301d718fa2darylm
28516a5fed65808adf648004b34f98718301d718fa2darylmstatic void freeexp (FuncState *fs, expdesc *e) {
28616a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k == VNONRELOC)
28716a5fed65808adf648004b34f98718301d718fa2darylm    freereg(fs, e->u.info);
28816a5fed65808adf648004b34f98718301d718fa2darylm}
28916a5fed65808adf648004b34f98718301d718fa2darylm
29016a5fed65808adf648004b34f98718301d718fa2darylm
29116a5fed65808adf648004b34f98718301d718fa2darylmstatic int addk (FuncState *fs, TValue *key, TValue *v) {
29216a5fed65808adf648004b34f98718301d718fa2darylm  lua_State *L = fs->ls->L;
29316a5fed65808adf648004b34f98718301d718fa2darylm  TValue *idx = luaH_set(L, fs->h, key);
29416a5fed65808adf648004b34f98718301d718fa2darylm  Proto *f = fs->f;
29516a5fed65808adf648004b34f98718301d718fa2darylm  int k, oldsize;
29616a5fed65808adf648004b34f98718301d718fa2darylm  if (ttisnumber(idx)) {
29716a5fed65808adf648004b34f98718301d718fa2darylm    lua_Number n = nvalue(idx);
29816a5fed65808adf648004b34f98718301d718fa2darylm    lua_number2int(k, n);
29916a5fed65808adf648004b34f98718301d718fa2darylm    if (luaV_rawequalobj(&f->k[k], v))
30016a5fed65808adf648004b34f98718301d718fa2darylm      return k;
30116a5fed65808adf648004b34f98718301d718fa2darylm    /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0");
30216a5fed65808adf648004b34f98718301d718fa2darylm       go through and create a new entry for this value */
30316a5fed65808adf648004b34f98718301d718fa2darylm  }
30416a5fed65808adf648004b34f98718301d718fa2darylm  /* constant not found; create a new entry */
30516a5fed65808adf648004b34f98718301d718fa2darylm  oldsize = f->sizek;
30616a5fed65808adf648004b34f98718301d718fa2darylm  k = fs->nk;
30716a5fed65808adf648004b34f98718301d718fa2darylm  /* numerical value does not need GC barrier;
30816a5fed65808adf648004b34f98718301d718fa2darylm     table has no metatable, so it does not need to invalidate cache */
30916a5fed65808adf648004b34f98718301d718fa2darylm  setnvalue(idx, cast_num(k));
31016a5fed65808adf648004b34f98718301d718fa2darylm  luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
31116a5fed65808adf648004b34f98718301d718fa2darylm  while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
31216a5fed65808adf648004b34f98718301d718fa2darylm  setobj(L, &f->k[k], v);
31316a5fed65808adf648004b34f98718301d718fa2darylm  fs->nk++;
31416a5fed65808adf648004b34f98718301d718fa2darylm  luaC_barrier(L, f, v);
31516a5fed65808adf648004b34f98718301d718fa2darylm  return k;
31616a5fed65808adf648004b34f98718301d718fa2darylm}
31716a5fed65808adf648004b34f98718301d718fa2darylm
31816a5fed65808adf648004b34f98718301d718fa2darylm
31916a5fed65808adf648004b34f98718301d718fa2darylmint luaK_stringK (FuncState *fs, TString *s) {
32016a5fed65808adf648004b34f98718301d718fa2darylm  TValue o;
32116a5fed65808adf648004b34f98718301d718fa2darylm  setsvalue(fs->ls->L, &o, s);
32216a5fed65808adf648004b34f98718301d718fa2darylm  return addk(fs, &o, &o);
32316a5fed65808adf648004b34f98718301d718fa2darylm}
32416a5fed65808adf648004b34f98718301d718fa2darylm
32516a5fed65808adf648004b34f98718301d718fa2darylm
32616a5fed65808adf648004b34f98718301d718fa2darylmint luaK_numberK (FuncState *fs, lua_Number r) {
32716a5fed65808adf648004b34f98718301d718fa2darylm  int n;
32816a5fed65808adf648004b34f98718301d718fa2darylm  lua_State *L = fs->ls->L;
32916a5fed65808adf648004b34f98718301d718fa2darylm  TValue o;
33016a5fed65808adf648004b34f98718301d718fa2darylm  setnvalue(&o, r);
33116a5fed65808adf648004b34f98718301d718fa2darylm  if (r == 0 || luai_numisnan(NULL, r)) {  /* handle -0 and NaN */
33216a5fed65808adf648004b34f98718301d718fa2darylm    /* use raw representation as key to avoid numeric problems */
33316a5fed65808adf648004b34f98718301d718fa2darylm    setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r)));
33416a5fed65808adf648004b34f98718301d718fa2darylm    n = addk(fs, L->top - 1, &o);
33516a5fed65808adf648004b34f98718301d718fa2darylm    L->top--;
33616a5fed65808adf648004b34f98718301d718fa2darylm  }
33716a5fed65808adf648004b34f98718301d718fa2darylm  else
33816a5fed65808adf648004b34f98718301d718fa2darylm    n = addk(fs, &o, &o);  /* regular case */
33916a5fed65808adf648004b34f98718301d718fa2darylm  return n;
34016a5fed65808adf648004b34f98718301d718fa2darylm}
34116a5fed65808adf648004b34f98718301d718fa2darylm
34216a5fed65808adf648004b34f98718301d718fa2darylm
34316a5fed65808adf648004b34f98718301d718fa2darylmstatic int boolK (FuncState *fs, int b) {
34416a5fed65808adf648004b34f98718301d718fa2darylm  TValue o;
34516a5fed65808adf648004b34f98718301d718fa2darylm  setbvalue(&o, b);
34616a5fed65808adf648004b34f98718301d718fa2darylm  return addk(fs, &o, &o);
34716a5fed65808adf648004b34f98718301d718fa2darylm}
34816a5fed65808adf648004b34f98718301d718fa2darylm
34916a5fed65808adf648004b34f98718301d718fa2darylm
35016a5fed65808adf648004b34f98718301d718fa2darylmstatic int nilK (FuncState *fs) {
35116a5fed65808adf648004b34f98718301d718fa2darylm  TValue k, v;
35216a5fed65808adf648004b34f98718301d718fa2darylm  setnilvalue(&v);
35316a5fed65808adf648004b34f98718301d718fa2darylm  /* cannot use nil as key; instead use table itself to represent nil */
35416a5fed65808adf648004b34f98718301d718fa2darylm  sethvalue(fs->ls->L, &k, fs->h);
35516a5fed65808adf648004b34f98718301d718fa2darylm  return addk(fs, &k, &v);
35616a5fed65808adf648004b34f98718301d718fa2darylm}
35716a5fed65808adf648004b34f98718301d718fa2darylm
35816a5fed65808adf648004b34f98718301d718fa2darylm
35916a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
36016a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k == VCALL) {  /* expression is an open function call? */
36116a5fed65808adf648004b34f98718301d718fa2darylm    SETARG_C(getcode(fs, e), nresults+1);
36216a5fed65808adf648004b34f98718301d718fa2darylm  }
36316a5fed65808adf648004b34f98718301d718fa2darylm  else if (e->k == VVARARG) {
36416a5fed65808adf648004b34f98718301d718fa2darylm    SETARG_B(getcode(fs, e), nresults+1);
36516a5fed65808adf648004b34f98718301d718fa2darylm    SETARG_A(getcode(fs, e), fs->freereg);
36616a5fed65808adf648004b34f98718301d718fa2darylm    luaK_reserveregs(fs, 1);
36716a5fed65808adf648004b34f98718301d718fa2darylm  }
36816a5fed65808adf648004b34f98718301d718fa2darylm}
36916a5fed65808adf648004b34f98718301d718fa2darylm
37016a5fed65808adf648004b34f98718301d718fa2darylm
37116a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_setoneret (FuncState *fs, expdesc *e) {
37216a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k == VCALL) {  /* expression is an open function call? */
37316a5fed65808adf648004b34f98718301d718fa2darylm    e->k = VNONRELOC;
37416a5fed65808adf648004b34f98718301d718fa2darylm    e->u.info = GETARG_A(getcode(fs, e));
37516a5fed65808adf648004b34f98718301d718fa2darylm  }
37616a5fed65808adf648004b34f98718301d718fa2darylm  else if (e->k == VVARARG) {
37716a5fed65808adf648004b34f98718301d718fa2darylm    SETARG_B(getcode(fs, e), 2);
37816a5fed65808adf648004b34f98718301d718fa2darylm    e->k = VRELOCABLE;  /* can relocate its simple result */
37916a5fed65808adf648004b34f98718301d718fa2darylm  }
38016a5fed65808adf648004b34f98718301d718fa2darylm}
38116a5fed65808adf648004b34f98718301d718fa2darylm
38216a5fed65808adf648004b34f98718301d718fa2darylm
38316a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_dischargevars (FuncState *fs, expdesc *e) {
38416a5fed65808adf648004b34f98718301d718fa2darylm  switch (e->k) {
38516a5fed65808adf648004b34f98718301d718fa2darylm    case VLOCAL: {
38616a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VNONRELOC;
38716a5fed65808adf648004b34f98718301d718fa2darylm      break;
38816a5fed65808adf648004b34f98718301d718fa2darylm    }
38916a5fed65808adf648004b34f98718301d718fa2darylm    case VUPVAL: {
39016a5fed65808adf648004b34f98718301d718fa2darylm      e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
39116a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VRELOCABLE;
39216a5fed65808adf648004b34f98718301d718fa2darylm      break;
39316a5fed65808adf648004b34f98718301d718fa2darylm    }
39416a5fed65808adf648004b34f98718301d718fa2darylm    case VINDEXED: {
39516a5fed65808adf648004b34f98718301d718fa2darylm      OpCode op = OP_GETTABUP;  /* assume 't' is in an upvalue */
39616a5fed65808adf648004b34f98718301d718fa2darylm      freereg(fs, e->u.ind.idx);
39716a5fed65808adf648004b34f98718301d718fa2darylm      if (e->u.ind.vt == VLOCAL) {  /* 't' is in a register? */
39816a5fed65808adf648004b34f98718301d718fa2darylm        freereg(fs, e->u.ind.t);
39916a5fed65808adf648004b34f98718301d718fa2darylm        op = OP_GETTABLE;
40016a5fed65808adf648004b34f98718301d718fa2darylm      }
40116a5fed65808adf648004b34f98718301d718fa2darylm      e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
40216a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VRELOCABLE;
40316a5fed65808adf648004b34f98718301d718fa2darylm      break;
40416a5fed65808adf648004b34f98718301d718fa2darylm    }
40516a5fed65808adf648004b34f98718301d718fa2darylm    case VVARARG:
40616a5fed65808adf648004b34f98718301d718fa2darylm    case VCALL: {
40716a5fed65808adf648004b34f98718301d718fa2darylm      luaK_setoneret(fs, e);
40816a5fed65808adf648004b34f98718301d718fa2darylm      break;
40916a5fed65808adf648004b34f98718301d718fa2darylm    }
41016a5fed65808adf648004b34f98718301d718fa2darylm    default: break;  /* there is one value available (somewhere) */
41116a5fed65808adf648004b34f98718301d718fa2darylm  }
41216a5fed65808adf648004b34f98718301d718fa2darylm}
41316a5fed65808adf648004b34f98718301d718fa2darylm
41416a5fed65808adf648004b34f98718301d718fa2darylm
41516a5fed65808adf648004b34f98718301d718fa2darylmstatic int code_label (FuncState *fs, int A, int b, int jump) {
41616a5fed65808adf648004b34f98718301d718fa2darylm  luaK_getlabel(fs);  /* those instructions may be jump targets */
41716a5fed65808adf648004b34f98718301d718fa2darylm  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
41816a5fed65808adf648004b34f98718301d718fa2darylm}
41916a5fed65808adf648004b34f98718301d718fa2darylm
42016a5fed65808adf648004b34f98718301d718fa2darylm
42116a5fed65808adf648004b34f98718301d718fa2darylmstatic void discharge2reg (FuncState *fs, expdesc *e, int reg) {
42216a5fed65808adf648004b34f98718301d718fa2darylm  luaK_dischargevars(fs, e);
42316a5fed65808adf648004b34f98718301d718fa2darylm  switch (e->k) {
42416a5fed65808adf648004b34f98718301d718fa2darylm    case VNIL: {
42516a5fed65808adf648004b34f98718301d718fa2darylm      luaK_nil(fs, reg, 1);
42616a5fed65808adf648004b34f98718301d718fa2darylm      break;
42716a5fed65808adf648004b34f98718301d718fa2darylm    }
42816a5fed65808adf648004b34f98718301d718fa2darylm    case VFALSE: case VTRUE: {
42916a5fed65808adf648004b34f98718301d718fa2darylm      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
43016a5fed65808adf648004b34f98718301d718fa2darylm      break;
43116a5fed65808adf648004b34f98718301d718fa2darylm    }
43216a5fed65808adf648004b34f98718301d718fa2darylm    case VK: {
43316a5fed65808adf648004b34f98718301d718fa2darylm      luaK_codek(fs, reg, e->u.info);
43416a5fed65808adf648004b34f98718301d718fa2darylm      break;
43516a5fed65808adf648004b34f98718301d718fa2darylm    }
43616a5fed65808adf648004b34f98718301d718fa2darylm    case VKNUM: {
43716a5fed65808adf648004b34f98718301d718fa2darylm      luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval));
43816a5fed65808adf648004b34f98718301d718fa2darylm      break;
43916a5fed65808adf648004b34f98718301d718fa2darylm    }
44016a5fed65808adf648004b34f98718301d718fa2darylm    case VRELOCABLE: {
44116a5fed65808adf648004b34f98718301d718fa2darylm      Instruction *pc = &getcode(fs, e);
44216a5fed65808adf648004b34f98718301d718fa2darylm      SETARG_A(*pc, reg);
44316a5fed65808adf648004b34f98718301d718fa2darylm      break;
44416a5fed65808adf648004b34f98718301d718fa2darylm    }
44516a5fed65808adf648004b34f98718301d718fa2darylm    case VNONRELOC: {
44616a5fed65808adf648004b34f98718301d718fa2darylm      if (reg != e->u.info)
44716a5fed65808adf648004b34f98718301d718fa2darylm        luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
44816a5fed65808adf648004b34f98718301d718fa2darylm      break;
44916a5fed65808adf648004b34f98718301d718fa2darylm    }
45016a5fed65808adf648004b34f98718301d718fa2darylm    default: {
45116a5fed65808adf648004b34f98718301d718fa2darylm      lua_assert(e->k == VVOID || e->k == VJMP);
45216a5fed65808adf648004b34f98718301d718fa2darylm      return;  /* nothing to do... */
45316a5fed65808adf648004b34f98718301d718fa2darylm    }
45416a5fed65808adf648004b34f98718301d718fa2darylm  }
45516a5fed65808adf648004b34f98718301d718fa2darylm  e->u.info = reg;
45616a5fed65808adf648004b34f98718301d718fa2darylm  e->k = VNONRELOC;
45716a5fed65808adf648004b34f98718301d718fa2darylm}
45816a5fed65808adf648004b34f98718301d718fa2darylm
45916a5fed65808adf648004b34f98718301d718fa2darylm
46016a5fed65808adf648004b34f98718301d718fa2darylmstatic void discharge2anyreg (FuncState *fs, expdesc *e) {
46116a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k != VNONRELOC) {
46216a5fed65808adf648004b34f98718301d718fa2darylm    luaK_reserveregs(fs, 1);
46316a5fed65808adf648004b34f98718301d718fa2darylm    discharge2reg(fs, e, fs->freereg-1);
46416a5fed65808adf648004b34f98718301d718fa2darylm  }
46516a5fed65808adf648004b34f98718301d718fa2darylm}
46616a5fed65808adf648004b34f98718301d718fa2darylm
46716a5fed65808adf648004b34f98718301d718fa2darylm
46816a5fed65808adf648004b34f98718301d718fa2darylmstatic void exp2reg (FuncState *fs, expdesc *e, int reg) {
46916a5fed65808adf648004b34f98718301d718fa2darylm  discharge2reg(fs, e, reg);
47016a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k == VJMP)
47116a5fed65808adf648004b34f98718301d718fa2darylm    luaK_concat(fs, &e->t, e->u.info);  /* put this jump in `t' list */
47216a5fed65808adf648004b34f98718301d718fa2darylm  if (hasjumps(e)) {
47316a5fed65808adf648004b34f98718301d718fa2darylm    int final;  /* position after whole expression */
47416a5fed65808adf648004b34f98718301d718fa2darylm    int p_f = NO_JUMP;  /* position of an eventual LOAD false */
47516a5fed65808adf648004b34f98718301d718fa2darylm    int p_t = NO_JUMP;  /* position of an eventual LOAD true */
47616a5fed65808adf648004b34f98718301d718fa2darylm    if (need_value(fs, e->t) || need_value(fs, e->f)) {
47716a5fed65808adf648004b34f98718301d718fa2darylm      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
47816a5fed65808adf648004b34f98718301d718fa2darylm      p_f = code_label(fs, reg, 0, 1);
47916a5fed65808adf648004b34f98718301d718fa2darylm      p_t = code_label(fs, reg, 1, 0);
48016a5fed65808adf648004b34f98718301d718fa2darylm      luaK_patchtohere(fs, fj);
48116a5fed65808adf648004b34f98718301d718fa2darylm    }
48216a5fed65808adf648004b34f98718301d718fa2darylm    final = luaK_getlabel(fs);
48316a5fed65808adf648004b34f98718301d718fa2darylm    patchlistaux(fs, e->f, final, reg, p_f);
48416a5fed65808adf648004b34f98718301d718fa2darylm    patchlistaux(fs, e->t, final, reg, p_t);
48516a5fed65808adf648004b34f98718301d718fa2darylm  }
48616a5fed65808adf648004b34f98718301d718fa2darylm  e->f = e->t = NO_JUMP;
48716a5fed65808adf648004b34f98718301d718fa2darylm  e->u.info = reg;
48816a5fed65808adf648004b34f98718301d718fa2darylm  e->k = VNONRELOC;
48916a5fed65808adf648004b34f98718301d718fa2darylm}
49016a5fed65808adf648004b34f98718301d718fa2darylm
49116a5fed65808adf648004b34f98718301d718fa2darylm
49216a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_exp2nextreg (FuncState *fs, expdesc *e) {
49316a5fed65808adf648004b34f98718301d718fa2darylm  luaK_dischargevars(fs, e);
49416a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, e);
49516a5fed65808adf648004b34f98718301d718fa2darylm  luaK_reserveregs(fs, 1);
49616a5fed65808adf648004b34f98718301d718fa2darylm  exp2reg(fs, e, fs->freereg - 1);
49716a5fed65808adf648004b34f98718301d718fa2darylm}
49816a5fed65808adf648004b34f98718301d718fa2darylm
49916a5fed65808adf648004b34f98718301d718fa2darylm
50016a5fed65808adf648004b34f98718301d718fa2darylmint luaK_exp2anyreg (FuncState *fs, expdesc *e) {
50116a5fed65808adf648004b34f98718301d718fa2darylm  luaK_dischargevars(fs, e);
50216a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k == VNONRELOC) {
50316a5fed65808adf648004b34f98718301d718fa2darylm    if (!hasjumps(e)) return e->u.info;  /* exp is already in a register */
50416a5fed65808adf648004b34f98718301d718fa2darylm    if (e->u.info >= fs->nactvar) {  /* reg. is not a local? */
50516a5fed65808adf648004b34f98718301d718fa2darylm      exp2reg(fs, e, e->u.info);  /* put value on it */
50616a5fed65808adf648004b34f98718301d718fa2darylm      return e->u.info;
50716a5fed65808adf648004b34f98718301d718fa2darylm    }
50816a5fed65808adf648004b34f98718301d718fa2darylm  }
50916a5fed65808adf648004b34f98718301d718fa2darylm  luaK_exp2nextreg(fs, e);  /* default */
51016a5fed65808adf648004b34f98718301d718fa2darylm  return e->u.info;
51116a5fed65808adf648004b34f98718301d718fa2darylm}
51216a5fed65808adf648004b34f98718301d718fa2darylm
51316a5fed65808adf648004b34f98718301d718fa2darylm
51416a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_exp2anyregup (FuncState *fs, expdesc *e) {
51516a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k != VUPVAL || hasjumps(e))
51616a5fed65808adf648004b34f98718301d718fa2darylm    luaK_exp2anyreg(fs, e);
51716a5fed65808adf648004b34f98718301d718fa2darylm}
51816a5fed65808adf648004b34f98718301d718fa2darylm
51916a5fed65808adf648004b34f98718301d718fa2darylm
52016a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_exp2val (FuncState *fs, expdesc *e) {
52116a5fed65808adf648004b34f98718301d718fa2darylm  if (hasjumps(e))
52216a5fed65808adf648004b34f98718301d718fa2darylm    luaK_exp2anyreg(fs, e);
52316a5fed65808adf648004b34f98718301d718fa2darylm  else
52416a5fed65808adf648004b34f98718301d718fa2darylm    luaK_dischargevars(fs, e);
52516a5fed65808adf648004b34f98718301d718fa2darylm}
52616a5fed65808adf648004b34f98718301d718fa2darylm
52716a5fed65808adf648004b34f98718301d718fa2darylm
52816a5fed65808adf648004b34f98718301d718fa2darylmint luaK_exp2RK (FuncState *fs, expdesc *e) {
52916a5fed65808adf648004b34f98718301d718fa2darylm  luaK_exp2val(fs, e);
53016a5fed65808adf648004b34f98718301d718fa2darylm  switch (e->k) {
53116a5fed65808adf648004b34f98718301d718fa2darylm    case VTRUE:
53216a5fed65808adf648004b34f98718301d718fa2darylm    case VFALSE:
53316a5fed65808adf648004b34f98718301d718fa2darylm    case VNIL: {
53416a5fed65808adf648004b34f98718301d718fa2darylm      if (fs->nk <= MAXINDEXRK) {  /* constant fits in RK operand? */
53516a5fed65808adf648004b34f98718301d718fa2darylm        e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE));
53616a5fed65808adf648004b34f98718301d718fa2darylm        e->k = VK;
53716a5fed65808adf648004b34f98718301d718fa2darylm        return RKASK(e->u.info);
53816a5fed65808adf648004b34f98718301d718fa2darylm      }
53916a5fed65808adf648004b34f98718301d718fa2darylm      else break;
54016a5fed65808adf648004b34f98718301d718fa2darylm    }
54116a5fed65808adf648004b34f98718301d718fa2darylm    case VKNUM: {
54216a5fed65808adf648004b34f98718301d718fa2darylm      e->u.info = luaK_numberK(fs, e->u.nval);
54316a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VK;
54416a5fed65808adf648004b34f98718301d718fa2darylm      /* go through */
54516a5fed65808adf648004b34f98718301d718fa2darylm    }
54616a5fed65808adf648004b34f98718301d718fa2darylm    case VK: {
54716a5fed65808adf648004b34f98718301d718fa2darylm      if (e->u.info <= MAXINDEXRK)  /* constant fits in argC? */
54816a5fed65808adf648004b34f98718301d718fa2darylm        return RKASK(e->u.info);
54916a5fed65808adf648004b34f98718301d718fa2darylm      else break;
55016a5fed65808adf648004b34f98718301d718fa2darylm    }
55116a5fed65808adf648004b34f98718301d718fa2darylm    default: break;
55216a5fed65808adf648004b34f98718301d718fa2darylm  }
55316a5fed65808adf648004b34f98718301d718fa2darylm  /* not a constant in the right range: put it in a register */
55416a5fed65808adf648004b34f98718301d718fa2darylm  return luaK_exp2anyreg(fs, e);
55516a5fed65808adf648004b34f98718301d718fa2darylm}
55616a5fed65808adf648004b34f98718301d718fa2darylm
55716a5fed65808adf648004b34f98718301d718fa2darylm
55816a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
55916a5fed65808adf648004b34f98718301d718fa2darylm  switch (var->k) {
56016a5fed65808adf648004b34f98718301d718fa2darylm    case VLOCAL: {
56116a5fed65808adf648004b34f98718301d718fa2darylm      freeexp(fs, ex);
56216a5fed65808adf648004b34f98718301d718fa2darylm      exp2reg(fs, ex, var->u.info);
56316a5fed65808adf648004b34f98718301d718fa2darylm      return;
56416a5fed65808adf648004b34f98718301d718fa2darylm    }
56516a5fed65808adf648004b34f98718301d718fa2darylm    case VUPVAL: {
56616a5fed65808adf648004b34f98718301d718fa2darylm      int e = luaK_exp2anyreg(fs, ex);
56716a5fed65808adf648004b34f98718301d718fa2darylm      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
56816a5fed65808adf648004b34f98718301d718fa2darylm      break;
56916a5fed65808adf648004b34f98718301d718fa2darylm    }
57016a5fed65808adf648004b34f98718301d718fa2darylm    case VINDEXED: {
57116a5fed65808adf648004b34f98718301d718fa2darylm      OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
57216a5fed65808adf648004b34f98718301d718fa2darylm      int e = luaK_exp2RK(fs, ex);
57316a5fed65808adf648004b34f98718301d718fa2darylm      luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
57416a5fed65808adf648004b34f98718301d718fa2darylm      break;
57516a5fed65808adf648004b34f98718301d718fa2darylm    }
57616a5fed65808adf648004b34f98718301d718fa2darylm    default: {
57716a5fed65808adf648004b34f98718301d718fa2darylm      lua_assert(0);  /* invalid var kind to store */
57816a5fed65808adf648004b34f98718301d718fa2darylm      break;
57916a5fed65808adf648004b34f98718301d718fa2darylm    }
58016a5fed65808adf648004b34f98718301d718fa2darylm  }
58116a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, ex);
58216a5fed65808adf648004b34f98718301d718fa2darylm}
58316a5fed65808adf648004b34f98718301d718fa2darylm
58416a5fed65808adf648004b34f98718301d718fa2darylm
58516a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
58616a5fed65808adf648004b34f98718301d718fa2darylm  int ereg;
58716a5fed65808adf648004b34f98718301d718fa2darylm  luaK_exp2anyreg(fs, e);
58816a5fed65808adf648004b34f98718301d718fa2darylm  ereg = e->u.info;  /* register where 'e' was placed */
58916a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, e);
59016a5fed65808adf648004b34f98718301d718fa2darylm  e->u.info = fs->freereg;  /* base register for op_self */
59116a5fed65808adf648004b34f98718301d718fa2darylm  e->k = VNONRELOC;
59216a5fed65808adf648004b34f98718301d718fa2darylm  luaK_reserveregs(fs, 2);  /* function and 'self' produced by op_self */
59316a5fed65808adf648004b34f98718301d718fa2darylm  luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
59416a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, key);
59516a5fed65808adf648004b34f98718301d718fa2darylm}
59616a5fed65808adf648004b34f98718301d718fa2darylm
59716a5fed65808adf648004b34f98718301d718fa2darylm
59816a5fed65808adf648004b34f98718301d718fa2darylmstatic void invertjump (FuncState *fs, expdesc *e) {
59916a5fed65808adf648004b34f98718301d718fa2darylm  Instruction *pc = getjumpcontrol(fs, e->u.info);
60016a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
60116a5fed65808adf648004b34f98718301d718fa2darylm                                           GET_OPCODE(*pc) != OP_TEST);
60216a5fed65808adf648004b34f98718301d718fa2darylm  SETARG_A(*pc, !(GETARG_A(*pc)));
60316a5fed65808adf648004b34f98718301d718fa2darylm}
60416a5fed65808adf648004b34f98718301d718fa2darylm
60516a5fed65808adf648004b34f98718301d718fa2darylm
60616a5fed65808adf648004b34f98718301d718fa2darylmstatic int jumponcond (FuncState *fs, expdesc *e, int cond) {
60716a5fed65808adf648004b34f98718301d718fa2darylm  if (e->k == VRELOCABLE) {
60816a5fed65808adf648004b34f98718301d718fa2darylm    Instruction ie = getcode(fs, e);
60916a5fed65808adf648004b34f98718301d718fa2darylm    if (GET_OPCODE(ie) == OP_NOT) {
61016a5fed65808adf648004b34f98718301d718fa2darylm      fs->pc--;  /* remove previous OP_NOT */
61116a5fed65808adf648004b34f98718301d718fa2darylm      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
61216a5fed65808adf648004b34f98718301d718fa2darylm    }
61316a5fed65808adf648004b34f98718301d718fa2darylm    /* else go through */
61416a5fed65808adf648004b34f98718301d718fa2darylm  }
61516a5fed65808adf648004b34f98718301d718fa2darylm  discharge2anyreg(fs, e);
61616a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, e);
61716a5fed65808adf648004b34f98718301d718fa2darylm  return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond);
61816a5fed65808adf648004b34f98718301d718fa2darylm}
61916a5fed65808adf648004b34f98718301d718fa2darylm
62016a5fed65808adf648004b34f98718301d718fa2darylm
62116a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_goiftrue (FuncState *fs, expdesc *e) {
62216a5fed65808adf648004b34f98718301d718fa2darylm  int pc;  /* pc of last jump */
62316a5fed65808adf648004b34f98718301d718fa2darylm  luaK_dischargevars(fs, e);
62416a5fed65808adf648004b34f98718301d718fa2darylm  switch (e->k) {
62516a5fed65808adf648004b34f98718301d718fa2darylm    case VJMP: {
62616a5fed65808adf648004b34f98718301d718fa2darylm      invertjump(fs, e);
62716a5fed65808adf648004b34f98718301d718fa2darylm      pc = e->u.info;
62816a5fed65808adf648004b34f98718301d718fa2darylm      break;
62916a5fed65808adf648004b34f98718301d718fa2darylm    }
63016a5fed65808adf648004b34f98718301d718fa2darylm    case VK: case VKNUM: case VTRUE: {
63116a5fed65808adf648004b34f98718301d718fa2darylm      pc = NO_JUMP;  /* always true; do nothing */
63216a5fed65808adf648004b34f98718301d718fa2darylm      break;
63316a5fed65808adf648004b34f98718301d718fa2darylm    }
63416a5fed65808adf648004b34f98718301d718fa2darylm    default: {
63516a5fed65808adf648004b34f98718301d718fa2darylm      pc = jumponcond(fs, e, 0);
63616a5fed65808adf648004b34f98718301d718fa2darylm      break;
63716a5fed65808adf648004b34f98718301d718fa2darylm    }
63816a5fed65808adf648004b34f98718301d718fa2darylm  }
63916a5fed65808adf648004b34f98718301d718fa2darylm  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
64016a5fed65808adf648004b34f98718301d718fa2darylm  luaK_patchtohere(fs, e->t);
64116a5fed65808adf648004b34f98718301d718fa2darylm  e->t = NO_JUMP;
64216a5fed65808adf648004b34f98718301d718fa2darylm}
64316a5fed65808adf648004b34f98718301d718fa2darylm
64416a5fed65808adf648004b34f98718301d718fa2darylm
64516a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_goiffalse (FuncState *fs, expdesc *e) {
64616a5fed65808adf648004b34f98718301d718fa2darylm  int pc;  /* pc of last jump */
64716a5fed65808adf648004b34f98718301d718fa2darylm  luaK_dischargevars(fs, e);
64816a5fed65808adf648004b34f98718301d718fa2darylm  switch (e->k) {
64916a5fed65808adf648004b34f98718301d718fa2darylm    case VJMP: {
65016a5fed65808adf648004b34f98718301d718fa2darylm      pc = e->u.info;
65116a5fed65808adf648004b34f98718301d718fa2darylm      break;
65216a5fed65808adf648004b34f98718301d718fa2darylm    }
65316a5fed65808adf648004b34f98718301d718fa2darylm    case VNIL: case VFALSE: {
65416a5fed65808adf648004b34f98718301d718fa2darylm      pc = NO_JUMP;  /* always false; do nothing */
65516a5fed65808adf648004b34f98718301d718fa2darylm      break;
65616a5fed65808adf648004b34f98718301d718fa2darylm    }
65716a5fed65808adf648004b34f98718301d718fa2darylm    default: {
65816a5fed65808adf648004b34f98718301d718fa2darylm      pc = jumponcond(fs, e, 1);
65916a5fed65808adf648004b34f98718301d718fa2darylm      break;
66016a5fed65808adf648004b34f98718301d718fa2darylm    }
66116a5fed65808adf648004b34f98718301d718fa2darylm  }
66216a5fed65808adf648004b34f98718301d718fa2darylm  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
66316a5fed65808adf648004b34f98718301d718fa2darylm  luaK_patchtohere(fs, e->f);
66416a5fed65808adf648004b34f98718301d718fa2darylm  e->f = NO_JUMP;
66516a5fed65808adf648004b34f98718301d718fa2darylm}
66616a5fed65808adf648004b34f98718301d718fa2darylm
66716a5fed65808adf648004b34f98718301d718fa2darylm
66816a5fed65808adf648004b34f98718301d718fa2darylmstatic void codenot (FuncState *fs, expdesc *e) {
66916a5fed65808adf648004b34f98718301d718fa2darylm  luaK_dischargevars(fs, e);
67016a5fed65808adf648004b34f98718301d718fa2darylm  switch (e->k) {
67116a5fed65808adf648004b34f98718301d718fa2darylm    case VNIL: case VFALSE: {
67216a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VTRUE;
67316a5fed65808adf648004b34f98718301d718fa2darylm      break;
67416a5fed65808adf648004b34f98718301d718fa2darylm    }
67516a5fed65808adf648004b34f98718301d718fa2darylm    case VK: case VKNUM: case VTRUE: {
67616a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VFALSE;
67716a5fed65808adf648004b34f98718301d718fa2darylm      break;
67816a5fed65808adf648004b34f98718301d718fa2darylm    }
67916a5fed65808adf648004b34f98718301d718fa2darylm    case VJMP: {
68016a5fed65808adf648004b34f98718301d718fa2darylm      invertjump(fs, e);
68116a5fed65808adf648004b34f98718301d718fa2darylm      break;
68216a5fed65808adf648004b34f98718301d718fa2darylm    }
68316a5fed65808adf648004b34f98718301d718fa2darylm    case VRELOCABLE:
68416a5fed65808adf648004b34f98718301d718fa2darylm    case VNONRELOC: {
68516a5fed65808adf648004b34f98718301d718fa2darylm      discharge2anyreg(fs, e);
68616a5fed65808adf648004b34f98718301d718fa2darylm      freeexp(fs, e);
68716a5fed65808adf648004b34f98718301d718fa2darylm      e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
68816a5fed65808adf648004b34f98718301d718fa2darylm      e->k = VRELOCABLE;
68916a5fed65808adf648004b34f98718301d718fa2darylm      break;
69016a5fed65808adf648004b34f98718301d718fa2darylm    }
69116a5fed65808adf648004b34f98718301d718fa2darylm    default: {
69216a5fed65808adf648004b34f98718301d718fa2darylm      lua_assert(0);  /* cannot happen */
69316a5fed65808adf648004b34f98718301d718fa2darylm      break;
69416a5fed65808adf648004b34f98718301d718fa2darylm    }
69516a5fed65808adf648004b34f98718301d718fa2darylm  }
69616a5fed65808adf648004b34f98718301d718fa2darylm  /* interchange true and false lists */
69716a5fed65808adf648004b34f98718301d718fa2darylm  { int temp = e->f; e->f = e->t; e->t = temp; }
69816a5fed65808adf648004b34f98718301d718fa2darylm  removevalues(fs, e->f);
69916a5fed65808adf648004b34f98718301d718fa2darylm  removevalues(fs, e->t);
70016a5fed65808adf648004b34f98718301d718fa2darylm}
70116a5fed65808adf648004b34f98718301d718fa2darylm
70216a5fed65808adf648004b34f98718301d718fa2darylm
70316a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
70416a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(!hasjumps(t));
70516a5fed65808adf648004b34f98718301d718fa2darylm  t->u.ind.t = (lu_byte)t->u.info;
70616a5fed65808adf648004b34f98718301d718fa2darylm  t->u.ind.idx = (short)luaK_exp2RK(fs, k);
70716a5fed65808adf648004b34f98718301d718fa2darylm  t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
70816a5fed65808adf648004b34f98718301d718fa2darylm                                 : check_exp(vkisinreg(t->k), VLOCAL);
70916a5fed65808adf648004b34f98718301d718fa2darylm  t->k = VINDEXED;
71016a5fed65808adf648004b34f98718301d718fa2darylm}
71116a5fed65808adf648004b34f98718301d718fa2darylm
71216a5fed65808adf648004b34f98718301d718fa2darylm
71316a5fed65808adf648004b34f98718301d718fa2darylmstatic int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
71416a5fed65808adf648004b34f98718301d718fa2darylm  lua_Number r;
71516a5fed65808adf648004b34f98718301d718fa2darylm  if (!isnumeral(e1) || !isnumeral(e2)) return 0;
71616a5fed65808adf648004b34f98718301d718fa2darylm  if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0)
71716a5fed65808adf648004b34f98718301d718fa2darylm    return 0;  /* do not attempt to divide by 0 */
71816a5fed65808adf648004b34f98718301d718fa2darylm  r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval);
71916a5fed65808adf648004b34f98718301d718fa2darylm  e1->u.nval = r;
72016a5fed65808adf648004b34f98718301d718fa2darylm  return 1;
72116a5fed65808adf648004b34f98718301d718fa2darylm}
72216a5fed65808adf648004b34f98718301d718fa2darylm
72316a5fed65808adf648004b34f98718301d718fa2darylm
72416a5fed65808adf648004b34f98718301d718fa2darylmstatic void codearith (FuncState *fs, OpCode op,
72516a5fed65808adf648004b34f98718301d718fa2darylm                       expdesc *e1, expdesc *e2, int line) {
72616a5fed65808adf648004b34f98718301d718fa2darylm  if (constfolding(op, e1, e2))
72716a5fed65808adf648004b34f98718301d718fa2darylm    return;
72816a5fed65808adf648004b34f98718301d718fa2darylm  else {
72916a5fed65808adf648004b34f98718301d718fa2darylm    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
73016a5fed65808adf648004b34f98718301d718fa2darylm    int o1 = luaK_exp2RK(fs, e1);
73116a5fed65808adf648004b34f98718301d718fa2darylm    if (o1 > o2) {
73216a5fed65808adf648004b34f98718301d718fa2darylm      freeexp(fs, e1);
73316a5fed65808adf648004b34f98718301d718fa2darylm      freeexp(fs, e2);
73416a5fed65808adf648004b34f98718301d718fa2darylm    }
73516a5fed65808adf648004b34f98718301d718fa2darylm    else {
73616a5fed65808adf648004b34f98718301d718fa2darylm      freeexp(fs, e2);
73716a5fed65808adf648004b34f98718301d718fa2darylm      freeexp(fs, e1);
73816a5fed65808adf648004b34f98718301d718fa2darylm    }
73916a5fed65808adf648004b34f98718301d718fa2darylm    e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);
74016a5fed65808adf648004b34f98718301d718fa2darylm    e1->k = VRELOCABLE;
74116a5fed65808adf648004b34f98718301d718fa2darylm    luaK_fixline(fs, line);
74216a5fed65808adf648004b34f98718301d718fa2darylm  }
74316a5fed65808adf648004b34f98718301d718fa2darylm}
74416a5fed65808adf648004b34f98718301d718fa2darylm
74516a5fed65808adf648004b34f98718301d718fa2darylm
74616a5fed65808adf648004b34f98718301d718fa2darylmstatic void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
74716a5fed65808adf648004b34f98718301d718fa2darylm                                                          expdesc *e2) {
74816a5fed65808adf648004b34f98718301d718fa2darylm  int o1 = luaK_exp2RK(fs, e1);
74916a5fed65808adf648004b34f98718301d718fa2darylm  int o2 = luaK_exp2RK(fs, e2);
75016a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, e2);
75116a5fed65808adf648004b34f98718301d718fa2darylm  freeexp(fs, e1);
75216a5fed65808adf648004b34f98718301d718fa2darylm  if (cond == 0 && op != OP_EQ) {
75316a5fed65808adf648004b34f98718301d718fa2darylm    int temp;  /* exchange args to replace by `<' or `<=' */
75416a5fed65808adf648004b34f98718301d718fa2darylm    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
75516a5fed65808adf648004b34f98718301d718fa2darylm    cond = 1;
75616a5fed65808adf648004b34f98718301d718fa2darylm  }
75716a5fed65808adf648004b34f98718301d718fa2darylm  e1->u.info = condjump(fs, op, cond, o1, o2);
75816a5fed65808adf648004b34f98718301d718fa2darylm  e1->k = VJMP;
75916a5fed65808adf648004b34f98718301d718fa2darylm}
76016a5fed65808adf648004b34f98718301d718fa2darylm
76116a5fed65808adf648004b34f98718301d718fa2darylm
76216a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
76316a5fed65808adf648004b34f98718301d718fa2darylm  expdesc e2;
76416a5fed65808adf648004b34f98718301d718fa2darylm  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
76516a5fed65808adf648004b34f98718301d718fa2darylm  switch (op) {
76616a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_MINUS: {
76716a5fed65808adf648004b34f98718301d718fa2darylm      if (isnumeral(e))  /* minus constant? */
76816a5fed65808adf648004b34f98718301d718fa2darylm        e->u.nval = luai_numunm(NULL, e->u.nval);  /* fold it */
76916a5fed65808adf648004b34f98718301d718fa2darylm      else {
77016a5fed65808adf648004b34f98718301d718fa2darylm        luaK_exp2anyreg(fs, e);
77116a5fed65808adf648004b34f98718301d718fa2darylm        codearith(fs, OP_UNM, e, &e2, line);
77216a5fed65808adf648004b34f98718301d718fa2darylm      }
77316a5fed65808adf648004b34f98718301d718fa2darylm      break;
77416a5fed65808adf648004b34f98718301d718fa2darylm    }
77516a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_NOT: codenot(fs, e); break;
77616a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_LEN: {
77716a5fed65808adf648004b34f98718301d718fa2darylm      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */
77816a5fed65808adf648004b34f98718301d718fa2darylm      codearith(fs, OP_LEN, e, &e2, line);
77916a5fed65808adf648004b34f98718301d718fa2darylm      break;
78016a5fed65808adf648004b34f98718301d718fa2darylm    }
78116a5fed65808adf648004b34f98718301d718fa2darylm    default: lua_assert(0);
78216a5fed65808adf648004b34f98718301d718fa2darylm  }
78316a5fed65808adf648004b34f98718301d718fa2darylm}
78416a5fed65808adf648004b34f98718301d718fa2darylm
78516a5fed65808adf648004b34f98718301d718fa2darylm
78616a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
78716a5fed65808adf648004b34f98718301d718fa2darylm  switch (op) {
78816a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_AND: {
78916a5fed65808adf648004b34f98718301d718fa2darylm      luaK_goiftrue(fs, v);
79016a5fed65808adf648004b34f98718301d718fa2darylm      break;
79116a5fed65808adf648004b34f98718301d718fa2darylm    }
79216a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_OR: {
79316a5fed65808adf648004b34f98718301d718fa2darylm      luaK_goiffalse(fs, v);
79416a5fed65808adf648004b34f98718301d718fa2darylm      break;
79516a5fed65808adf648004b34f98718301d718fa2darylm    }
79616a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_CONCAT: {
79716a5fed65808adf648004b34f98718301d718fa2darylm      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */
79816a5fed65808adf648004b34f98718301d718fa2darylm      break;
79916a5fed65808adf648004b34f98718301d718fa2darylm    }
80016a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
80116a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_MOD: case OPR_POW: {
80216a5fed65808adf648004b34f98718301d718fa2darylm      if (!isnumeral(v)) luaK_exp2RK(fs, v);
80316a5fed65808adf648004b34f98718301d718fa2darylm      break;
80416a5fed65808adf648004b34f98718301d718fa2darylm    }
80516a5fed65808adf648004b34f98718301d718fa2darylm    default: {
80616a5fed65808adf648004b34f98718301d718fa2darylm      luaK_exp2RK(fs, v);
80716a5fed65808adf648004b34f98718301d718fa2darylm      break;
80816a5fed65808adf648004b34f98718301d718fa2darylm    }
80916a5fed65808adf648004b34f98718301d718fa2darylm  }
81016a5fed65808adf648004b34f98718301d718fa2darylm}
81116a5fed65808adf648004b34f98718301d718fa2darylm
81216a5fed65808adf648004b34f98718301d718fa2darylm
81316a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_posfix (FuncState *fs, BinOpr op,
81416a5fed65808adf648004b34f98718301d718fa2darylm                  expdesc *e1, expdesc *e2, int line) {
81516a5fed65808adf648004b34f98718301d718fa2darylm  switch (op) {
81616a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_AND: {
81716a5fed65808adf648004b34f98718301d718fa2darylm      lua_assert(e1->t == NO_JUMP);  /* list must be closed */
81816a5fed65808adf648004b34f98718301d718fa2darylm      luaK_dischargevars(fs, e2);
81916a5fed65808adf648004b34f98718301d718fa2darylm      luaK_concat(fs, &e2->f, e1->f);
82016a5fed65808adf648004b34f98718301d718fa2darylm      *e1 = *e2;
82116a5fed65808adf648004b34f98718301d718fa2darylm      break;
82216a5fed65808adf648004b34f98718301d718fa2darylm    }
82316a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_OR: {
82416a5fed65808adf648004b34f98718301d718fa2darylm      lua_assert(e1->f == NO_JUMP);  /* list must be closed */
82516a5fed65808adf648004b34f98718301d718fa2darylm      luaK_dischargevars(fs, e2);
82616a5fed65808adf648004b34f98718301d718fa2darylm      luaK_concat(fs, &e2->t, e1->t);
82716a5fed65808adf648004b34f98718301d718fa2darylm      *e1 = *e2;
82816a5fed65808adf648004b34f98718301d718fa2darylm      break;
82916a5fed65808adf648004b34f98718301d718fa2darylm    }
83016a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_CONCAT: {
83116a5fed65808adf648004b34f98718301d718fa2darylm      luaK_exp2val(fs, e2);
83216a5fed65808adf648004b34f98718301d718fa2darylm      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
83316a5fed65808adf648004b34f98718301d718fa2darylm        lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
83416a5fed65808adf648004b34f98718301d718fa2darylm        freeexp(fs, e1);
83516a5fed65808adf648004b34f98718301d718fa2darylm        SETARG_B(getcode(fs, e2), e1->u.info);
83616a5fed65808adf648004b34f98718301d718fa2darylm        e1->k = VRELOCABLE; e1->u.info = e2->u.info;
83716a5fed65808adf648004b34f98718301d718fa2darylm      }
83816a5fed65808adf648004b34f98718301d718fa2darylm      else {
83916a5fed65808adf648004b34f98718301d718fa2darylm        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
84016a5fed65808adf648004b34f98718301d718fa2darylm        codearith(fs, OP_CONCAT, e1, e2, line);
84116a5fed65808adf648004b34f98718301d718fa2darylm      }
84216a5fed65808adf648004b34f98718301d718fa2darylm      break;
84316a5fed65808adf648004b34f98718301d718fa2darylm    }
84416a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
84516a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_MOD: case OPR_POW: {
84616a5fed65808adf648004b34f98718301d718fa2darylm      codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
84716a5fed65808adf648004b34f98718301d718fa2darylm      break;
84816a5fed65808adf648004b34f98718301d718fa2darylm    }
84916a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_EQ: case OPR_LT: case OPR_LE: {
85016a5fed65808adf648004b34f98718301d718fa2darylm      codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
85116a5fed65808adf648004b34f98718301d718fa2darylm      break;
85216a5fed65808adf648004b34f98718301d718fa2darylm    }
85316a5fed65808adf648004b34f98718301d718fa2darylm    case OPR_NE: case OPR_GT: case OPR_GE: {
85416a5fed65808adf648004b34f98718301d718fa2darylm      codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
85516a5fed65808adf648004b34f98718301d718fa2darylm      break;
85616a5fed65808adf648004b34f98718301d718fa2darylm    }
85716a5fed65808adf648004b34f98718301d718fa2darylm    default: lua_assert(0);
85816a5fed65808adf648004b34f98718301d718fa2darylm  }
85916a5fed65808adf648004b34f98718301d718fa2darylm}
86016a5fed65808adf648004b34f98718301d718fa2darylm
86116a5fed65808adf648004b34f98718301d718fa2darylm
86216a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_fixline (FuncState *fs, int line) {
86316a5fed65808adf648004b34f98718301d718fa2darylm  fs->f->lineinfo[fs->pc - 1] = line;
86416a5fed65808adf648004b34f98718301d718fa2darylm}
86516a5fed65808adf648004b34f98718301d718fa2darylm
86616a5fed65808adf648004b34f98718301d718fa2darylm
86716a5fed65808adf648004b34f98718301d718fa2darylmvoid luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
86816a5fed65808adf648004b34f98718301d718fa2darylm  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
86916a5fed65808adf648004b34f98718301d718fa2darylm  int b = (tostore == LUA_MULTRET) ? 0 : tostore;
87016a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert(tostore != 0);
87116a5fed65808adf648004b34f98718301d718fa2darylm  if (c <= MAXARG_C)
87216a5fed65808adf648004b34f98718301d718fa2darylm    luaK_codeABC(fs, OP_SETLIST, base, b, c);
87316a5fed65808adf648004b34f98718301d718fa2darylm  else if (c <= MAXARG_Ax) {
87416a5fed65808adf648004b34f98718301d718fa2darylm    luaK_codeABC(fs, OP_SETLIST, base, b, 0);
87516a5fed65808adf648004b34f98718301d718fa2darylm    codeextraarg(fs, c);
87616a5fed65808adf648004b34f98718301d718fa2darylm  }
87716a5fed65808adf648004b34f98718301d718fa2darylm  else
87816a5fed65808adf648004b34f98718301d718fa2darylm    luaX_syntaxerror(fs->ls, "constructor too long");
87916a5fed65808adf648004b34f98718301d718fa2darylm  fs->freereg = (lu_byte)base + 1;  /* free registers with list values */
88016a5fed65808adf648004b34f98718301d718fa2darylm}
88116a5fed65808adf648004b34f98718301d718fa2darylm
882