aboutsummaryrefslogtreecommitdiff
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
parent5e8a9e324ccdba03b326f8a8fafa0446042975a5 (diff)
downloadlua-074352911f3fe3102e4103c2b7140d1cf3d48492.tar.gz
lua-074352911f3fe3102e4103c2b7140d1cf3d48492.tar.bz2
lua-074352911f3fe3102e4103c2b7140d1cf3d48492.zip
new coding for while and repeat (with new scoping for repeat)
-rw-r--r--lcode.c10
-rw-r--r--lparser.c115
-rw-r--r--luaconf.h12
3 files changed, 53 insertions, 84 deletions
diff --git a/lcode.c b/lcode.c
index d4239f02..7f30bea4 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.13 2005/05/20 15:53:42 roberto Exp roberto $ 2** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -535,6 +535,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
535 } 535 }
536 } 536 }
537 luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ 537 luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
538 luaK_patchtohere(fs, e->t);
539 e->t = NO_JUMP;
538} 540}
539 541
540 542
@@ -560,6 +562,8 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
560 } 562 }
561 } 563 }
562 luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ 564 luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
565 luaK_patchtohere(fs, e->f);
566 e->f = NO_JUMP;
563} 567}
564 568
565 569
@@ -636,14 +640,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
636 switch (op) { 640 switch (op) {
637 case OPR_AND: { 641 case OPR_AND: {
638 luaK_goiftrue(fs, v); 642 luaK_goiftrue(fs, v);
639 luaK_patchtohere(fs, v->t);
640 v->t = NO_JUMP;
641 break; 643 break;
642 } 644 }
643 case OPR_OR: { 645 case OPR_OR: {
644 luaK_goiffalse(fs, v); 646 luaK_goiffalse(fs, v);
645 luaK_patchtohere(fs, v->f);
646 v->f = NO_JUMP;
647 break; 647 break;
648 } 648 }
649 case OPR_CONCAT: { 649 case OPR_CONCAT: {
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 }
diff --git a/luaconf.h b/luaconf.h
index 34c4c05e..e623e314 100644
--- a/luaconf.h
+++ b/luaconf.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: luaconf.h,v 1.58 2005/08/09 17:57:29 roberto Exp roberto $ 2** $Id: luaconf.h,v 1.59 2005/08/15 14:12:32 roberto Exp roberto $
3** Configuration file for Lua 3** Configuration file for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -456,13 +456,6 @@
456 456
457 457
458/* 458/*
459@@ LUAI_MAXEXPWHILE is the maximum size of code for expressions
460@* controling a 'while' loop.
461*/
462#define LUAI_MAXEXPWHILE 100
463
464
465/*
466@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. 459@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
467*/ 460*/
468#define LUAL_BUFFERSIZE BUFSIZ 461#define LUAL_BUFFERSIZE BUFSIZ
@@ -481,7 +474,8 @@
481*/ 474*/
482 475
483/* On a Pentium, resort to a trick */ 476/* On a Pentium, resort to a trick */
484#if !defined(LUA_ANSI) && (defined(__i386) || defined (_M_IX86)) 477#if !defined(LUA_ANSI) && !defined(__SSE2__) && \
478 (defined(__i386) || defined (_M_IX86))
485union luai_Cast { double l_d; long l_l; }; 479union luai_Cast { double l_d; long l_l; };
486#define lua_number2int(i,d) \ 480#define lua_number2int(i,d) \
487 { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } 481 { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }