commit 074352911f3fe3102e4103c2b7140d1cf3d48492
parent 5e8a9e324ccdba03b326f8a8fafa0446042975a5
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 17 Aug 2005 15:31:47 -0300
new coding for while and repeat (with new scoping for repeat)
Diffstat:
M | lcode.c | | | 10 | +++++----- |
M | lparser.c | | | 115 | +++++++++++++++++++++++++++++++------------------------------------------------ |
M | luaconf.h | | | 12 | +++--------- |
3 files changed, 53 insertions(+), 84 deletions(-)
diff --git a/lcode.c b/lcode.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.c,v 2.13 2005/05/20 15:53:42 roberto Exp roberto $
+** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -535,6 +535,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
}
}
luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
+ luaK_patchtohere(fs, e->t);
+ e->t = NO_JUMP;
}
@@ -560,6 +562,8 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
}
}
luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
+ luaK_patchtohere(fs, e->f);
+ e->f = NO_JUMP;
}
@@ -636,14 +640,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
switch (op) {
case OPR_AND: {
luaK_goiftrue(fs, v);
- luaK_patchtohere(fs, v->t);
- v->t = NO_JUMP;
break;
}
case OPR_OR: {
luaK_goiffalse(fs, v);
- luaK_patchtohere(fs, v->f);
- v->f = NO_JUMP;
break;
}
case OPR_CONCAT: {
diff --git a/lparser.c b/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.30 2005/06/13 14:25:29 roberto Exp roberto $
+** $Id: lparser.c,v 2.31 2005/07/11 14:01:37 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -317,6 +317,7 @@ static void leaveblock (FuncState *fs) {
removevars(fs->ls, bl->nactvar);
if (bl->upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ lua_assert(!bl->isbreakable || !bl->upval); /* loops have no body */
lua_assert(bl->nactvar == fs->nactvar);
fs->freereg = fs->nactvar; /* free registers */
luaK_patchtohere(fs, bl->breaklist);
@@ -981,79 +982,70 @@ static int cond (LexState *ls) {
expdesc v;
expr(ls, &v); /* read condition */
if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ else if (v.k == VK) v.k = VTRUE; /* 'trues' too */
luaK_goiftrue(ls->fs, &v);
- luaK_patchtohere(ls->fs, v.t);
return v.f;
}
-/*
-** The while statement optimizes its code by coding the condition
-** after its body (and thus avoiding one jump in the loop).
-*/
-
+static void breakstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ BlockCnt *bl = fs->bl;
+ int upval = 0;
+ while (bl && !bl->isbreakable) {
+ upval |= bl->upval;
+ bl = bl->previous;
+ }
+ if (!bl)
+ luaX_syntaxerror(ls, "no loop to break");
+ if (upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+}
-/*
-** the call `luaK_goiffalse' may grow the size of an expression by
-** at most this:
-*/
-#define EXTRAEXP 5
static void whilestat (LexState *ls, int line) {
/* whilestat -> WHILE cond DO block END */
- Instruction codeexp[LUAI_MAXEXPWHILE + EXTRAEXP];
- int lineexp;
- int i;
- int sizeexp;
FuncState *fs = ls->fs;
- int whileinit, blockinit, expinit;
- expdesc v;
+ int whileinit;
+ int condexit;
BlockCnt bl;
next(ls); /* skip WHILE */
- whileinit = luaK_jump(fs); /* jump to condition (which will be moved) */
- expinit = luaK_getlabel(fs);
- expr(ls, &v); /* parse condition */
- if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */
- lineexp = ls->linenumber;
- luaK_goiffalse(fs, &v);
- luaK_concat(fs, &v.f, fs->jpc);
- fs->jpc = NO_JUMP;
- sizeexp = fs->pc - expinit; /* size of expression code */
- if (sizeexp > LUAI_MAXEXPWHILE)
- luaX_syntaxerror(ls, LUA_QL("while") " condition too complex");
- for (i = 0; i < sizeexp; i++) /* save `exp' code */
- codeexp[i] = fs->f->code[expinit + i];
- fs->pc = expinit; /* remove `exp' code */
+ whileinit = luaK_getlabel(fs);
+ condexit = cond(ls);
enterblock(fs, &bl, 1);
checknext(ls, TK_DO);
- blockinit = luaK_getlabel(fs);
block(ls);
- luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */
- /* move `exp' back to code */
- if (v.t != NO_JUMP) v.t += fs->pc - expinit;
- if (v.f != NO_JUMP) v.f += fs->pc - expinit;
- for (i=0; i<sizeexp; i++)
- luaK_code(fs, codeexp[i], lineexp);
+ luaK_patchlist(fs, luaK_jump(fs), whileinit);
check_match(ls, TK_END, TK_WHILE, line);
leaveblock(fs);
- luaK_patchlist(fs, v.t, blockinit); /* true conditions go back to loop */
- luaK_patchtohere(fs, v.f); /* false conditions finish the loop */
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
}
static void repeatstat (LexState *ls, int line) {
/* repeatstat -> REPEAT block UNTIL cond */
+ int condexit;
FuncState *fs = ls->fs;
int repeat_init = luaK_getlabel(fs);
- int flist;
- BlockCnt bl;
- enterblock(fs, &bl, 1);
- next(ls);
- block(ls);
+ BlockCnt bl1, bl2;
+ enterblock(fs, &bl1, 1); /* loop block */
+ enterblock(fs, &bl2, 0); /* scope block */
+ next(ls); /* skip REPEAT */
+ chunk(ls);
check_match(ls, TK_UNTIL, TK_REPEAT, line);
- flist = cond(ls);
- luaK_patchlist(fs, flist, repeat_init);
- leaveblock(fs);
+ condexit = cond(ls); /* read condition (inside scope block) */
+ if (!bl2.upval) { /* no upvalues? */
+ leaveblock(fs); /* finish scope */
+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
+ }
+ else { /* complete semantics when there are upvalues */
+ breakstat(ls); /* if condition then break */
+ luaK_patchtohere(ls->fs, condexit); /* else... */
+ leaveblock(fs); /* finish scope... */
+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
+ }
+ leaveblock(fs); /* finish loop */
}
@@ -1153,12 +1145,12 @@ static void forstat (LexState *ls, int line) {
static int test_then_block (LexState *ls) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
- int flist;
+ int condexit;
next(ls); /* skip IF or ELSEIF */
- flist = cond(ls);
+ condexit = cond(ls);
checknext(ls, TK_THEN);
block(ls); /* `then' part */
- return flist;
+ return condexit;
}
@@ -1292,24 +1284,6 @@ static void retstat (LexState *ls) {
}
-static void breakstat (LexState *ls) {
- /* stat -> BREAK */
- FuncState *fs = ls->fs;
- BlockCnt *bl = fs->bl;
- int upval = 0;
- next(ls); /* skip BREAK */
- while (bl && !bl->isbreakable) {
- upval |= bl->upval;
- bl = bl->previous;
- }
- if (!bl)
- luaX_syntaxerror(ls, "no loop to break");
- if (upval)
- luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
- luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
-}
-
-
static int statement (LexState *ls) {
int line = ls->linenumber; /* may be needed for error messages */
switch (ls->t.token) {
@@ -1352,6 +1326,7 @@ static int statement (LexState *ls) {
return 1; /* must be last statement */
}
case TK_BREAK: { /* stat -> breakstat */
+ next(ls); /* skip BREAK */
breakstat(ls);
return 1; /* must be last statement */
}
diff --git a/luaconf.h b/luaconf.h
@@ -1,5 +1,5 @@
/*
-** $Id: luaconf.h,v 1.58 2005/08/09 17:57:29 roberto Exp roberto $
+** $Id: luaconf.h,v 1.59 2005/08/15 14:12:32 roberto Exp roberto $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@@ -456,13 +456,6 @@
/*
-@@ LUAI_MAXEXPWHILE is the maximum size of code for expressions
-@* controling a 'while' loop.
-*/
-#define LUAI_MAXEXPWHILE 100
-
-
-/*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
*/
#define LUAL_BUFFERSIZE BUFSIZ
@@ -481,7 +474,8 @@
*/
/* On a Pentium, resort to a trick */
-#if !defined(LUA_ANSI) && (defined(__i386) || defined (_M_IX86))
+#if !defined(LUA_ANSI) && !defined(__SSE2__) && \
+ (defined(__i386) || defined (_M_IX86))
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) \
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }