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; } |
