aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-17 15:32:09 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-17 15:32:09 -0300
commit074352911f3fe3102e4103c2b7140d1cf3d48492 (patch)
tree5f3435634af978b8e32bde9b28d2e0d5d71686cb /lparser.c
parent5e8a9e324ccdba03b326f8a8fafa0446042975a5 (diff)
downloadlua-074352911f3fe3102e4103c2b7140d1cf3d48492.tar.gz
lua-074352911f3fe3102e4103c2b7140d1cf3d48492.tar.bz2
lua-074352911f3fe3102e4103c2b7140d1cf3d48492.zip
new coding for while and repeat (with new scoping for repeat)
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c115
1 files changed, 45 insertions, 70 deletions
diff --git a/lparser.c b/lparser.c
index 7a6bbcef..2b85c1a9 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.30 2005/06/13 14:25:29 roberto Exp roberto $ 2** $Id: lparser.c,v 2.31 2005/07/11 14:01:37 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -317,6 +317,7 @@ static void leaveblock (FuncState *fs) {
317 removevars(fs->ls, bl->nactvar); 317 removevars(fs->ls, bl->nactvar);
318 if (bl->upval) 318 if (bl->upval)
319 luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); 319 luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
320 lua_assert(!bl->isbreakable || !bl->upval); /* loops have no body */
320 lua_assert(bl->nactvar == fs->nactvar); 321 lua_assert(bl->nactvar == fs->nactvar);
321 fs->freereg = fs->nactvar; /* free registers */ 322 fs->freereg = fs->nactvar; /* free registers */
322 luaK_patchtohere(fs, bl->breaklist); 323 luaK_patchtohere(fs, bl->breaklist);
@@ -981,79 +982,70 @@ static int cond (LexState *ls) {
981 expdesc v; 982 expdesc v;
982 expr(ls, &v); /* read condition */ 983 expr(ls, &v); /* read condition */
983 if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ 984 if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
985 else if (v.k == VK) v.k = VTRUE; /* 'trues' too */
984 luaK_goiftrue(ls->fs, &v); 986 luaK_goiftrue(ls->fs, &v);
985 luaK_patchtohere(ls->fs, v.t);
986 return v.f; 987 return v.f;
987} 988}
988 989
989 990
990/* 991static void breakstat (LexState *ls) {
991** The while statement optimizes its code by coding the condition 992 FuncState *fs = ls->fs;
992** after its body (and thus avoiding one jump in the loop). 993 BlockCnt *bl = fs->bl;
993*/ 994 int upval = 0;
994 995 while (bl && !bl->isbreakable) {
996 upval |= bl->upval;
997 bl = bl->previous;
998 }
999 if (!bl)
1000 luaX_syntaxerror(ls, "no loop to break");
1001 if (upval)
1002 luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
1003 luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
1004}
995 1005
996/*
997** the call `luaK_goiffalse' may grow the size of an expression by
998** at most this:
999*/
1000#define EXTRAEXP 5
1001 1006
1002static void whilestat (LexState *ls, int line) { 1007static void whilestat (LexState *ls, int line) {
1003 /* whilestat -> WHILE cond DO block END */ 1008 /* whilestat -> WHILE cond DO block END */
1004 Instruction codeexp[LUAI_MAXEXPWHILE + EXTRAEXP];
1005 int lineexp;
1006 int i;
1007 int sizeexp;
1008 FuncState *fs = ls->fs; 1009 FuncState *fs = ls->fs;
1009 int whileinit, blockinit, expinit; 1010 int whileinit;
1010 expdesc v; 1011 int condexit;
1011 BlockCnt bl; 1012 BlockCnt bl;
1012 next(ls); /* skip WHILE */ 1013 next(ls); /* skip WHILE */
1013 whileinit = luaK_jump(fs); /* jump to condition (which will be moved) */ 1014 whileinit = luaK_getlabel(fs);
1014 expinit = luaK_getlabel(fs); 1015 condexit = cond(ls);
1015 expr(ls, &v); /* parse condition */
1016 if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */
1017 lineexp = ls->linenumber;
1018 luaK_goiffalse(fs, &v);
1019 luaK_concat(fs, &v.f, fs->jpc);
1020 fs->jpc = NO_JUMP;
1021 sizeexp = fs->pc - expinit; /* size of expression code */
1022 if (sizeexp > LUAI_MAXEXPWHILE)
1023 luaX_syntaxerror(ls, LUA_QL("while") " condition too complex");
1024 for (i = 0; i < sizeexp; i++) /* save `exp' code */
1025 codeexp[i] = fs->f->code[expinit + i];
1026 fs->pc = expinit; /* remove `exp' code */
1027 enterblock(fs, &bl, 1); 1016 enterblock(fs, &bl, 1);
1028 checknext(ls, TK_DO); 1017 checknext(ls, TK_DO);
1029 blockinit = luaK_getlabel(fs);
1030 block(ls); 1018 block(ls);
1031 luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */ 1019 luaK_patchlist(fs, luaK_jump(fs), whileinit);
1032 /* move `exp' back to code */
1033 if (v.t != NO_JUMP) v.t += fs->pc - expinit;
1034 if (v.f != NO_JUMP) v.f += fs->pc - expinit;
1035 for (i=0; i<sizeexp; i++)
1036 luaK_code(fs, codeexp[i], lineexp);
1037 check_match(ls, TK_END, TK_WHILE, line); 1020 check_match(ls, TK_END, TK_WHILE, line);
1038 leaveblock(fs); 1021 leaveblock(fs);
1039 luaK_patchlist(fs, v.t, blockinit); /* true conditions go back to loop */ 1022 luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
1040 luaK_patchtohere(fs, v.f); /* false conditions finish the loop */
1041} 1023}
1042 1024
1043 1025
1044static void repeatstat (LexState *ls, int line) { 1026static void repeatstat (LexState *ls, int line) {
1045 /* repeatstat -> REPEAT block UNTIL cond */ 1027 /* repeatstat -> REPEAT block UNTIL cond */
1028 int condexit;
1046 FuncState *fs = ls->fs; 1029 FuncState *fs = ls->fs;
1047 int repeat_init = luaK_getlabel(fs); 1030 int repeat_init = luaK_getlabel(fs);
1048 int flist; 1031 BlockCnt bl1, bl2;
1049 BlockCnt bl; 1032 enterblock(fs, &bl1, 1); /* loop block */
1050 enterblock(fs, &bl, 1); 1033 enterblock(fs, &bl2, 0); /* scope block */
1051 next(ls); 1034 next(ls); /* skip REPEAT */
1052 block(ls); 1035 chunk(ls);
1053 check_match(ls, TK_UNTIL, TK_REPEAT, line); 1036 check_match(ls, TK_UNTIL, TK_REPEAT, line);
1054 flist = cond(ls); 1037 condexit = cond(ls); /* read condition (inside scope block) */
1055 luaK_patchlist(fs, flist, repeat_init); 1038 if (!bl2.upval) { /* no upvalues? */
1056 leaveblock(fs); 1039 leaveblock(fs); /* finish scope */
1040 luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
1041 }
1042 else { /* complete semantics when there are upvalues */
1043 breakstat(ls); /* if condition then break */
1044 luaK_patchtohere(ls->fs, condexit); /* else... */
1045 leaveblock(fs); /* finish scope... */
1046 luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
1047 }
1048 leaveblock(fs); /* finish loop */
1057} 1049}
1058 1050
1059 1051
@@ -1153,12 +1145,12 @@ static void forstat (LexState *ls, int line) {
1153 1145
1154static int test_then_block (LexState *ls) { 1146static int test_then_block (LexState *ls) {
1155 /* test_then_block -> [IF | ELSEIF] cond THEN block */ 1147 /* test_then_block -> [IF | ELSEIF] cond THEN block */
1156 int flist; 1148 int condexit;
1157 next(ls); /* skip IF or ELSEIF */ 1149 next(ls); /* skip IF or ELSEIF */
1158 flist = cond(ls); 1150 condexit = cond(ls);
1159 checknext(ls, TK_THEN); 1151 checknext(ls, TK_THEN);
1160 block(ls); /* `then' part */ 1152 block(ls); /* `then' part */
1161 return flist; 1153 return condexit;
1162} 1154}
1163 1155
1164 1156
@@ -1292,24 +1284,6 @@ static void retstat (LexState *ls) {
1292} 1284}
1293 1285
1294 1286
1295static void breakstat (LexState *ls) {
1296 /* stat -> BREAK */
1297 FuncState *fs = ls->fs;
1298 BlockCnt *bl = fs->bl;
1299 int upval = 0;
1300 next(ls); /* skip BREAK */
1301 while (bl && !bl->isbreakable) {
1302 upval |= bl->upval;
1303 bl = bl->previous;
1304 }
1305 if (!bl)
1306 luaX_syntaxerror(ls, "no loop to break");
1307 if (upval)
1308 luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
1309 luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
1310}
1311
1312
1313static int statement (LexState *ls) { 1287static int statement (LexState *ls) {
1314 int line = ls->linenumber; /* may be needed for error messages */ 1288 int line = ls->linenumber; /* may be needed for error messages */
1315 switch (ls->t.token) { 1289 switch (ls->t.token) {
@@ -1352,6 +1326,7 @@ static int statement (LexState *ls) {
1352 return 1; /* must be last statement */ 1326 return 1; /* must be last statement */
1353 } 1327 }
1354 case TK_BREAK: { /* stat -> breakstat */ 1328 case TK_BREAK: { /* stat -> breakstat */
1329 next(ls); /* skip BREAK */
1355 breakstat(ls); 1330 breakstat(ls);
1356 return 1; /* must be last statement */ 1331 return 1; /* must be last statement */
1357 } 1332 }