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 */ }
void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { FuncState *fs = ls->fs; if (!discharge(fs, v)) { /* `v' is an expression? */ OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { /* expression has no jumps */ if (onlyone) luaK_setcallreturns(fs, 1); /* call must return 1 value */ } else { /* expression has jumps */ int final; /* position after whole expression */ int j = NO_JUMP; /* eventual jump over values */ int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) || need_value(fs, v->u.l.t, OP_JMPONT)) { /* expression needs values */ if (ISJUMP(previous)) luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ else { j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ /* correct stack for compiler and symbolic execution */ luaK_adjuststack(fs, 1); } p_nil = code_label(fs, OP_PUSHNILJMP, 0); p_1 = code_label(fs, OP_PUSHINT, 1); luaK_patchlist(fs, j, luaK_getlabel(fs)); } final = luaK_getlabel(fs); luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); v->u.l.f = v->u.l.t = NO_JUMP; }
static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { int prevpos; /* position of last instruction */ Instruction *previous; int *golist, *exitlist; if (!invert) { golist = &v->u.l.f; /* go if false */ exitlist = &v->u.l.t; /* exit if true */ } else { golist = &v->u.l.t; /* go if true */ exitlist = &v->u.l.f; /* exit if false */ } discharge1(fs, v); prevpos = fs->pc-1; previous = &fs->f->code[prevpos]; LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here"); if (!ISJUMP(GET_OPCODE(*previous))) prevpos = luaK_code1(fs, jump, NO_JUMP); else { /* last instruction is already a jump */ if (invert) SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); } luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ luaK_patchlist(fs, *golist, luaK_getlabel(fs)); *golist = NO_JUMP; }
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); }
static void closegoto(LexState *ls, int g, Labeldesc *label) { int i; FuncState *fs = ls->fs; Labellist *gl = &ls->dyd->gt; Labeldesc *gt = &gl->arr[g]; lua_assert(luaS_eqstr(gt->name, label->name)); if (gt->nactvar < label->nactvar) { TString *vname = getlocvar(fs, gt->nactvar)->varname; const char *msg = luaO_pushfstring(ls->L, "<goto %s> at line %d jumps into the scope of local " LUA_QS, getstr(gt->name), gt->line, getstr(vname)); semerror(ls, msg); } luaK_patchlist(fs, gt->pc, label->pc); /* remove goto from pending list */ for (i = g; i < gl->n - 1; i++) gl->arr[i] = gl->arr[i + 1]; gl->n--; }
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); luaK_patchlist(fs, bl.continuelist, whileinit); /* continue goes to start, too */ check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ }
/* ** returns current `pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). ** discharge list of jumps to last target. */ int luaK_getlabel (FuncState *fs) { if (fs->pc != fs->lasttarget) { int lasttarget = fs->lasttarget; fs->lasttarget = fs->pc; luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ } return fs->pc; }
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 */ }
static void repeatstat (LexState *ls, int line) { /* repeatstat -> REPEAT block UNTIL cond */ FuncState *fs = ls->fs; int repeat_init = luaK_getlabel(fs); expdesc v; BlockCnt bl; enterblock(fs, &bl, 1); next(ls); block(ls); check_match(ls, TK_UNTIL, TK_REPEAT, line); cond(ls, &v); luaK_patchlist(fs, v.f, repeat_init); leaveblock(fs); }
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); }
static void whilestat (LexState *ls, int line) { /* whilestat -> WHILE cond DO block END */ FuncState *fs = ls->fs; int whileinit; int condexit; BlockCnt *pbl = (BlockCnt*)malloc(sizeof(BlockCnt)); luaX_next(ls); /* skip WHILE */ whileinit = luaK_getlabel(fs); condexit = cond(ls); enterblock(fs, pbl, 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 */ free(pbl); }
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 */ }
void FuncState::luaK_jumpto(int t) { luaK_patchlist(luaK_jump(), t); }