diff --git a/lcode.c b/lcode.c index 6d463311..f72bcdb3 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.99 2002/05/07 17:36:56 roberto Exp roberto $ +** $Id: lcode.c,v 1.100 2002/05/09 14:14:34 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -39,6 +39,13 @@ void luaK_nil (FuncState *fs, int from, int n) { } +void luaK_moveexp (expdesc *e, int offset) { + if (e->t != NO_JUMP) e->t += offset; + if (e->f != NO_JUMP) e->f += offset; + if (e->k == VRELOCABLE || e->k == VJMP) e->info += offset; +} + + int luaK_jump (FuncState *fs) { int j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); if (j == fs->lasttarget) { /* possible jumps to this jump? */ @@ -515,12 +522,10 @@ 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; } -static void luaK_goiffalse (FuncState *fs, expdesc *e) { +void luaK_goiffalse (FuncState *fs, expdesc *e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e->k) { @@ -542,8 +547,6 @@ static 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; } @@ -607,10 +610,14 @@ 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: { @@ -727,7 +734,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { } -static int luaK_code (FuncState *fs, Instruction i) { +int luaK_code (FuncState *fs, Instruction i, int line) { Proto *f = fs->f; int oldsize = f->sizecode; /* put new instruction in code array */ @@ -736,19 +743,19 @@ static int luaK_code (FuncState *fs, Instruction i) { f->code[fs->pc] = i; if (f->sizecode != oldsize) luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int); - f->lineinfo[fs->pc] = fs->ls->lastline; + f->lineinfo[fs->pc] = line; return fs->pc++; } int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { lua_assert(getOpMode(o) == iABC); - return luaK_code(fs, CREATE_ABC(o, a, b, c)); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); } int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); } diff --git a/lcode.h b/lcode.h index 472b4ebc..7d46ca43 100644 --- a/lcode.h +++ b/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.32 2002/04/24 20:07:46 roberto Exp roberto $ +** $Id: lcode.h,v 1.33 2002/05/07 17:36:56 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -41,6 +41,7 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) +int luaK_code (FuncState *fs, Instruction i, int line); int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); void luaK_nil (FuncState *fs, int from, int n); @@ -54,7 +55,9 @@ void luaK_exp2val (FuncState *fs, expdesc *e); int luaK_exp2RK (FuncState *fs, expdesc *e); void luaK_self (FuncState *fs, expdesc *e, expdesc *key); void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +void luaK_moveexp (expdesc *e, int offset); void luaK_goiftrue (FuncState *fs, expdesc *e); +void luaK_goiffalse (FuncState *fs, expdesc *e); void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); int luaK_jump (FuncState *fs); diff --git a/lparser.c b/lparser.c index b6e500b8..eaf0bc8a 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.178 2002/04/24 20:07:46 roberto Exp roberto $ +** $Id: lparser.c,v 1.179 2002/05/07 17:36:56 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -946,22 +946,61 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { static void cond (LexState *ls, expdesc *v) { /* cond -> exp */ expr(ls, v); /* read condition */ + if (v->k == VNIL) v->k = VFALSE; /* `falses' are all equal here */ luaK_goiftrue(ls->fs, v); + luaK_patchtohere(ls->fs, v->t); } +/* +** The while statement optimizes its code by coding the condition +** after its body (and thus avoiding one jump in the loop). +*/ + +/* +** maximum size of expressions for optimizing `while' code +*/ +#ifndef MAXEXPWHILE +#define MAXEXPWHILE 100 +#endif + +/* +** 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[MAXEXPWHILE + EXTRAEXP]; + int lineexp = 0; + int i; + int sizeexp; FuncState *fs = ls->fs; int while_init = luaK_getlabel(fs); expdesc v; BlockCnt bl; - enterblock(fs, &bl, 1); next(ls); - cond(ls, &v); + expr(ls, &v); + if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ + lineexp = ls->linenumber; + luaK_goiffalse(fs, &v); + sizeexp = fs->pc - while_init; + if (sizeexp > MAXEXPWHILE) + luaX_syntaxerror(ls, "while condition too complex"); + fs->pc = while_init; /* remove `exp' code */ + luaK_getlabel(fs); + for (i = 0; i < sizeexp; i++) /* save `exp' code */ + codeexp[i] = fs->f->code[while_init + i]; + luaK_jump(fs); + enterblock(fs, &bl, 1); check(ls, TK_DO); block(ls); - luaK_patchlist(fs, luaK_jump(fs), while_init); + luaK_patchtohere(fs, while_init); /* initial jump jumps to here */ + luaK_moveexp(&v, fs->pc - while_init); /* correct pointers */ + for (i=0; i