From f9cf402fbd1ba2ab00f5aa5f7d0ff5c9c0580dd5 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 12 Apr 2000 15:57:19 -0300 Subject: first implementation of FOR --- lparser.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 39127e2a..df4aeecf 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.80 2000/04/10 19:21:14 roberto Exp roberto $ +** $Id: lparser.c,v 1.81 2000/04/11 18:37:18 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -884,7 +884,7 @@ static void whilestat (LexState *ls, int line) { block(ls); luaK_patchlist(fs, luaK_jump(fs), while_init); luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); - check_END(ls, TK_WHILE, line); + check_END(ls, TK_WHILE, line); /* trace END when loop ends */ leavebreak(fs, &bl); } @@ -906,7 +906,40 @@ static void repeatstat (LexState *ls, int line) { } -static void test_and_bock (LexState *ls, expdesc *v) { +static void forstat (LexState *ls, int line) { + /* forstat -> FOR NAME '=' expr1 ',' expr1 [',' expr1] DO block END */ + 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 */ + check(ls, '='); + exp1(ls); /* initial value */ + check(ls, ','); + exp1(ls); /* limit */ + if (optional(ls, ',')) + 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); + check_END(ls, TK_WHILE, line); + leavebreak(fs, &bl); + removelocalvars(ls, 3, fs->lastsetline); +} + + +static void test_and_block (LexState *ls, expdesc *v) { + /* test_and_block -> [IF | ELSEIF] cond THEN block */ setline_and_next(ls); /* skip IF or ELSEIF */ expr(ls, v); /* cond */ luaK_goiftrue(ls->fs, v, 0); @@ -921,11 +954,11 @@ static void ifstat (LexState *ls, int line) { FuncState *fs = ls->fs; expdesc v; int escapelist = NO_JUMP; - test_and_bock(ls, &v); /* IF cond THEN block */ + test_and_block(ls, &v); /* IF cond THEN block */ while (ls->token == TK_ELSEIF) { luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); - test_and_bock(ls, &v); /* ELSEIF cond THEN block */ + test_and_block(ls, &v); /* ELSEIF cond THEN block */ } if (ls->token == TK_ELSE) { luaK_concat(fs, &escapelist, luaK_jump(fs)); @@ -1062,6 +1095,10 @@ static int stat (LexState *ls) { check_END(ls, TK_DO, line); return 1; + case TK_FOR: /* stat -> forstat */ + forstat(ls, line); + return 1; + case TK_REPEAT: /* stat -> repeatstat */ repeatstat(ls, line); return 1; -- cgit v1.2.3-55-g6feb