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 */ }
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); }
static void forstat (LexState *ls, int line) { /* forstat -> FOR (fornum | forlist) END */ FuncState *fs = GetCurrentFuncState( ls ); TString *varname; BlockCnt bl; enterblock(fs, &bl, 1); /* scope for loop and control variables */ luaX_next(ls); /* skip `for' */ varname = str_checkname(ls); /* first variable name */ switch (ls->t.token) { case '=': fornum(ls, varname, line); break; case ',': case TK_IN: forlist(ls, varname); break; default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); break; } check_match(ls, TK_END, TK_FOR, line); leaveblock(fs); /* loop scope (`break' jumps to this point) */ }
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 block (LexState *ls) { /* block -> chunk */ FuncState *fs = ls->fs; BlockCnt bl; enterblock(fs, &bl, 0); chunk(ls); lua_assert(bl.breaklist == NO_JUMP); leaveblock(fs); }
static void block (LexState *ls) { /* block -> chunk */ FuncState *fs = ls->fs; BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt)); enterblock(fs, pbl, 0); chunk(ls); lua_assert(pbl->breaklist == NO_JUMP); leaveblock(fs); luaM_free(ls->L,pbl); }
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 forstat (LexState *ls, int line) { /* forstat -> fornum | forlist */ FuncState *fs = ls->fs; TString *varname; BlockCnt bl; enterblock(fs, &bl, 0); /* block to control variable scope */ next(ls); /* skip `for' */ varname = str_checkname(ls); /* first variable name */ switch (ls->t.token) { case '=': fornum(ls, varname, line); break; case ',': case TK_IN: forlist(ls, varname); break; default: luaX_syntaxerror(ls, "`=' or `in' expected"); } check_match(ls, TK_END, TK_FOR, line); 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 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 */ }
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 */ }
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); }