From bd8b9c94b38ddaa3cd7324cbca98571633e03f91 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 8 Mar 2002 16:10:32 -0300 Subject: generic for (with any number of control variables) --- lparser.c | 84 +++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 40 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 67aa21ab..507bddfe 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ +** $Id: lparser.c,v 1.167 2002/02/14 21:46:58 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -247,12 +247,12 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { } -static void code_params (LexState *ls, int nparams, short dots) { +static void code_params (LexState *ls, int nparams, int dots) { FuncState *fs = ls->fs; adjustlocalvars(ls, nparams); luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); - fs->f->numparams = cast(short, fs->nactloc); /* `self' could be there already */ - fs->f->is_vararg = dots; + fs->f->numparams = cast(lu_byte, fs->nactloc); + fs->f->is_vararg = cast(lu_byte, dots); if (dots) { new_localvarstr(ls, "arg", 0); adjustlocalvars(ls, 1); @@ -271,7 +271,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { static void leavebreak (FuncState *fs, Breaklabel *bl) { fs->bl = bl->previous; - luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); + luaK_patchtohere(fs, bl->breaklist); lua_assert(bl->nactloc == fs->nactloc); } @@ -471,8 +471,11 @@ static void recfield (LexState *ls, struct ConsControl *cc) { FuncState *fs = ls->fs; int reg = ls->fs->freereg; expdesc key, val; - if (ls->t.token == TK_NAME) + if (ls->t.token == TK_NAME) { + luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); + cc->nh++; checkname(ls, &key); + } else /* ls->t.token == '[' */ luaY_index(ls, &key); check(ls, '='); @@ -481,8 +484,6 @@ static void recfield (LexState *ls, struct ConsControl *cc) { luaK_exp2anyreg(fs, &val); luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key)); fs->freereg = reg; /* free registers */ - luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); - cc->nh++; } @@ -893,7 +894,7 @@ static void whilestat (LexState *ls, int line) { check(ls, TK_DO); block(ls); luaK_patchlist(fs, luaK_jump(fs), while_init); - luaK_patchlist(fs, v.f, luaK_getlabel(fs)); + luaK_patchtohere(fs, v.f); check_match(ls, TK_END, TK_WHILE, line); leavebreak(fs, &bl); } @@ -922,24 +923,11 @@ static void exp1 (LexState *ls) { } -static void forbody (LexState *ls, OpCode loopfor) { - /* forbody -> DO block END */ - FuncState *fs = ls->fs; - int basereg = fs->freereg - 3; - int prep = luaK_jump(fs); - int blockinit = luaK_getlabel(fs); - check(ls, TK_DO); - adjustlocalvars(ls, 3); /* scope for control variables */ - block(ls); - luaK_patchlist(fs, prep, luaK_getlabel(fs)); - luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); - removelocalvars(ls, 3, 1); -} - - static void fornum (LexState *ls, TString *varname) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + /* fornum -> NAME = exp1,exp1[,exp1] DO body */ FuncState *fs = ls->fs; + int prep; + int base = fs->freereg; new_localvar(ls, varname, 0); new_localvarstr(ls, "(limit)", 1); new_localvarstr(ls, "(step)", 2); @@ -954,26 +942,42 @@ static void fornum (LexState *ls, TString *varname) { luaK_reserveregs(fs, 1); } luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); - forbody(ls, OP_FORLOOP); + luaK_jump(fs); + prep = luaK_getlabel(fs); + check(ls, TK_DO); + adjustlocalvars(ls, 3); /* scope for control variables */ + block(ls); + luaK_patchtohere(fs, prep-1); + luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep); + removelocalvars(ls, 3, 1); } static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME,NAME IN exp1 forbody */ + /* forlist -> NAME {,NAME} IN exp1 DO body */ FuncState *fs = ls->fs; + int nvars = 0; + int prep; + int base = fs->freereg; new_localvarstr(ls, "(table)", 0); - new_localvar(ls, indexname, 1); - if (optional(ls, ',')) { - new_localvar(ls, str_checkname(ls), 2); - next(ls); /* skip var name */ + new_localvar(ls, indexname, ++nvars); + while (optional(ls, ',')) { + new_localvar(ls, str_checkname(ls), ++nvars); + next(ls); } - else - new_localvarstr(ls, "(val)", 2); check(ls, TK_IN); exp1(ls); /* table */ - luaK_reserveregs(fs, 2); /* registers for index and val */ - luaK_codeABC(fs, OP_LOADNIL, fs->freereg - 2, fs->freereg - 1, 0); - forbody(ls, OP_TFORLOOP); + luaK_checkstack(fs, 2); /* at least two slots, to traverse tables */ + luaK_reserveregs(fs, nvars); /* registers for vars */ + luaK_codeABC(fs, OP_LOADNIL, base+1, base+nvars, 0); + adjustlocalvars(ls, nvars+1); /* scope for control variables */ + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + prep = luaK_jump(fs); + check(ls, TK_DO); + block(ls); + luaK_patchlist(fs, luaK_jump(fs), prep-1); + luaK_patchtohere(fs, prep); + removelocalvars(ls, nvars+1, 1); } @@ -1013,18 +1017,18 @@ static void ifstat (LexState *ls, int line) { test_then_block(ls, &v); /* IF cond THEN block */ while (ls->t.token == TK_ELSEIF) { luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchlist(fs, v.f, luaK_getlabel(fs)); + luaK_patchtohere(fs, v.f); test_then_block(ls, &v); /* ELSEIF cond THEN block */ } if (ls->t.token == TK_ELSE) { luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchlist(fs, v.f, luaK_getlabel(fs)); + luaK_patchtohere(fs, v.f); next(ls); /* skip ELSE */ block(ls); /* `else' part */ } else luaK_concat(fs, &escapelist, v.f); - luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); + luaK_patchtohere(fs, escapelist); check_match(ls, TK_END, TK_IF, line); } @@ -1182,7 +1186,7 @@ static int statement (LexState *ls) { static void parlist (LexState *ls) { /* parlist -> [ param { `,' param } ] */ int nparams = 0; - short dots = 0; + int dots = 0; if (ls->t.token != ')') { /* is `parlist' not empty? */ do { switch (ls->t.token) { -- cgit v1.2.3-55-g6feb