Beispiel #1
0
static void ifstat(LexState* ls, int line)
{
	/* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
	FuncState* fs = ls->fs;
	int flist;
	int escapelist = NO_JUMP;
	flist = test_then_block(ls);	/* IF cond THEN block */
	while (ls->t.token == TK_ELSEIF)
	{
		luaK_concat(fs, &escapelist, luaK_jump(fs));
		luaK_patchtohere(fs, flist);
		flist = test_then_block(ls);  /* ELSEIF cond THEN block */
	}
	if (ls->t.token == TK_ELSE)
	{
		luaK_concat(fs, &escapelist, luaK_jump(fs));
		luaK_patchtohere(fs, flist);
		luaX_next(ls);	/* skip ELSE (after patch, for correct line info) */
		block(ls);	/* `else' part */
	}
	else
		luaK_concat(fs, &escapelist, flist);
	luaK_patchtohere(fs, escapelist);
	check_match(ls, TK_END, TK_IF, line);
}
Beispiel #2
0
static void selectstat (LexState *ls, int line) {
  /* selectstat -> CASE val1 OF val2 THEN block [OF valx THEN block [ELSE THEN block]] ESAC */
  FuncState *fs = ls->fs;
  BlockCnt bl;
  int escapelist = NO_JUMP;
  expdesc v;
  luaX_next(ls);  /* skip `case' */
  enterblock(fs, &bl, 0);  /* block to control variable scope */
  expr(ls, &v);
  checknext(ls, TK_OF);
  casestat(ls, &v);
  while (ls->t.token == TK_OF) {
    luaK_concat(fs, &escapelist, luaK_jump(fs));
    luaK_patchtohere(fs, v.f);
    luaX_next(ls);  /* skip OF */
    casestat(ls, &v);  /* OF val THEN block */
  }
  if (ls->t.token == TK_ELSE) {
    luaK_concat(fs, &escapelist, luaK_jump(fs));
    luaK_patchtohere(fs, v.f);
    luaX_next(ls);  /* skip ELSE */
    block(ls);  /* default part */
  } else {
    luaK_concat(fs, &escapelist, v.f);
  }
  luaK_patchtohere(fs, escapelist);
  check_match(ls, TK_ESAC, TK_CASE, line);
  leaveblock(fs);
}
Beispiel #3
0
static void forbody (LexState *ls, int base, int line, int nvars, int isnum)
{
    /* forbody -> DO block */
    BlockCnt bl;
    FuncState *fs = GetCurrentFuncState( ls );

    adjustlocalvars(ls, 3);  /* control variables */

    checknext(ls, TK_DO);

    int prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);

    enterblock(fs, &bl, 0);  /* scope for declared variables */

    adjustlocalvars(ls, nvars);
    luaK_reserveregs(fs, nvars);
    block(ls);

    leaveblock(fs);  /* end of scope for declared variables */

    luaK_patchtohere(fs, prep);

    int endfor = (isnum) ?
        luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);

    luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */

    luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
}
Beispiel #4
0
static void repeatstat(LexState* ls, int line)
{
	/* repeatstat -> REPEAT block UNTIL cond */
	int condexit;
	FuncState* fs = ls->fs;
	int repeat_init = luaK_getlabel(fs);
	BlockCnt bl1, bl2;
	enterblock(fs, &bl1, 1);  /* loop block */
	enterblock(fs, &bl2, 0);  /* scope block */
	luaX_next(ls);	/* skip REPEAT */
	chunk(ls);
	luaK_patchtohere(fs, bl1.continuelist);
	check_match(ls, TK_UNTIL, TK_REPEAT, line);
	condexit = cond(ls);	/* read condition (inside scope block) */
	if (!bl2.upval)	   /* no upvalues? */
	{
		leaveblock(fs);	 /* finish scope */
		luaK_patchlist(ls->fs, condexit, repeat_init);	/* close the loop */
	}
	else	/* complete semantics when there are upvalues */
	{
		breakstat(ls);	/* if condition then break */
		luaK_patchtohere(ls->fs, condexit);	 /* else... */
		leaveblock(fs);	 /* finish scope... */
		luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);	 /* and repeat */
	}
	leaveblock(fs);	 /* finish loop */
}
Beispiel #5
0
static void continuestat (LexState *ls) {
  /* stat -> CONTINUE [loop number] */
  FuncState *fs = ls->fs;
  BlockCnt *bl = fs->bl;
  BlockCnt *nextbl = NULL;
  int upval = 0, wasupval = 0;
  int levels = 1;
  next(ls);  /* skip CONTINUE */
  if (testnext(ls, TK_NUMBER)) {
    if (ls->t.seminfo.r != floor(ls->t.seminfo.r))
      luaX_syntaxerror(ls, "loop block number must be integer");
    levels = (int) ls->t.seminfo.r;
    if (levels < 1 || levels > LUA_MAXBREAKLEVEL)
      luaX_syntaxerror(ls, "loop block number out of range");
  }
  while (levels-- > 0) {
	wasupval = upval;
	while (bl && !bl->isbreakable) {
	  upval |= bl->upval;
      bl = bl->previous;
	}
    if (bl && levels > 0) {
  	  nextbl = bl;
    bl = bl->previous;
	}
  }
  if (!bl)
    luaX_syntaxerror(ls, "no loop to continue");
  if (wasupval)
    luaK_codeABC(fs, OP_CLOSE, nextbl->nactvar, 0, 0);
  luaK_concat(fs, &bl->continuelist, luaK_jump(fs));
}
Beispiel #6
0
static void leaveblock(FuncState *fs)
{
    BlockCnt *bl = fs->bl;
    LexState *ls = fs->ls;

    if (bl->previous && bl->upval)
    {
        /* create a 'jump to here' to close upvalues */
        int j = luaK_jump(fs);
        luaK_patchclose(fs, j, bl->nactvar);
        luaK_patchtohere(fs, j);
    }

    if (bl->isloop)
        breaklabel(ls); /* close pending breaks */

    fs->bl = bl->previous;
    removevars(fs, bl->nactvar);
    lua_assert(bl->nactvar == fs->nactvar);
    fs->freereg      = fs->nactvar; /* free registers */
    ls->dyd->label.n = bl->firstlabel; /* remove local labels */
    if (bl->previous) /* inner block? */
        movegotosout(fs, bl); /* update pending gotos to outer block */
    else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */
        undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */
}
Beispiel #7
0
static void breakstat (LexState *ls) {
  FuncState *fs = ls->fs;
  BlockCnt *bl = fs->bl;
  int upval = 0;
  while (bl && !bl->isbreakable) {
    upval |= bl->upval;
    bl = bl->previous;
  }
  if (!bl)
    luaX_syntaxerror(ls, "no loop to break");
  if (upval)
    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
}
Beispiel #8
0
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
  BlockCnt bl;
  FuncState *fs = ls->fs;
  int prep, endfor;
  adjustlocalvars(ls, nvars);  /* scope for all variables */
  check(ls, TK_DO);
  enterblock(fs, &bl, 1);  /* loop block */
  prep = luaK_getlabel(fs);
  block(ls);
  luaK_patchtohere(fs, prep-1);
  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */
  luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);
  leaveblock(fs);
}
Beispiel #9
0
static void whilestat (LexState *ls, int line) {
  /* whilestat -> WHILE cond DO block END */
  FuncState *fs = ls->fs;
  int whileinit;
  int condexit;
  BlockCnt bl;
  luaX_next(ls);  /* skip WHILE */
  whileinit = luaK_getlabel(fs);
  condexit = cond(ls);
  enterblock(fs, &bl, 1);
  checknext(ls, TK_DO);
  block(ls);
  luaK_patchlist(fs, luaK_jump(fs), whileinit);
  check_match(ls, TK_END, TK_WHILE, line);
  leaveblock(fs);
  luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */
}
Beispiel #10
0
/*
** Ensures final expression result (including results from its jump
** lists) is in register 'reg'.
** If expression has jumps, need to patch these jumps either to
** its final position or to "load" instructions (for those tests
** that do not produce values).
*/
static void exp2reg (FuncState *fs, expdesc *e, int reg) {
  discharge2reg(fs, e, reg);
  if (e->k == VJMP)  /* expression itself is a test? */
    luaK_concat(fs, &e->t, e->u.info);  /* put this jump in 't' list */
  if (hasjumps(e)) {
    int final;  /* position after whole expression */
    int p_f = NO_JUMP;  /* position of an eventual LOAD false */
    int p_t = NO_JUMP;  /* position of an eventual LOAD true */
    if (need_value(fs, e->t) || need_value(fs, e->f)) {
      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
      p_f = code_loadbool(fs, reg, 0, 1);
      p_t = code_loadbool(fs, reg, 1, 0);
      luaK_patchtohere(fs, fj);
    }
    final = luaK_getlabel(fs);
    patchlistaux(fs, e->f, final, reg, p_f);
    patchlistaux(fs, e->t, final, reg, p_t);
  }
Beispiel #11
0
static void breakstat (LexState *ls) {
  FuncState *fs = ls->fs;
  BlockCnt *bl = fs->bl;
  int upval = 0;
  while (bl && bl->isbreakable != 1) {
    if (bl->isbreakable == 2)
      luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0);
    else if (bl->isbreakable == 3)
      luaX_syntaxerror(ls, "can't break in 'finally' clause");
    upval |= bl->upval;
    bl = bl->previous;
  }
  if (!bl)
    luaX_syntaxerror(ls, "no loop to break");
  if (upval)
    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
}
Beispiel #12
0
/*static*/ void FuncState::exp2reg (/*FuncState *fs,*/ expdesc *e, int reg) {
	discharge2reg(e, reg);
	if (e->k == VJMP)
		luaK_concat(&e->t, e->u.info);  /* put this jump in 't' list */
	if (hasjumps(e)) {
		int final;  /* position after whole expression */
		int p_f = NO_JUMP;  /* position of an eventual LOAD false */
		int p_t = NO_JUMP;  /* position of an eventual LOAD true */
		if (need_value(e->t) || need_value(e->f)) {
			int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump();
			p_f = code_label(reg, 0, 1);
			p_t = code_label(reg, 1, 0);
			luaK_patchtohere(fj);
		}
		final = luaK_getlabel();
		patchlistaux(e->f, final, reg, p_f);
		patchlistaux(e->t, final, reg, p_t);
	}
Beispiel #13
0
static void exp2reg (FuncState *fs, expdesc *e, int reg) {
  discharge2reg(fs, e, reg);
  if (e->k == VJMP)
    luaK_concat(fs, &e->t, e->u.info);  /* put this jump in `t' list */
  if (hasjumps(e)) {
	if (e->k != VJMP)
	  luaK_goiftrue(fs, e);
    int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
    int p_f = code_label(fs, reg, 0, 1);
    luaK_patchtohere(fs, fj);
    int p_t = code_label(fs, reg, 1, 0);
    patchlistaux(fs, e->f, p_f);
    patchlistaux(fs, e->t, p_t);
  }
  e->f = e->t = NO_JUMP;
  e->u.info = reg;
  e->k = VNONRELOC;
}
Beispiel #14
0
static void whilestat (LexState *ls, int line) {
  /* whilestat -> WHILE cond DO block END */
  Instruction codeexp[MAXEXPWHILE + EXTRAEXP];
  int lineexp;
  int i;
  int sizeexp;
  FuncState *fs = ls->fs;
  int whileinit, blockinit, expinit;
  expdesc v;
  BlockCnt bl;
  next(ls);  /* skip WHILE */
  whileinit = luaK_jump(fs);  /* jump to condition (which will be moved) */
  expinit = luaK_getlabel(fs);
  expr(ls, &v);  /* parse condition */
  if (v.k == VK) v.k = VTRUE;  /* `trues' are all equal here */
  lineexp = ls->linenumber;
  luaK_goiffalse(fs, &v);
  luaK_concat(fs, &v.f, fs->jpc);
  fs->jpc = NO_JUMP;
  sizeexp = fs->pc - expinit;  /* size of expression code */
  if (sizeexp > MAXEXPWHILE) 
    luaX_syntaxerror(ls, "`while' condition too complex");
  for (i = 0; i < sizeexp; i++)  /* save `exp' code */
    codeexp[i] = fs->f->code[expinit + i];
  fs->pc = expinit;  /* remove `exp' code */
  enterblock(fs, &bl, 1);
  check(ls, TK_DO);
  blockinit = luaK_getlabel(fs);
  block(ls);
  luaK_patchtohere(fs, whileinit);  /* initial jump jumps to here */
  luaK_patchtohere(fs, bl.continuelist);
  /* move `exp' back to code */
  if (v.t != NO_JUMP) v.t += fs->pc - expinit;
  if (v.f != NO_JUMP) v.f += fs->pc - expinit;
  for (i=0; i<sizeexp; i++)
    luaK_code(fs, codeexp[i], lineexp);
  check_match(ls, TK_END, TK_WHILE, line);
  leaveblock(fs);
  luaK_patchlist(fs, v.t, blockinit);  /* true conditions go back to loop */
  luaK_patchtohere(fs, v.f);  /* false conditions finish the loop */
}
Beispiel #15
0
/*static*/ void FuncState::leaveblock (/*FuncState *fs*/) {
	//BlockCnt *bl = fs->bl;
	//LexState *ls = fs->ls;
	if (bl->previous && bl->upval) {
		/* create a 'jump to here' to close upvalues */
		int j = luaK_jump();
		luaK_patchclose(j, bl->nactvar);
		luaK_patchtohere(j);
	}
	if (bl->isloop)
		ls->breaklabel();  /* close pending breaks */
	bl = bl->previous;
	removevars(bl->nactvar);
	lua_assert(bl->nactvar == nactvar);
	free_reg = nactvar;  /* free registers */
	ls->dyd->label.n = bl->firstlabel;  /* remove local labels */
	if (bl->previous)  /* inner block? */
		movegotosout(bl);  /* update pending gotos to outer block */
	else if (bl->firstgoto < ls->dyd->gt.n)  /* pending gotos in outer block? */
		ls->undefgoto(&ls->dyd->gt.arr[bl->firstgoto]);  /* error */
}
Beispiel #16
0
static void fornum (LexState *ls, TString *varname, int line) {
  /* fornum -> NAME = exp1,exp1[,exp1] DO body */
  FuncState *fs = ls->fs;
  int base = fs->freereg;
  new_localvar(ls, varname, 0);
  new_localvarstr(ls, "(for limit)", 1);
  new_localvarstr(ls, "(for step)", 2);
  check(ls, '=');
  exp1(ls);  /* initial value */
  check(ls, ',');
  exp1(ls);  /* limit */
  if (testnext(ls, ','))
    exp1(ls);  /* optional step */
  else {  /* default step = 1 */
    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
    luaK_reserveregs(fs, 1);
  }
  luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
  luaK_jump(fs);
  forbody(ls, base, line, 3, 1);
}
Beispiel #17
0
static void repeatstat (LexState *ls, int line) {
  /* repeatstat -> REPEAT block UNTIL cond */
  int condexit;
  FuncState *fs = ls->fs;
  int repeat_init = luaK_getlabel(fs);
  BlockCnt bl1, bl2;
  enterblock(fs, &bl1, 1);  /* loop block */
  enterblock(fs, &bl2, 0);  /* scope block */
  luaX_next(ls);  /* skip REPEAT */
  chunk(ls);
  check_match(ls, TK_UNTIL, TK_REPEAT, line);
#if LUA_EXT_CONTINUE
  if (bl2.continuelist != NO_JUMP) {
    int oldprohibition = fs->prohibitedloc;
    luaK_patchtohere(fs, bl2.continuelist);
    fs->prohibitedloc = bl2.continuepos;
    condexit = cond(ls);  /* read condition (inside scope block) */
    fs->prohibitedloc = oldprohibition;
    bl2.continuelist = NO_JUMP;
  }
  else {
    condexit = cond(ls);  /* read condition (inside scope block) */
  }
#else
  condexit = cond(ls);  /* read condition (inside scope block) */
#endif /* LUA_EXT_CONTINUE */
  if (!bl2.upval) {  /* no upvalues? */
    leaveblock(fs);  /* finish scope */
    luaK_patchlist(ls->fs, condexit, repeat_init);  /* close the loop */
  }
  else {  /* complete semantics when there are upvalues */
    breakstat(ls);  /* if condition then break */
    luaK_patchtohere(ls->fs, condexit);  /* else... */
    leaveblock(fs);  /* finish scope... */
    luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);  /* and repeat */
  }
  leaveblock(fs);  /* finish loop */
}
Beispiel #18
0
static void breakstat (LexState *ls)
{
    FuncState *fs = GetCurrentFuncState( ls );
    BlockCnt *bl = (BlockCnt*)fs->blockList.GetFirst();
    int upval = 0;

    while (bl && !bl->isbreakable)
    {
        upval |= bl->upval;
        bl = (BlockCnt*)bl->next;
    }

    if (!bl)
    {
        luaX_syntaxerror(ls, "no loop to break");
    }

    if (upval)
    {
        luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
    }

    luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
}
Beispiel #19
0
static void continuestat (LexState *ls) {
  FuncState *fs = ls->fs;
  BlockCnt *bl = fs->bl;
  int continuepos = fs->nactvar;
  {
    BlockCnt *b2 = bl;
    if (b2)
    {
      b2 = b2->previous;
      while (b2 && !b2->isbreakable) {
        continuepos = bl->nactvar;
        bl = b2;
        b2 = b2->previous;
      }
    }
    if (!b2)
      luaX_syntaxerror(ls, "no loop to continue");
    /* b2 is a loop block, bl is the scope block just above it,
       continuepos is the nactvar of the scope above that */
  }
  if (bl->continuelist == NO_JUMP)
    bl->continuepos = continuepos;
  luaK_concat(fs, &bl->continuelist, luaK_jump(fs));
}
Beispiel #20
0
static int ICACHE_FLASH_ATTR condjump (FuncState *fs, OpCode op, int A, int B, int C) {
  luaK_codeABC(fs, op, A, B, C);
  return luaK_jump(fs);
}
Beispiel #21
0
/*
** Code a "conditional jump", that is, a test or comparison opcode
** followed by a jump. Return jump position.
*/
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
  luaK_codeABC(fs, op, A, B, C);
  return luaK_jump(fs);
}
Beispiel #22
0
/*static*/ int FuncState::condjump (/*FuncState *fs,*/ OpCode op, int A, int B, int C) {
	luaK_codeABC(op, A, B, C);
	return luaK_jump();
}
Beispiel #23
0
void FuncState::luaK_jumpto(int t)
{
	luaK_patchlist(luaK_jump(), t);
}
Beispiel #24
0
static void trystat (LexState *ls, int line) {
  /* trystat -> TRY block CATCH err DO block END */
  FuncState *fs = ls->fs;
  BlockCnt bl;
  int base, pc, escapelist = NO_JUMP;

  luaX_next(ls);

  enterblock(fs, &bl, 2);   /* try block */
  base = fs->freereg;
  new_localvarliteral(ls, "(error obj)", 0);
  adjustlocalvars(ls, 1);  /* error object */
  luaK_reserveregs(fs, 1);

  pc = luaK_codeAsBx(fs, OP_TRY, base, NO_JUMP);
  chunk(ls);

  if (ls->t.token == TK_CATCH) {
    TString *varname;
    int errobj;

    luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0);
    luaK_concat(fs, &escapelist, luaK_jump(fs));
    SET_OPCODE(fs->f->code[pc], OP_TRYCATCH);   /* change it to TRYCATCH */
    luaK_patchtohere(fs, pc);
    bl.isbreakable = 0;

    // local err
    luaX_next(ls);  /* skip `catch' */
    varname = str_checkname(ls);  /* first variable name */

    // do
    checknext(ls, TK_DO);
    errobj = fs->freereg;
    new_localvar(ls, varname, 0);
    adjustlocalvars(ls, 1);
    luaK_reserveregs(fs, 1);
    luaK_codeABC(fs, OP_MOVE, errobj, base, 0);

    block(ls);

  } else if (ls->t.token == TK_FINALLY) {
    luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0);
    luaK_concat(fs, &escapelist, luaK_jump(fs));
    SET_OPCODE(fs->f->code[pc], OP_TRYFIN);   /* change it to TRYFIN */
    luaK_patchtohere(fs, pc);
    bl.isbreakable = 3;

    luaX_next(ls);  /* skip 'finally' */

    block(ls);

    luaK_codeABC(fs, OP_RETFIN, base, 0, 0);  /* OP_ENDFIN jump to the return point */

  } else {
    luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0);
    luaK_concat(fs, &escapelist, pc);
  }

  leaveblock(fs);

  luaK_patchtohere(fs, escapelist);
  check_match(ls, TK_END, TK_TRY, line);
}