From 563de491be90601f23a735aede89ea9a3ef86ee9 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Sat, 4 Mar 2000 17:18:15 -0300 Subject: a better way to control optimizations. --- lcode.c | 160 ++++++++++++++++++++++++++++------------------- lcode.h | 14 +++-- lopcodes.h | 4 +- lparser.c | 205 ++++++++++++++++++++++++++++++------------------------------- lparser.h | 19 ++---- lvm.c | 8 +-- 6 files changed, 218 insertions(+), 192 deletions(-) diff --git a/lcode.c b/lcode.c index be97e2bb..d43103fd 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.4 2000/03/03 18:53:17 roberto Exp roberto $ +** $Id: lcode.c,v 1.5 2000/03/03 20:30:47 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -20,10 +20,19 @@ void luaK_error (LexState *ls, const char *msg) { } -static Instruction *last_i (LexState *ls, expdesc *v) { +/* +** Returns the address of the previous instruction, for optimizations. +** If there is a jump target between this and the current instruction, +** returns the address of a dummy instruction to avoid wrong optimizations. +*/ +static Instruction *previous_instruction (LexState *ls) { FuncState *fs = ls->fs; - int last_pc = (v->info != NOJUMPS) ? v->info : fs->pc-1; - return &fs->f->code[last_pc]; + if (fs->pc > fs->lasttarget) /* no jumps to current position? */ + return &fs->f->code[fs->pc-1]; /* returns previous instruction */ + else { + static Instruction dummy = CREATE_0(ENDCODE); + return &dummy; /* no optimizations after an `ENDCODE' */ + } } @@ -35,61 +44,74 @@ int luaK_primitivecode (LexState *ls, Instruction i) { } -static void luaK_minus (LexState *ls, expdesc *v) { - Instruction *last = last_i(ls, v); - switch(GET_OPCODE(*last)) { - case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); return; - case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); return; - case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); return; +static void luaK_minus (LexState *ls) { + Instruction *previous = previous_instruction(ls); + switch(GET_OPCODE(*previous)) { + case PUSHINT: *previous = SETARG_S(*previous, -GETARG_S(*previous)); return; + case PUSHNUM: *previous = SET_OPCODE(*previous, PUSHNEGNUM); return; + case PUSHNEGNUM: *previous = SET_OPCODE(*previous, PUSHNUM); return; default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); } } -static void luaK_gettable (LexState *ls, expdesc *v) { - Instruction *last = last_i(ls, v); +static void luaK_gettable (LexState *ls) { + Instruction *previous = previous_instruction(ls); luaK_deltastack(ls, -1); - switch(GET_OPCODE(*last)) { - case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; + switch(GET_OPCODE(*previous)) { + case PUSHSTRING: *previous = SET_OPCODE(*previous, GETDOTTED); break; default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); } } -static void luaK_add (LexState *ls, expdesc *v) { - Instruction *last = last_i(ls, v); +static void luaK_add (LexState *ls) { + Instruction *previous = previous_instruction(ls); luaK_deltastack(ls, -1); - switch(GET_OPCODE(*last)) { - case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; + switch(GET_OPCODE(*previous)) { + case PUSHINT: *previous = SET_OPCODE(*previous, ADDI); break; default: luaK_primitivecode(ls, CREATE_0(ADDOP)); } } -static void luaK_sub (LexState *ls, expdesc *v) { - Instruction *last = last_i(ls, v); +static void luaK_sub (LexState *ls) { + Instruction *previous = previous_instruction(ls); luaK_deltastack(ls, -1); - switch(GET_OPCODE(*last)) { + switch(GET_OPCODE(*previous)) { case PUSHINT: - *last = SET_OPCODE(*last, ADDI); - *last = SETARG_S(*last, -GETARG_S(*last)); + *previous = SET_OPCODE(*previous, ADDI); + *previous = SETARG_S(*previous, -GETARG_S(*previous)); break; default: luaK_primitivecode(ls, CREATE_0(SUBOP)); } } -void luaK_retcode (LexState *ls, int nlocals, listdesc *e) { - if (e->n > 0 && luaK_iscall(ls, e->info)) { - Instruction *last = &ls->fs->f->code[ls->fs->pc-1]; - *last = SET_OPCODE(*last, TAILCALL); - *last = SETARG_B(*last, nlocals); +void luaK_retcode (LexState *ls, int nlocals, int nexps) { + Instruction *previous = previous_instruction(ls); + if (nexps > 0 && GET_OPCODE(*previous) == CALL) { + LUA_ASSERT(ls->L, GETARG_B(*previous) == MULT_RET, "call should be open"); + *previous = SET_OPCODE(*previous, TAILCALL); + *previous = SETARG_B(*previous, nlocals); } else luaK_primitivecode(ls, CREATE_U(RETCODE, nlocals)); } +static void luaK_pushnil (LexState *ls, int n) { + Instruction *previous = previous_instruction(ls); + luaK_deltastack(ls, n); + switch(GET_OPCODE(*previous)) { + case PUSHNIL: + *previous = SETARG_U(*previous, GETARG_U(*previous)+n); + break; + default: luaK_primitivecode(ls, CREATE_U(PUSHNIL, n)); + } +} + + int luaK_code (LexState *ls, Instruction i, int delta) { luaK_deltastack(ls, delta); return luaK_primitivecode(ls, i); @@ -104,6 +126,17 @@ void luaK_fixjump (LexState *ls, int pc, int dest) { } +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (LexState *ls) { + FuncState *fs = ls->fs; + fs->lasttarget = fs->pc; + return fs->pc; +} + + void luaK_deltastack (LexState *ls, int delta) { FuncState *fs = ls->fs; fs->stacksize += delta; @@ -151,28 +184,27 @@ void luaK_adjuststack (LexState *ls, int n) { if (n > 0) luaK_U(ls, POP, n, -n); else if (n < 0) - luaK_U(ls, PUSHNIL, (-n)-1, -n); + luaK_pushnil(ls, -n); } -int luaK_iscall (LexState *ls, int hasjumps) { - if (hasjumps) return 0; /* a call cannot have internal jumps */ - else /* check whether last instruction is a function call */ - return (GET_OPCODE(ls->fs->f->code[ls->fs->pc-1]) == CALL); +int luaK_lastisopen (LexState *ls) { + /* check whether last instruction is an (open) function call */ + Instruction *i = previous_instruction(ls); + if (GET_OPCODE(*i) == CALL) { + LUA_ASSERT(ls->L, GETARG_B(*i) == MULT_RET, "call should be open"); + return 1; + } + else return 0; } -void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) { - if (!hasjumps) { /* if `hasjumps' cannot be a function call */ - Instruction *i = &ls->fs->f->code[ls->fs->pc-1]; - if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ - int old_nresults = GETARG_B(*i); - if (old_nresults != MULT_RET) - luaK_deltastack(ls, -old_nresults); /* pop old nresults */ - *i = SETARG_B(*i, nresults); /* set nresults */ - if (nresults != MULT_RET) - luaK_deltastack(ls, nresults); /* push results */ - } +void luaK_setcallreturns (LexState *ls, int nresults) { + Instruction *i = previous_instruction(ls); + if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ + LUA_ASSERT(ls->L, GETARG_B(*i) == MULT_RET, "call should be open"); + *i = SETARG_B(*i, nresults); /* set nresults */ + luaK_deltastack(ls, nresults); /* push results */ } } @@ -182,7 +214,7 @@ static void assertglobal (LexState *ls, int index) { } -void luaK_2stack (LexState *ls, expdesc *var) { +void luaK_tostack (LexState *ls, expdesc *var) { switch (var->k) { case VLOCAL: luaK_U(ls, PUSHLOCAL, var->info, 1); @@ -192,14 +224,20 @@ void luaK_2stack (LexState *ls, expdesc *var) { assertglobal(ls, var->info); /* make sure that there is a global */ break; case VINDEXED: - luaK_gettable(ls, var); + luaK_gettable(ls); break; case VEXP: - luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ - return; /* does not change var->info */ + return; /* exp result is already on stack */ } var->k = VEXP; - var->info = NOJUMPS; +} + + +void luaK_1tostack (LexState *ls, expdesc *var) { + if (var->k == VEXP) + luaK_setcallreturns(ls, 1); /* call must return 1 value */ + else + luaK_tostack(ls, var); } @@ -222,30 +260,29 @@ void luaK_storevar (LexState *ls, const expdesc *var) { void luaK_prefix (LexState *ls, int op, expdesc *v) { - luaK_2stack(ls, v); - if (op == '-') luaK_minus(ls, v); + luaK_1tostack(ls, v); + if (op == '-') luaK_minus(ls); else luaK_0(ls, NOTOP, 0); - v->info = NOJUMPS; } -void luaK_infix (LexState *ls, expdesc *v) { - luaK_2stack(ls, v); - if (ls->token == AND) +void luaK_infix (LexState *ls, int op, expdesc *v) { + luaK_1tostack(ls, v); + if (op == AND) v->info = luaK_0(ls, ONFJMP, -1); - else if (ls->token == OR) + else if (op == OR) v->info = luaK_0(ls, ONTJMP, -1); } void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { - luaK_2stack(ls, v2); + luaK_1tostack(ls, v2); switch (op) { case AND: case OR: - luaK_fixjump(ls, v1->info, ls->fs->pc); - return; /* keep v1->info != NOJUMPS */ - case '+': luaK_add(ls, v2); break; - case '-': luaK_sub(ls, v2); break; + luaK_fixjump(ls, v1->info, luaK_getlabel(ls)); + break; + case '+': luaK_add(ls); break; + case '-': luaK_sub(ls); break; case '*': luaK_0(ls, MULTOP, -1); break; case '/': luaK_0(ls, DIVOP, -1); break; case '^': luaK_0(ls, POWOP, -1); break; @@ -257,6 +294,5 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { case GE: luaK_0(ls, GEOP, -1); break; case LE: luaK_0(ls, LEOP, -1); break; } - v1->info = NOJUMPS; } diff --git a/lcode.h b/lcode.h index 0ba83766..0f8eadc1 100644 --- a/lcode.h +++ b/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $ +** $Id: lcode.h,v 1.3 2000/03/03 18:53:17 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -22,18 +22,20 @@ void luaK_error (LexState *ls, const char *msg); int luaK_primitivecode (LexState *ls, Instruction i); int luaK_code (LexState *ls, Instruction i, int delta); -void luaK_retcode (LexState *ls, int nlocals, listdesc *e); +void luaK_retcode (LexState *ls, int nlocals, int nexps); void luaK_fixjump (LexState *ls, int pc, int dest); +int luaK_getlabel (LexState *ls); void luaK_deltastack (LexState *ls, int delta); void luaK_kstr (LexState *ls, int c); void luaK_number (LexState *ls, real f); void luaK_adjuststack (LexState *ls, int n); -int luaK_iscall (LexState *ls, int hasjumps); -void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults); -void luaK_2stack (LexState *ls, expdesc *var); +int luaK_lastisopen (LexState *ls); +void luaK_setcallreturns (LexState *ls, int nresults); +void luaK_tostack (LexState *ls, expdesc *var); +void luaK_1tostack (LexState *ls, expdesc *var); void luaK_storevar (LexState *ls, const expdesc *var); void luaK_prefix (LexState *ls, int op, expdesc *v); -void luaK_infix (LexState *ls, expdesc *v); +void luaK_infix (LexState *ls, int op, expdesc *v); void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2); diff --git a/lopcodes.h b/lopcodes.h index b2819c3b..494cb84c 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.43 2000/03/03 14:58:26 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.44 2000/03/03 18:53:17 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -71,7 +71,7 @@ RETCODE,/* U - (return) */ CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ TAILCALL,/* A B v_a-v_1 f (return) f(v1,...,v_a) */ -PUSHNIL,/* U - nil_0-nil_u */ +PUSHNIL,/* U - nil_1-nil_u */ POP,/* U a_u-a_1 - */ PUSHINT,/* S - (real)s */ diff --git a/lparser.c b/lparser.c index e39f77b0..4c1eeb80 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.63 2000/03/03 18:53:17 roberto Exp roberto $ +** $Id: lparser.c,v 1.64 2000/03/03 20:29:25 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -23,10 +23,11 @@ /* -** check whether arbitrary limits fit in respective opcode types +** check whether arbitrary limits fit into respective opcode types */ -#if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \ - MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B +#if MAXLOCALS > MAXARG_U || MAXUPVALUES > MAXARG_B || MAXVARSLH > MAXARG_B || \ + MAXPARAMS > MAXLOCALS || MAXSTACK > MAXARG_A || \ + LFIELDS_PER_FLUSH > MAXARG_B || MULT_RET > MAXARG_B #error invalid limits #endif @@ -53,7 +54,7 @@ static void body (LexState *ls, int needself, int line); static void chunk (LexState *ls); static void constructor (LexState *ls); static void expr (LexState *ls, expdesc *v); -static int exp1 (LexState *ls); +static void exp1 (LexState *ls); static void next (LexState *ls) { @@ -256,9 +257,9 @@ static void pushupvalue (LexState *ls, TaggedString *n) { } -static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { - int diff = d->n - nvars; - if (d->n == 0 || !luaK_iscall(ls, d->info)) { /* list is empty or closed */ +static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { + int diff = nexps - nvars; + if (nexps == 0 || !luaK_lastisopen(ls)) { /* list is empty or closed */ /* push or pop eventual difference between list lengths */ luaK_adjuststack(ls, diff); } @@ -266,10 +267,10 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { diff--; /* do not count function call itself */ if (diff <= 0) { /* more variables than values? */ /* function call must provide extra values */ - luaK_setcallreturns(ls, d->info, -diff); + luaK_setcallreturns(ls, -diff); } else { /* more values than variables */ - luaK_setcallreturns(ls, d->info, 0); /* call should provide no value */ + luaK_setcallreturns(ls, 0); /* call should provide no value */ luaK_adjuststack(ls, diff); /* pop eventual extra values */ } } @@ -310,7 +311,7 @@ static void func_onstack (LexState *ls, FuncState *func) { TProtoFunc *f = ls->fs->f; int i; for (i=0; inupvalues; i++) - luaK_2stack(ls, &func->upvalues[i]); + luaK_1tostack(ls, &func->upvalues[i]); luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, constantEM, MAXARG_A); f->kproto[f->nkproto++] = func->f; @@ -331,6 +332,7 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { fs->f = f; f->source = source; fs->pc = 0; + fs->lasttarget = 0; f->code = NULL; f->maxstacksize = 0; f->numparams = 0; /* default for main chunk */ @@ -380,57 +382,57 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { /*============================================================*/ -static void explist1 (LexState *ls, listdesc *d) { +static int explist1 (LexState *ls) { + /* explist1 -> expr { ',' expr } */ + int n = 1; /* at least one expression */ expdesc v; expr(ls, &v); - d->n = 1; while (ls->token == ',') { - d->n++; - luaK_2stack(ls, &v); - next(ls); + luaK_1tostack(ls, &v); /* gets only 1 value from previous expression */ + next(ls); /* skip comma */ expr(ls, &v); + n++; } - luaK_2stack(ls, &v); - luaK_setcallreturns(ls, v.info, MULT_RET); /* default for explists */ - d->info = v.info; + luaK_tostack(ls, &v); + return n; } -static void explist (LexState *ls, listdesc *d) { +static int explist (LexState *ls) { + /* explist -> [ explist1 ] */ switch (ls->token) { case ELSE: case ELSEIF: case END: case UNTIL: case EOS: case ';': case ')': - d->n = 0; - break; + return 0; /* empty list */ default: - explist1(ls, d); + return explist1(ls); } } -static void funcparams (LexState *ls, int slf) { +static void funcargs (LexState *ls, int slf) { FuncState *fs = ls->fs; int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ switch (ls->token) { - case '(': { /* funcparams -> '(' explist ')' */ + case '(': { /* funcargs -> '(' explist ')' */ int line = ls->linenumber; - listdesc e; + int nargs; next(ls); - explist(ls, &e); + nargs = explist(ls); check_match(ls, ')', '(', line); #ifdef LUA_COMPAT_ARGRET - if (e.n > 0) /* arg list is not empty? */ - luaK_setcallreturns(ls, e.pc, 1); /* last call returns only 1 value */ + if (nargs > 0) /* arg list is not empty? */ + luaK_setcallreturns(ls, 1); /* last call returns only 1 value */ #endif break; } - case '{': /* funcparams -> constructor */ + case '{': /* funcargs -> constructor */ constructor(ls); break; - case STRING: /* funcparams -> STRING */ + case STRING: /* funcargs -> STRING */ code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */ next(ls); break; @@ -439,8 +441,8 @@ static void funcparams (LexState *ls, int slf) { luaK_error(ls, "function arguments expected"); break; } - fs->stacksize = slevel; /* call will remove func and params */ - luaK_AB(ls, CALL, slevel, 0, 0); + fs->stacksize = slevel; /* call will remove function and arguments */ + luaK_AB(ls, CALL, slevel, MULT_RET, 0); } @@ -449,37 +451,34 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { switch (ls->token) { case '.': /* var_or_func_tail -> '.' NAME */ next(ls); - luaK_2stack(ls, v); /* `v' must be on stack */ + luaK_1tostack(ls, v); /* `v' must be on stack */ luaK_kstr(ls, checkname(ls)); v->k = VINDEXED; - v->info = NOJUMPS; break; case '[': /* var_or_func_tail -> '[' exp1 ']' */ next(ls); - luaK_2stack(ls, v); /* `v' must be on stack */ + luaK_1tostack(ls, v); /* `v' must be on stack */ v->k = VINDEXED; - v->info = exp1(ls); + exp1(ls); check(ls, ']'); break; - case ':': { /* var_or_func_tail -> ':' NAME funcparams */ + case ':': { /* var_or_func_tail -> ':' NAME funcargs */ int name; next(ls); name = checkname(ls); - luaK_2stack(ls, v); /* `v' must be on stack */ + luaK_1tostack(ls, v); /* `v' must be on stack */ luaK_U(ls, PUSHSELF, name, 1); - funcparams(ls, 1); + funcargs(ls, 1); v->k = VEXP; - v->info = NOJUMPS; break; } - case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ - luaK_2stack(ls, v); /* `v' must be on stack */ - funcparams(ls, 0); + case '(': case STRING: case '{': /* var_or_func_tail -> funcargs */ + luaK_1tostack(ls, v); /* `v' must be on stack */ + funcargs(ls, 0); v->k = VEXP; - v->info = NOJUMPS; break; default: return; /* should be follow... */ @@ -493,7 +492,6 @@ static void var_or_func (LexState *ls, expdesc *v) { if (optional(ls, '%')) { /* upvalue? */ pushupvalue(ls, str_checkname(ls)); v->k = VEXP; - v->info = NOJUMPS; } else /* variable name */ singlevar(ls, str_checkname(ls), v, 0); @@ -593,7 +591,7 @@ static void constructor_part (LexState *ls, constdesc *cd) { cd->k = 1; /* record */ } else { - luaK_2stack(ls, &v); + luaK_tostack(ls, &v); cd->n = listfields(ls); cd->k = 0; /* list */ } @@ -693,15 +691,13 @@ static void simpleexp (LexState *ls, expdesc *v) { return; } v->k = VEXP; - v->info = NOJUMPS; } -static int exp1 (LexState *ls) { +static void exp1 (LexState *ls) { expdesc v; expr(ls, &v); - luaK_2stack(ls, &v); - return v.info; + luaK_1tostack(ls, &v); } @@ -711,53 +707,54 @@ static int exp1 (LexState *ls) { */ static int get_priority (int op, int *rp) { switch (op) { - case AND: case OR: - *rp = 1; return 1; - case EQ: case NE: - case '>': case '<': case LE: case GE: - *rp = 2; return 2; - case CONC: - *rp = 4; return 4; /* left associative (?) */ - case '+': case '-': - *rp = 5; return 5; - case '*': case '/': - *rp = 6; return 6; + + case '^': *rp = 8; return 9; /* right associative */ + #define UNARY_PRIORITY 7 - case '^': - *rp = 8; return 9; /* right associative */ - default: - *rp = -1; return -1; + + case '*': case '/': *rp = 6; return 6; + + case '+': case '-': *rp = 5; return 5; + + case CONC: *rp = 4; return 4; /* left associative (?) */ + + case EQ: case NE: case '>': case '<': case LE: case GE: + *rp = 2; return 2; + + case AND: case OR: *rp = 1; return 1; + + default: *rp = -1; return -1; } } /* -** expr -> simplexep | (NOT | '-') expr | expr binop expr +** subexpr -> (simplexep | (NOT | '-') subexpr) { binop subexpr } ** where `binop' is any binary operator with a priority higher than `limit' */ -static void operator_expr (LexState *ls, expdesc *v, int limit) { +static void subexpr (LexState *ls, expdesc *v, int limit) { int rp; if (ls->token == '-' || ls->token == NOT) { int op = ls->token; /* operator */ next(ls); - operator_expr(ls, v, UNARY_PRIORITY); + subexpr(ls, v, UNARY_PRIORITY); luaK_prefix(ls, op, v); } else simpleexp(ls, v); - /* expand while following operators have a priority higher than `limit' */ + /* expand while operators have priorities higher than `limit' */ while (get_priority(ls->token, &rp) > limit) { - int op = ls->token; /* operator */ expdesc v2; - luaK_infix(ls, v); + int op = ls->token; /* current operator (with priority == `rp') */ next(ls); - operator_expr(ls, &v2, rp); + luaK_infix(ls, op, v); + subexpr(ls, &v2, rp); /* read sub-expression with priority > `rp' */ luaK_posfix(ls, op, v, &v2); } } static void expr (LexState *ls, expdesc *v) { - operator_expr(ls, v, -1); + subexpr(ls, v, -1); } /* }==================================================================== */ @@ -775,7 +772,7 @@ static void block (LexState *ls) { FuncState *fs = ls->fs; int nlocalvar = fs->nlocalvar; chunk(ls); - luaK_adjuststack(ls, fs->nlocalvar - nlocalvar); + luaK_adjuststack(ls, fs->nlocalvar - nlocalvar); /* remove local variables */ for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) luaI_unregisterlocalvar(ls, fs->lastsetline); } @@ -793,12 +790,12 @@ static int assignment (LexState *ls, expdesc *v, int nvars) { left = assignment(ls, &nv, nvars+1); } else { /* assignment -> '=' explist1 */ - listdesc d; + int nexps;; if (ls->token != '=') error_unexpected(ls); next(ls); - explist1(ls, &d); - adjust_mult_assign(ls, nvars, &d); + nexps = explist1(ls); + adjust_mult_assign(ls, nvars, nexps); } if (v->k != VINDEXED || left+(nvars-1) == 0) { /* global/local var or indexed var without values in between */ @@ -821,7 +818,8 @@ static void whilestat (LexState *ls, int line) { /* whilestat -> WHILE exp1 DO block END */ Instruction buffer[MAX_WHILE_EXP]; FuncState *fs = ls->fs; - int while_init = fs->pc; + int while_init = luaK_getlabel(ls); + int loopentry; /* point to jump to repeat the loop */ int cond_size; int i; next(ls); /* skip WHILE */ @@ -836,20 +834,20 @@ static void whilestat (LexState *ls, int line) { luaK_deltastack(ls, -1); luaK_S(ls, JMP, 0, 0); /* initial jump to condition */ check(ls, DO); + loopentry = luaK_getlabel(ls); block(ls); check_match(ls, END, WHILE, line); - luaK_fixjump(ls, while_init, fs->pc); + luaK_fixjump(ls, while_init, luaK_getlabel(ls)); /* copy condition to new position, and correct stack */ for (i=0; i REPEAT block UNTIL exp1 */ - FuncState *fs = ls->fs; - int repeat_init = fs->pc; + int repeat_init = luaK_getlabel(ls); next(ls); block(ls); check_match(ls, UNTIL, REPEAT, line); @@ -870,28 +868,28 @@ static int localnamelist (LexState *ls) { } -static void decinit (LexState *ls, listdesc *d) { +static int decinit (LexState *ls) { /* decinit -> ['=' explist1] */ if (ls->token == '=') { next(ls); - explist1(ls, d); + return explist1(ls); } else - d->n = 0; + return 0; /* no initializations */ } static void localstat (LexState *ls) { /* stat -> LOCAL localnamelist decinit */ FuncState *fs = ls->fs; - listdesc d; int nvars; + int nexps; check_debugline(ls); next(ls); nvars = localnamelist(ls); - decinit(ls, &d); + nexps = decinit(ls); adjustlocalvars(ls, nvars, fs->lastsetline); - adjust_mult_assign(ls, nvars, &d); + adjust_mult_assign(ls, nvars, nexps); } @@ -902,7 +900,7 @@ static int funcname (LexState *ls, expdesc *v) { if (ls->token == ':' || ls->token == '.') { needself = (ls->token == ':'); next(ls); - luaK_2stack(ls, v); + luaK_1tostack(ls, v); luaK_kstr(ls, checkname(ls)); v->k = VINDEXED; } @@ -931,9 +929,9 @@ static void namestat (LexState *ls) { check_debugline(ls); var_or_func(ls, &v); if (v.k == VEXP) { /* stat -> func */ - if (!luaK_iscall(ls, v.info)) /* is just an upvalue? */ + if (!luaK_lastisopen(ls)) /* is just an upvalue? */ luaK_error(ls, "syntax error"); - luaK_setcallreturns(ls, v.info, 0); /* call statement uses no results */ + luaK_setcallreturns(ls, 0); /* call statement uses no results */ } else { /* stat -> ['%'] NAME assignment */ int left = assignment(ls, &v, 1); @@ -950,11 +948,11 @@ static void ifpart (LexState *ls, int line) { int elseinit; next(ls); /* skip IF or ELSEIF */ exp1(ls); /* cond */ - c = luaK_S(ls, IFFJMP, 0, -1); /* jump `then' if `cond' is false */ + c = luaK_S(ls, IFFJMP, 0, -1); /* jump over `then' part if `cond' is false */ check(ls, THEN); block(ls); /* `then' part */ - je = luaK_S(ls, JMP, 0, 0); /* jump `else' part after `then' */ - elseinit = fs->pc; + je = luaK_S(ls, JMP, 0, 0); /* jump over `else' part after `then' */ + elseinit = luaK_getlabel(ls); if (ls->token == ELSEIF) ifpart(ls, line); else { @@ -962,14 +960,15 @@ static void ifpart (LexState *ls, int line) { block(ls); /* `else' part */ check_match(ls, END, IF, line); } - if (fs->pc > elseinit) /* is there an `else' part? */ - luaK_fixjump(ls, je, fs->pc); /* last jump jumps over it */ - else { + if (fs->pc > elseinit) { /* is there an `else' part? */ + luaK_fixjump(ls, je, luaK_getlabel(ls)); /* last jump jumps over it */ + luaK_fixjump(ls, c, elseinit); /* fix first jump to `else' part */ + } + else { /* no else part */ fs->pc--; /* remove last jump */ - elseinit--; /* first jump will be smaller */ LUA_ASSERT(L, fs->pc == je, "jump out of place"); + luaK_fixjump(ls, c, luaK_getlabel(ls)); /* fix first jump to `if' end */ } - luaK_fixjump(ls, c, elseinit); /* fix first jump to `else' part */ } @@ -1073,11 +1072,11 @@ static void body (LexState *ls, int needself, int line) { static void ret (LexState *ls) { /* ret -> [RETURN explist sc] */ if (ls->token == RETURN) { - listdesc e; + int nexps; /* number of expressions returned */ check_debugline(ls); next(ls); - explist(ls, &e); - luaK_retcode(ls, ls->fs->nlocalvar, &e); + nexps = explist(ls); + luaK_retcode(ls, ls->fs->nlocalvar, nexps); ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ optional(ls, ';'); } diff --git a/lparser.h b/lparser.h index a64b8dda..adc7f012 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.8 2000/03/03 14:58:26 roberto Exp roberto $ +** $Id: lparser.h,v 1.9 2000/03/03 18:53:17 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -46,13 +46,11 @@ ** Expression descriptor */ -#define NOJUMPS 0 - typedef enum { VGLOBAL, /* info is constant index of global name */ VLOCAL, /* info is stack index */ - VINDEXED, /* info is info of the index expression */ - VEXP /* info is NOJUMPS if exp has no internal jumps */ + VINDEXED, + VEXP /* info is jump target if exp has internal jumps */ } expkind; typedef struct expdesc { @@ -61,22 +59,13 @@ typedef struct expdesc { } expdesc; -/* -** Expression List descriptor: -** tells number of expressions in the list, -** and gives the `info' of last expression. -*/ -typedef struct listdesc { - int n; - int info; /* 0 if last expression has no internal jumps */ -} listdesc; - /* state needed to generate code for a given function */ typedef struct FuncState { TProtoFunc *f; /* current function header */ struct FuncState *prev; /* enclosing function */ int pc; /* next position to code */ + int lasttarget; /* `pc' of last `jump target' */ int stacksize; /* number of values on activation register */ int nlocalvar; /* number of active local variables */ int nupvalues; /* number of upvalues */ diff --git a/lvm.c b/lvm.c index 60a886c8..819e9a0e 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.89 2000/02/22 18:12:46 roberto Exp roberto $ +** $Id: lvm.c,v 1.90 2000/03/03 14:58:26 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -348,10 +348,10 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, return base+GETARG_B(i); case PUSHNIL: { - register int n = GETARG_U(i); - do { + int n = GETARG_U(i); + do { ttype(top++) = LUA_T_NIL; - } while (n--); + } while (--n > 0); break; } -- cgit v1.2.3-55-g6feb