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 parlist (LexState *ls) { /* parlist -> [ param { `,' param } ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; f->is_vararg = 0; if (ls->t.token != ')') { /* is `parlist' not empty? */ do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ new_localvar(ls, str_checkname(ls), nparams++); break; } case TK_DOTS: { /* param -> `...' */ luaX_next(ls); #if defined(LUA_COMPAT_VARARG) /* use `arg' as default name */ new_localvarliteral(ls, "arg", nparams++); f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; #endif f->is_vararg |= VARARG_ISVARARG; break; } default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); } } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ }
static void body (LexState *ls, expdesc *e, int needself, int line) { /* body -> `(' parlist `)' chunk END */ FuncState new_fs; open_func(ls, &new_fs); try { new_fs.f->linedefined = line; checknext(ls, '('); if (needself) { new_localvarliteral(ls, "self", 0); adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ')'); chunk(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); } catch( ... ) { close_func(ls); // We do not need the proto anymore. new_fs.f->DereferenceGC( ls->L ); throw; } close_func(ls); pushclosure(ls, &new_fs, e); // Terminate the FuncState again. new_fs.f->DereferenceGC( ls->L ); }
static void localstat (LexState *ls) { /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ int nvars = 0; int nexps; expdesc e; do { new_localvar(ls, str_checkname(ls), nvars++); } while (testnext(ls, ',')); if (testnext(ls, '=')) { nexps = explist1(ls, &e); } else { e.k = VVOID; nexps = 0; } adjust_assign(ls, nvars, nexps, &e); adjustlocalvars(ls, nvars); }
static void localfunc (LexState *ls) { expdesc v, b; new_localvar(ls, str_checkname(ls), 0); init_exp(&v, VLOCAL, ls->fs->freereg++); adjustlocalvars(ls, 1); body(ls, &b, 0, ls->linenumber); luaK_storevar(ls->fs, &v, &b); }
static void localstat (LexState *ls) { /* stat -> LOCAL NAME {`,' NAME} [ IN primaryexp | `=' explist1] */ int nvars = 0; int nexps; expdesc e; do { new_localvar(ls, str_checkname(ls), nvars++); } while (testnext(ls, ',')); if (testnext(ls, TK_IN)) { lu_byte from_var; int regs = ls->fs->freereg; int vars = ls->fs->nactvar; luaK_reserveregs(ls->fs, nvars); adjustlocalvars(ls, nvars); new_localvarliteral(ls, "(from)", 0); primaryexp(ls, &e); luaK_exp2nextreg(ls->fs, &e); from_var = ls->fs->nactvar; adjustlocalvars(ls, 1); luaK_setoneret(ls->fs, &e); /* close last expression */ for (nexps=0; nexps<nvars; nexps++) { expdesc v, key; init_exp(&e, VNONRELOC, ls->fs->freereg-1); codestring(ls, &key, getlocvar(ls->fs, vars+nexps).varname); luaK_indexed(ls->fs, &e, &key); init_exp(&v, VLOCAL, regs+nexps); luaK_storevar(ls->fs, &v, &e); } removevars(ls, from_var); return; } if (testnext(ls, '=')) nexps = explist1(ls, &e); else { e.k = VVOID; nexps = 0; } adjust_assign(ls, nvars, nexps, &e); adjustlocalvars(ls, nvars); }
static void code_params (LexState *ls, int nparams, int dots) { FuncState *fs = ls->fs; adjustlocalvars(ls, nparams); luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters"); fs->f->numparams = cast(lu_byte, fs->nactvar); fs->f->is_vararg = cast(lu_byte, dots); if (dots) create_local(ls, "arg"); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ }
static void localfunc (LexState *ls) { expdesc v, b; FuncState *fs = ls->fs; new_localvar(ls, str_checkname(ls), 0); init_exp(&v, VLOCAL, fs->freereg); luaK_reserveregs(fs, 1); adjustlocalvars(ls, 1); body(ls, &b, 0, ls->linenumber); luaK_storevar(fs, &v, &b); /* debug information will only see the variable after this point! */ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; }
static int assignment (LexState *ls, struct LHS_assign *lh, int nvars, lu_byte *from_var) { expdesc e; int from = 0; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); from = assignment(ls, &nv, nvars+1, from_var); } else { /* assignment -> IN primaryexp | `=' explist1 */ int nexps; if (testnext(ls, TK_IN)) { new_localvarliteral(ls, "(from)", 0); primaryexp(ls, &e); luaK_exp2nextreg(ls->fs, &e); *from_var = ls->fs->nactvar; adjustlocalvars(ls, 1); luaK_setoneret(ls->fs, &e); /* close last expression */ getfrom(ls, &e, &lh->v); luaK_storevar(ls->fs, &lh->v, &e); return 1; /* avoid default */ } else { checknext(ls, '='); nexps = explist1(ls, &e); } if (nexps == nvars) { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return 0; /* avoid default */ } else { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ if (from) getfrom(ls, &e, &lh->v); luaK_storevar(ls->fs, &lh->v, &e); return from; }
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 body (LexState *ls, expdesc *e, int needself, int line) { /* body -> `(' parlist `)' chunk END */ #ifdef LUA_UTILITIES_NET char szFuncName1[256]; char szFuncName2[256]; #endif FuncState new_fs; open_func(ls, &new_fs); new_fs.f->linedefined = line; #ifdef LUA_UTILITIES_NET szFuncName1[0] = 0; szFuncName2[0] = 0; TryGetFunctionName(ls->t.seminfo.ts, szFuncName1, 256); #endif checknext(ls, '('); if (needself) { new_localvarliteral(ls, "self", 0); adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ')'); chunk(ls); #ifdef LUA_UTILITIES_NET if (szFuncName1[0] == 0) TryGetFunctionName(ls->t.seminfo.ts, szFuncName2, 256); #endif new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); close_func(ls); #ifdef LUA_UTILITIES_NET // Use the correct function name based on values obtained if (szFuncName1[0] == 0) GetFunction(szFuncName2, ls, new_fs.f); else GetFunction(szFuncName1, ls, new_fs.f); #endif pushclosure(ls, &new_fs, e); }
static void body (LexState *ls, expdesc *e, int needself, int line) { /* body -> `(' parlist `)' chunk END */ FuncState new_fs; open_func(ls, &new_fs); new_fs.f->linedefined = line; checknext(ls, '('); if (needself) { new_localvarliteral(ls, "self", 0); adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ')'); chunk(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); close_func(ls); pushclosure(ls, &new_fs, e); }
static void create_local (LexState *ls, const char *name) { new_localvarstr(ls, name, 0); adjustlocalvars(ls, 1); }
static void constructor (LexState *ls, expdesc *t) { /* constructor -> ?? */ FuncState *fs = ls->fs; int line = ls->linenumber; int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); struct ConsControl cc; cc.na = cc.nh = cc.tostore = 0; cc.t = t; init_exp(t, VRELOCABLE, pc); init_exp(&cc.v, VVOID, 0); /* no value (yet) */ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ checknext(ls, '{'); #if LUA_OPTIONAL_COMMA for (;;) { #else do { #endif /* LUA_OPTIONAL_COMMA */ lua_assert(cc.v.k == VVOID || cc.tostore > 0); if (ls->t.token == '}') break; closelistfield(fs, &cc); switch(ls->t.token) { case TK_NAME: { /* may be listfields or recfields */ luaX_lookahead(ls); if (ls->lookahead.token != '=') /* expression? */ listfield(ls, &cc); else recfield(ls, &cc); break; } case '[': { /* constructor_item -> recfield */ recfield(ls, &cc); break; } default: { /* constructor_part -> listfield */ listfield(ls, &cc); break; } } #if LUA_OPTIONAL_COMMA if (ls->t.token == ',' || ls->t.token == ';') next(ls); else if (ls->t.token == '}') break; } #else } while (testnext(ls, ',') || testnext(ls, ';')); #endif /* LUA_OPTIONAL_COMMA */ check_match(ls, '}', '{', line); lastlistfield(fs, &cc); SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ } /* }====================================================================== */ static void parlist (LexState *ls) { /* parlist -> [ param { `,' param } ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; f->is_vararg = 0; if (ls->t.token != ')') { /* is `parlist' not empty? */ do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ new_localvar(ls, str_checkname(ls), nparams++); break; } case TK_DOTS: { /* param -> `...' */ luaX_next(ls); #if defined(LUA_COMPAT_VARARG) /* use `arg' as default name */ new_localvarliteral(ls, "arg", nparams++); f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; #endif f->is_vararg |= VARARG_ISVARARG; break; } default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); } } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ }
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); }