diff --git a/lbuiltin.c b/lbuiltin.c index 3a57e814..3c558886 100644 --- a/lbuiltin.c +++ b/lbuiltin.c @@ -1,5 +1,5 @@ /* -** $Id: lbuiltin.c,v 1.93 2000/02/22 18:12:46 roberto Exp roberto $ +** $Id: lbuiltin.c,v 1.94 2000/03/03 14:58:26 roberto Exp $ ** Built-in functions ** See Copyright Notice in lua.h */ @@ -553,13 +553,8 @@ static int sort_comp (lua_State *L, lua_Object f, const TObject *a, L->top--; return (ttype(L->top) != LUA_T_NIL); } - else { /* a < b? */ - int res; - *(L->top) = *a; - *(L->top+1) = *b; - res = luaV_lessthan(L, L->top, L->top+1); - return res; - } + else /* a < b? */ + return luaV_lessthan(L, a, b, L->top); } static void auxsort (lua_State *L, Hash *a, int l, int u, lua_Object f) { diff --git a/lcode.c b/lcode.c index d43103fd..3f0418b9 100644 --- a/lcode.c +++ b/lcode.c @@ -88,6 +88,16 @@ static void luaK_sub (LexState *ls) { } +static void luaK_conc (LexState *ls) { + Instruction *previous = previous_instruction(ls); + luaK_deltastack(ls, -1); + switch(GET_OPCODE(*previous)) { + case CONCOP: *previous = SETARG_U(*previous, GETARG_U(*previous)+1); break; + default: luaK_primitivecode(ls, CREATE_U(CONCOP, 2)); + } +} + + void luaK_retcode (LexState *ls, int nlocals, int nexps) { Instruction *previous = previous_instruction(ls); if (nexps > 0 && GET_OPCODE(*previous) == CALL) { @@ -286,7 +296,7 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { case '*': luaK_0(ls, MULTOP, -1); break; case '/': luaK_0(ls, DIVOP, -1); break; case '^': luaK_0(ls, POWOP, -1); break; - case CONC: luaK_0(ls, CONCOP, -1); break; + case CONC: luaK_conc(ls); break; case EQ: luaK_0(ls, EQOP, -1); break; case NE: luaK_0(ls, NEQOP, -1); break; case '>': luaK_0(ls, GTOP, -1); break; diff --git a/lopcodes.h b/lopcodes.h index 494cb84c..1e3b9ee9 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -24,34 +24,51 @@ is the usigned value minus 2^23. ===========================================================================*/ -#define EXCESS_S (1<<23) /* == 2^23 */ +#define SIZE_OP 8 +#define SIZE_U 24 +#define POS_U 8 +#define SIZE_S 24 +#define POS_S 8 +#define SIZE_A 16 +#define POS_A 16 +#define SIZE_B 8 +#define POS_B 8 + +#define EXCESS_S (1<<(SIZE_S-1)) /* == 2^23 */ + + +/* creates a mask with `n' 1 bits at position `p' */ +#define MASK1(n,p) ((~((~0ul)<>8)) -#define GETARG_S(i) ((int)((i)>>8)-EXCESS_S) -#define GETARG_A(i) ((int)((i)>>16)) -#define GETARG_B(i) ((int)(((i)>>8) & 0xFF)) +#define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) +#define GETARG_U(i) ((int)((i)>>POS_U)) +#define GETARG_S(i) ((int)((i)>>POS_S)-EXCESS_S) +#define GETARG_A(i) ((int)((i)>>POS_A)) +#define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) -#define SET_OPCODE(i,o) (((i)&0xFFFFFF00u) | (Instruction)(o)) -#define SETARG_U(i,u) (((i)&0x000000FFu) | ((Instruction)(u)<<8)) -#define SETARG_S(i,s) (((i)&0x000000FFu) | ((Instruction)((s)+EXCESS_S)<<8)) -#define SETARG_A(i,a) (((i)&0x0000FFFFu) | ((Instruction)(a)<<16)) -#define SETARG_B(i,b) (((i)&0xFFFF00FFu) | ((Instruction)(b)<<8)) +#define SET_OPCODE(i,o) (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o)) +#define SETARG_U(i,u) (((i)&MASK0(SIZE_U,POS_U)) | ((Instruction)(u)<': case '<': case LE: case GE: *rp = 2; return 2; @@ -941,18 +941,17 @@ static void namestat (LexState *ls) { static void ifpart (LexState *ls, int line) { - /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ + /* ifpart -> cond THEN block (ELSEIF ifpart | [ELSE block] END) */ FuncState *fs = ls->fs; int c; /* address of the conditional jump */ - int je; /* address of the unconditional jump (to skip `else' part) */ int elseinit; next(ls); /* skip IF or ELSEIF */ exp1(ls); /* cond */ - c = luaK_S(ls, IFFJMP, 0, -1); /* jump over `then' part if `cond' is false */ + c = luaK_S(ls, IFFJMP, 0, -1); /* 1st jump: over `then' part */ check(ls, THEN); block(ls); /* `then' part */ - je = luaK_S(ls, JMP, 0, 0); /* jump over `else' part after `then' */ - elseinit = luaK_getlabel(ls); + luaK_S(ls, JMP, 0, 0); /* 2nd jump: over `else' part */ + elseinit = luaK_getlabel(ls); /* address of 2nd jump == elseinit-1 */ if (ls->token == ELSEIF) ifpart(ls, line); else { @@ -961,13 +960,12 @@ static void ifpart (LexState *ls, int line) { check_match(ls, END, IF, line); } 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 */ + luaK_fixjump(ls, c, elseinit); /* fix 1st jump to `else' part */ + luaK_fixjump(ls, elseinit-1, luaK_getlabel(ls)); /* fix 2nd jump */ } else { /* no else part */ - fs->pc--; /* remove last jump */ - LUA_ASSERT(L, fs->pc == je, "jump out of place"); - luaK_fixjump(ls, c, luaK_getlabel(ls)); /* fix first jump to `if' end */ + fs->pc--; /* remove 2nd jump */ + luaK_fixjump(ls, c, luaK_getlabel(ls)); /* fix 1st jump to `if' end */ } } diff --git a/lvm.c b/lvm.c index 819e9a0e..4a24c43a 100644 --- a/lvm.c +++ b/lvm.c @@ -39,17 +39,6 @@ -static TaggedString *strconc (lua_State *L, const TaggedString *l, - const TaggedString *r) { - long nl = l->u.s.len; - long nr = r->u.s.len; - char *buffer = luaL_openspace(L, nl+nr); - memcpy(buffer, l->str, nl); - memcpy(buffer+nl, r->str, nr); - return luaS_newlstr(L, buffer, nl+nr); -} - - int luaV_tonumber (TObject *obj) { /* LUA_NUMBER */ if (ttype(obj) != LUA_T_STRING) return 1; @@ -253,22 +242,16 @@ static int luaV_strcomp (const TaggedString *ls, const TaggedString *rs) { } -int luaV_lessthan (lua_State *L, TObject *l, TObject *r) { +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top) { if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER) return (nvalue(l) < nvalue(r)); else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING) return (luaV_strcomp(tsvalue(l), tsvalue(r)) < 0); - else { - /* update top and put arguments in correct order to call TM */ - if (ltop = r+1; /* yes; 2nd is on top */ - else { /* no; exchange them */ - TObject temp = *r; - *r = *l; - *l = temp; - L->top = l+1; /* 1st is on top */ - } - call_binTM(L, L->top, IM_LT, "unexpected type in comparison"); + else { /* call TM */ + luaD_checkstack(L, 2); + *top++ = *l; + *top++ = *r; + call_binTM(L, top, IM_LT, "unexpected type in comparison"); L->top--; return (ttype(L->top) != LUA_T_NIL); } @@ -280,6 +263,34 @@ int luaV_lessthan (lua_State *L, TObject *l, TObject *r) { else ttype(o) = LUA_T_NIL +static void strconc (lua_State *L, int total, StkId top) { + do { + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (tostring(L, top-2) || tostring(L, top-1)) + call_binTM(L, top, IM_CONCAT, "unexpected type for concatenation"); + else { /* at least two string values; get as many as possible */ + long tl = tsvalue(top-2)->u.s.len + tsvalue(top-1)->u.s.len; + char *buffer; + int i; + while (n < total && !tostring(L, top-n-1)) { /* collect total length */ + tl += tsvalue(top-n-1)->u.s.len; + n++; + } + buffer = luaL_openspace(L, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + long l = tsvalue(top-i)->u.s.len; + memcpy(buffer+tl, tsvalue(top-i)->str, l); + tl += l; + } + tsvalue(top-n) = luaS_newlstr(L, buffer, tl); + } + total -= n-1; /* got `n' strings to create 1 new */ + top -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + void luaV_pack (lua_State *L, StkId firstelem, int nvararg, TObject *tab) { int i; Hash *htab; @@ -479,22 +490,22 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, case LTOP: top--; - setbool(top-1, luaV_lessthan(L, top-1, top)); + setbool(top-1, luaV_lessthan(L, top-1, top, top+1)); break; case LEOP: /* a <= b === !(b b === (b= b === !(atop = top; luaC_checkGC(L); break; + } case MINUSOP: if (tonumber(top-1)) { diff --git a/lvm.h b/lvm.h index 391d90ab..b3033200 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 1.16 2000/02/22 18:12:46 roberto Exp roberto $ +** $Id: lvm.h,v 1.17 2000/03/03 14:58:26 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -28,6 +28,6 @@ void luaV_getglobal (lua_State *L, GlobalVar *gv, StkId top); void luaV_setglobal (lua_State *L, GlobalVar *gv, StkId top); StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, StkId base); void luaV_closure (lua_State *L, int nelems); -int luaV_lessthan (lua_State *L, TObject *l, TObject *r); +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top); #endif