diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-08-17 15:32:09 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-08-17 15:32:09 -0300 |
commit | 074352911f3fe3102e4103c2b7140d1cf3d48492 (patch) | |
tree | 5f3435634af978b8e32bde9b28d2e0d5d71686cb | |
parent | 5e8a9e324ccdba03b326f8a8fafa0446042975a5 (diff) | |
download | lua-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.c | 10 | ||||
-rw-r--r-- | lparser.c | 115 | ||||
-rw-r--r-- | luaconf.h | 12 |
3 files changed, 53 insertions, 84 deletions
@@ -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: { |
@@ -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 | /* | 991 | static 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 | ||
1002 | static void whilestat (LexState *ls, int line) { | 1007 | static 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 | ||
1044 | static void repeatstat (LexState *ls, int line) { | 1026 | static 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 | ||
1154 | static int test_then_block (LexState *ls) { | 1146 | static 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 | ||
1295 | static 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 | |||
1313 | static int statement (LexState *ls) { | 1287 | static 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 | } |
@@ -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)) | ||
485 | union luai_Cast { double l_d; long l_l; }; | 479 | union 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; } |