From 93d93a0bfbc30f1176e973e1238b51e560eeb233 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 15 May 2000 16:48:04 -0300 Subject: first implementation of `for' over tables --- lparser.c | 89 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 26 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 9691f4d2..3fae5419 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.85 2000/05/10 16:33:20 roberto Exp roberto $ +** $Id: lparser.c,v 1.86 2000/05/12 18:12:04 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -205,7 +205,8 @@ static void store_localvar (LexState *ls, TString *name, int n) { } -static void adjustlocalvars (LexState *ls, int nvars, int line) { +static void adjustlocalvars (LexState *ls, int nvars) { + int line = ls->fs->lastsetline; FuncState *fs = ls->fs; int i; fs->nlocalvar += nvars; @@ -214,7 +215,8 @@ static void adjustlocalvars (LexState *ls, int nvars, int line) { } -static void removelocalvars (LexState *ls, int nvars, int line) { +static void removelocalvars (LexState *ls, int nvars) { + int line = ls->fs->lastsetline; ls->fs->nlocalvar -= nvars; while (nvars--) luaI_unregisterlocalvar(ls, line); @@ -223,7 +225,7 @@ static void removelocalvars (LexState *ls, int nvars, int line) { static void add_localvar (LexState *ls, const char *name) { store_localvar(ls, luaS_newfixed(ls->L, name), 0); - adjustlocalvars(ls, 1, 0); + adjustlocalvars(ls, 1); } @@ -303,7 +305,7 @@ static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { static void code_args (LexState *ls, int nparams, int dots) { FuncState *fs = ls->fs; - adjustlocalvars(ls, nparams, 0); + adjustlocalvars(ls, nparams); checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); nparams = fs->nlocalvar; /* `self' could be there already */ fs->f->numparams = nparams; @@ -838,7 +840,7 @@ static void block (LexState *ls) { int nlocalvar = fs->nlocalvar; chunk(ls); luaK_adjuststack(fs, fs->nlocalvar - nlocalvar); /* remove local variables */ - removelocalvars(ls, fs->nlocalvar - nlocalvar, fs->lastsetline); + removelocalvars(ls, fs->nlocalvar - nlocalvar); } @@ -907,15 +909,20 @@ static void repeatstat (LexState *ls, int line) { } -static void forstat (LexState *ls, int line) { - /* forstat -> FOR NAME '=' expr1 ',' expr1 [',' expr1] DO block END */ +static void forbody (LexState *ls, OpCode prepfor, OpCode loopfor) { FuncState *fs = ls->fs; - int prep; - int blockinit; - Breaklabel bl; - enterbreak(fs, &bl); - setline_and_next(ls); /* skip for */ - store_localvar(ls, str_checkname(ls), 0); /* control variable */ + int prep = luaK_code0(fs, prepfor); + int blockinit = luaK_getlabel(fs); + check(ls, TK_DO); + block(ls); + luaK_patchlist(fs, prep, luaK_getlabel(fs)); + luaK_patchlist(fs, luaK_code0(fs, loopfor), blockinit); +} + + +static void fornum (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + store_localvar(ls, varname, 0); check(ls, '='); exp1(ls); /* initial value */ check(ls, ','); @@ -924,18 +931,49 @@ static void forstat (LexState *ls, int line) { exp1(ls); /* optional step */ else luaK_code1(fs, OP_PUSHINT, 1); /* default step */ - adjustlocalvars(ls, 1, 0); /* init scope for control variable */ - add_localvar(ls, " limit "); - add_localvar(ls, " step "); - prep = luaK_code0(fs, OP_FORPREP); - blockinit = luaK_getlabel(fs); - check(ls, TK_DO); - block(ls); - luaK_patchlist(fs, prep, luaK_getlabel(fs)); - luaK_patchlist(fs, luaK_code0(fs, OP_FORLOOP), blockinit); + adjustlocalvars(ls, 1); /* scope for control variables */ + add_localvar(ls, "*limit*"); + add_localvar(ls, "*step*"); + forbody(ls, OP_FORPREP, OP_FORLOOP); + removelocalvars(ls, 3); +} + + +static void forlist (LexState *ls, TString *indexname) { + TString *valname; + check(ls, ','); + valname = str_checkname(ls); + /* next test is dirty, but avoids `in' being a reserved word */ + if (ls->token != TK_NAME || ls->seminfo.ts != luaS_new(ls->L, "in")) + luaK_error(ls, "`in' expected"); + next(ls); /* skip `in' */ + exp1(ls); /* table */ + add_localvar(ls, "*table*"); + add_localvar(ls, "*counter*"); + store_localvar(ls, indexname, 0); + store_localvar(ls, valname, 1); + adjustlocalvars(ls, 2); /* scope for control variable */ + forbody(ls, OP_LFORPREP, OP_LFORLOOP); + removelocalvars(ls, 4); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR NAME '=' expr1 ',' expr1 [',' expr1] DO block END */ + /* forstat -> FOR NAME1, NAME2 IN expr1 DO block END */ + FuncState *fs = ls->fs; + TString *varname; + Breaklabel bl; + enterbreak(fs, &bl); + setline_and_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->token) { + case '=': fornum(ls, varname); break; + case ',': forlist(ls, varname); break; + default: luaK_error(ls, "`=' or `,' expected"); + } check_END(ls, TK_FOR, line); leavebreak(fs, &bl); - removelocalvars(ls, 3, fs->lastsetline); } @@ -999,13 +1037,12 @@ static int decinit (LexState *ls) { static void localstat (LexState *ls) { /* stat -> LOCAL localnamelist decinit */ - FuncState *fs = ls->fs; int nvars; int nexps; setline_and_next(ls); /* skip LOCAL */ nvars = localnamelist(ls); nexps = decinit(ls); - adjustlocalvars(ls, nvars, fs->lastsetline); + adjustlocalvars(ls, nvars); adjust_mult_assign(ls, nvars, nexps); } -- cgit v1.2.3-55-g6feb