From 9aff171f3bf0125314a29a5ca952470b2d83708e Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 11 Dec 2001 20:48:44 -0200 Subject: new type `boolean' --- lapi.c | 23 ++++++++++++ lbaselib.c | 19 +++++----- lcode.c | 123 ++++++++++++++++++++++++++++++------------------------------- ldebug.c | 8 ++-- lgc.c | 6 ++- llex.c | 6 +-- llex.h | 8 ++-- lobject.c | 4 +- lobject.h | 9 ++++- lopcodes.c | 6 +-- lopcodes.h | 7 ++-- lparser.c | 12 +++++- lparser.h | 4 +- ltable.c | 3 ++ ltests.c | 10 +---- ltm.c | 2 +- lua.h | 11 ++++-- lvm.c | 26 ++++++------- 18 files changed, 166 insertions(+), 121 deletions(-) diff --git a/lapi.c b/lapi.c index af151636..50578513 100644 --- a/lapi.c +++ b/lapi.c @@ -174,6 +174,12 @@ LUA_API int lua_isnumber (lua_State *L, int index) { } +LUA_API int lua_istrue (lua_State *L, int index) { + TObject *o = luaA_indexAcceptable(L, index); + return (o != NULL && !l_isfalse(o)); +} + + LUA_API int lua_isstring (lua_State *L, int index) { int t = lua_type(L, index); return (t == LUA_TSTRING || t == LUA_TNUMBER); @@ -213,6 +219,15 @@ LUA_API lua_Number lua_tonumber (lua_State *L, int index) { } +LUA_API int lua_toboolean (lua_State *L, int index) { + const TObject *o = luaA_indexAcceptable(L, index); + if (o != NULL && (ttype(o) == LUA_TBOOLEAN)) + return bvalue(o); + else + return -1; +} + + LUA_API const char *lua_tostring (lua_State *L, int index) { StkId o = luaA_indexAcceptable(L, index); if (o == NULL) @@ -323,6 +338,14 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { } +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, b); + api_incr_top(L); + lua_unlock(L); +} + + /* ** get functions (Lua -> stack) diff --git a/lbaselib.c b/lbaselib.c index bb66ab32..8f53a0d9 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -216,10 +216,8 @@ static int luaB_type (lua_State *L) { if (lua_isnull(L, 2)) lua_pushstring(L, lua_typename(L, lua_type(L, 1))); else { - if (strcmp(lua_typename(L, lua_type(L, 1)), luaL_check_string(L, 2)) == 0) - lua_pushnumber(L, 1); - else - lua_pushnil(L); + lua_pushboolean(L, + (strcmp(lua_typename(L, lua_type(L, 1)), luaL_check_string(L, 2)) == 0)); } return 1; } @@ -401,8 +399,12 @@ static int luaB_tostring (lua_State *L) { case LUA_TSTRING: lua_pushvalue(L, 1); return 1; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + return 1; case LUA_TTABLE: - sprintf(buff, "%.40s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1)); + sprintf(buff, "%.40s: %p", lua_typename(L, lua_type(L, 1)), + lua_topointer(L, 1)); break; case LUA_TFUNCTION: sprintf(buff, "function: %p", lua_topointer(L, 1)); @@ -464,9 +466,8 @@ static int luaB_foreach (lua_State *L) { static int luaB_assert (lua_State *L) { luaL_check_any(L, 1); - if (lua_isnil(L, 1)) - luaL_verror(L, "assertion failed! %.90s", - luaL_opt_string(L, 2, "")); + if (!lua_istrue(L, 1)) + luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, "")); lua_settop(L, 1); return 1; } @@ -542,7 +543,7 @@ static int sort_comp (lua_State *L, int a, int b) { lua_pushvalue(L, a-1); /* -1 to compensate function */ lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ lua_rawcall(L, 2, 1); - res = !lua_isnil(L, -1); + res = lua_istrue(L, -1); lua_pop(L, 1); return res; } diff --git a/lcode.c b/lcode.c index 210450fa..4e8d23c1 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.82 2001/09/07 17:39:10 roberto Exp $ +** $Id: lcode.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -221,10 +221,10 @@ static void freeexp (FuncState *fs, expdesc *e) { } -static int addk (FuncState *fs, TObject *k) { +static int addk (FuncState *fs, TObject *k, TObject *v) { const TObject *index = luaH_get(fs->h, k); if (ttype(index) == LUA_TNUMBER) { - lua_assert(luaO_equalObj(&fs->f->k[cast(int, nvalue(index))], k)); + lua_assert(luaO_equalObj(&fs->f->k[cast(int, nvalue(index))], v)); return cast(int, nvalue(index)); } else { /* constant not found; create a new entry */ @@ -232,7 +232,7 @@ static int addk (FuncState *fs, TObject *k) { Proto *f = fs->f; luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, MAXARG_Bc, "constant table overflow"); - setobj(&f->k[fs->nk], k); + setobj(&f->k[fs->nk], v); setnvalue(&o, fs->nk); luaH_set(fs->L, fs->h, k, &o); return fs->nk++; @@ -243,14 +243,22 @@ static int addk (FuncState *fs, TObject *k) { int luaK_stringk (FuncState *fs, TString *s) { TObject o; setsvalue(&o, s); - return addk(fs, &o); + return addk(fs, &o, &o); } static int number_constant (FuncState *fs, lua_Number r) { TObject o; setnvalue(&o, r); - return addk(fs, &o); + return addk(fs, &o, &o); +} + + +static int nil_constant (FuncState *fs) { + TObject k, v; + setnilvalue(&v); + sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */ + return addk(fs, &k, &v); } @@ -298,27 +306,29 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { } -static int code_label (FuncState *fs, OpCode op, int A, int sBc) { +static int code_label (FuncState *fs, int A, int b, int jump) { luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeAsBc(fs, op, A, sBc); + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); } static void dischargejumps (FuncState *fs, expdesc *e, int reg) { if (hasjumps(e)) { int final; /* position after whole expression */ - int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ - int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ + int p_f = NO_JUMP; /* position of an eventual PUSH false */ + int p_t = NO_JUMP; /* position of an eventual PUSH true */ if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { /* expression needs values */ - if (e->k != VJMP) - code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ - p_nil = code_label(fs, OP_NILJMP, reg, 0); - p_1 = code_label(fs, OP_LOADINT, reg, 1); + if (e->k != VJMP) { + luaK_getlabel(fs); /* these instruction may be jump target */ + luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */ + } + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); } final = luaK_getlabel(fs); - luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); - luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); + luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); + luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); } e->f = e->t = NO_JUMP; } @@ -331,6 +341,10 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_nil(fs, reg, 1); break; } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } case VNUMBER: { lua_Number f = e->u.n; int i = cast(int, f); @@ -424,13 +438,25 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { int luaK_exp2RK (FuncState *fs, expdesc *e) { luaK_exp2val(fs, e); - if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { - e->u.i.info = number_constant(fs, e->u.n); - e->k = VK; + switch (e->k) { + case VNUMBER: case VNIL: { + if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */ + e->u.i.info = (e->k == VNIL) ? nil_constant(fs) : + number_constant(fs, e->u.n); + e->k = VK; + return e->u.i.info + MAXSTACK; + } + else break; + } + case VK: { + if (e->u.i.info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */ + return e->u.i.info + MAXSTACK; + else break; + } + default: break; } - else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) - luaK_exp2anyreg(fs, e); /* not a constant in the right range */ - return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info; + /* not a constant in the right range: put in a register */ + return luaK_exp2anyreg(fs, e); } @@ -521,11 +547,11 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e->k) { - case VK: case VNUMBER: { + case VK: case VNUMBER: case VTRUE: { pc = NO_JUMP; /* always true; do nothing */ break; } - case VNIL: { + case VFALSE: { pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ break; } @@ -534,14 +560,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { pc = e->u.i.info; break; } - case VRELOCABLE: - case VNONRELOC: { - pc = jumponcond(fs, e, OP_TESTF); - break; - } default: { - pc = 0; /* to avoid warnings */ - lua_assert(0); /* cannot happen */ + pc = jumponcond(fs, e, OP_TESTF); break; } } @@ -555,23 +575,20 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e->k) { - case VNIL: { + case VNIL: case VFALSE: { pc = NO_JUMP; /* always false; do nothing */ break; } - case VJMP: { - pc = e->u.i.info; + case VTRUE: { + pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ break; } - case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ - case VRELOCABLE: - case VNONRELOC: { - pc = jumponcond(fs, e, OP_TESTT); + case VJMP: { + pc = e->u.i.info; break; } default: { - pc = 0; /* to avoid warnings */ - lua_assert(0); /* cannot happen */ + pc = jumponcond(fs, e, OP_TESTT); break; } } @@ -584,13 +601,12 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) { static void codenot (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); switch (e->k) { - case VNIL: { - e->u.n = 1; - e->k = VNUMBER; + case VNIL: case VFALSE: { + e->k = VTRUE; break; } - case VK: case VNUMBER: { - e->k = VNIL; + case VK: case VNUMBER: case VTRUE: { + e->k = VFALSE; break; } case VJMP: { @@ -719,23 +735,6 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { } break; } - case OPR_EQ: case OPR_NE: { - luaK_exp2val(fs, e2); - if (e2->k == VNIL) { /* exp x= nil ? */ - if (e1->k == VK) { /* constant x= nil ? */ - if (op == OPR_EQ) /* constant == nil ? */ - e1->k = VNIL; /* always false */ - /* else always true (leave the constant itself) */ - } - else { - OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT; - e1->u.i.info = jumponcond(fs, e1, opc); - e1->k = VJMP; - } - break; - } - /* else go through */ - } default: { int o1, o2; OpCode opc; diff --git a/ldebug.c b/ldebug.c index 954c68c0..410bbbbf 100644 --- a/ldebug.c +++ b/ldebug.c @@ -359,6 +359,10 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { if (testOpMode(op, OpModeT)) check(GET_OPCODE(pt->code[pc+1]) == OP_CJMP); switch (op) { + case OP_LOADBOOL: { + check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ + break; + } case OP_LOADNIL: { if (a <= reg && reg <= b) last = pc; /* set registers from `a' to `b' */ @@ -393,10 +397,6 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { pc += b; /* do the jump */ break; } - case OP_NILJMP: { - check(pc+2 < pt->sizecode); /* check its jump */ - break; - } case OP_CALL: { if (b != NO_REG) { checkreg(pt, a+b); diff --git a/lgc.c b/lgc.c index 29586007..e70dbc77 100644 --- a/lgc.c +++ b/lgc.c @@ -110,7 +110,9 @@ static void markobject (GCState *st, TObject *o) { break; } default: { - lua_assert(ttype(o) == LUA_TNIL || ttype(o) == LUA_TNUMBER); + lua_assert(ttype(o) == LUA_TNIL || + ttype(o) == LUA_TNUMBER || + ttype(o) == LUA_TBOOLEAN); break; } } @@ -196,7 +198,7 @@ static int hasmark (const TObject *o) { return ismarked(hvalue(o)); case LUA_TFUNCTION: return clvalue(o)->c.marked; - default: /* number, nil */ + default: /* number, nil, boolean */ return 1; } } diff --git a/llex.c b/llex.c index 6fb02f17..08815def 100644 --- a/llex.c +++ b/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 1.92 2001/11/16 16:29:10 roberto Exp $ +** $Id: llex.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -27,9 +27,9 @@ /* ORDER RESERVED */ static const char *const token2string [] = { "and", "break", "do", "else", "elseif", - "end", "for", "function", "global", "if", + "end", "false", "for", "function", "global", "if", "in", "local", "nil", "not", "or", "repeat", - "return", "then", "until", "while", "", + "return", "then", "true", "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", "" }; diff --git a/llex.h b/llex.h index d90ff2d7..8f0ae213 100644 --- a/llex.h +++ b/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.39 2001/11/16 16:29:10 roberto Exp $ +** $Id: llex.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -24,9 +24,9 @@ enum RESERVED { /* terminal symbols denoted by reserved words */ TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FOR, TK_FUNCTION, TK_GLOBAL, TK_IF, - TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, - TK_UNTIL, TK_WHILE, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_GLOBAL, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, /* other terminal symbols */ TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, TK_STRING, TK_EOS diff --git a/lobject.c b/lobject.c index 67ba2b62..15ae4893 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 1.71 2001/10/25 19:14:14 roberto Exp $ +** $Id: lobject.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -57,6 +57,8 @@ int luaO_equalObj (const TObject *t1, const TObject *t2) { return nvalue(t1) == nvalue(t2); case LUA_TNIL: return 1; + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); default: /* all other types are equal if pointers are equal */ return tsvalue(t1) == tsvalue(t2); } diff --git a/lobject.h b/lobject.h index bf07e3db..9d197af2 100644 --- a/lobject.h +++ b/lobject.h @@ -37,7 +37,8 @@ typedef union { union Closure *cl; struct Table *h; struct lua_TObject *v; - lua_Number n; /* LUA_TNUMBER */ + lua_Number n; + int b; } Value; @@ -55,7 +56,10 @@ typedef struct lua_TObject { #define clvalue(o) ((o)->value.cl) #define hvalue(o) ((o)->value.h) #define vvalue(o) ((o)->value.v) +#define bvalue(o) ((o)->value.b) +#define l_isfalse(o) (ttype(o) == LUA_TNIL || \ + (ttype(o) == LUA_TBOOLEAN && bvalue(o) == 0)) /* Macros to set values */ #define setnvalue(obj,x) \ @@ -63,6 +67,9 @@ typedef struct lua_TObject { #define chgnvalue(obj,x) ((obj)->value.n=(x)) +#define setbvalue(obj,x) \ + { TObject *_o=(obj); _o->tt=LUA_TBOOLEAN; _o->value.b=(x); } + #define setsvalue(obj,x) \ { TObject *_o=(obj); _o->tt=LUA_TSTRING; _o->value.ts=(x); } diff --git a/lopcodes.c b/lopcodes.c index c0974d96..e52805e5 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.6 2001/10/25 19:14:14 roberto Exp $ +** $Id: lopcodes.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** extracted automatically from lopcodes.h by mkprint.lua ** DO NOT EDIT ** See Copyright Notice in lua.h @@ -18,6 +18,7 @@ const char *const luaP_opnames[] = { "MOVE", "LOADK", "LOADINT", + "LOADBOOL", "LOADNIL", "GETUPVAL", "GETGLOBAL", @@ -45,7 +46,6 @@ const char *const luaP_opnames[] = { "TESTGE", "TESTT", "TESTF", - "NILJMP", "CALL", "RETURN", "FORPREP", @@ -69,6 +69,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */ ,opmode(0,0,0,0, 1,1,iABc) /* OP_LOADK */ ,opmode(0,0,0,0, 1,0,iAsBc) /* OP_LOADINT */ + ,opmode(0,0,0,0, 1,0,iABC) /* OP_LOADBOOL */ ,opmode(0,0,1,0, 1,0,iABC) /* OP_LOADNIL */ ,opmode(0,0,0,0, 1,0,iABC) /* OP_GETUPVAL */ ,opmode(0,0,0,0, 1,1,iABc) /* OP_GETGLOBAL */ @@ -96,7 +97,6 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(1,0,0,1, 0,0,iABC) /* OP_TESTGE */ ,opmode(1,0,1,0, 1,0,iABC) /* OP_TESTT */ ,opmode(1,0,1,0, 1,0,iABC) /* OP_TESTF */ - ,opmode(0,0,0,0, 1,0,iABc) /* OP_NILJMP */ ,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */ ,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */ ,opmode(0,0,0,0, 0,0,iAsBc) /* OP_FORPREP */ diff --git a/lopcodes.h b/lopcodes.h index ce09a7a4..b9539a9a 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.82 2001/10/25 19:14:14 roberto Exp $ +** $Id: lopcodes.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -130,6 +130,7 @@ name args description OP_MOVE,/* A B R(A) := R(B) */ OP_LOADK,/* A Bc R(A) := Kst(Bc) */ OP_LOADINT,/* A sBc R(A) := (Number)sBc */ +OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) PC++ */ OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ OP_GETUPVAL,/* A B R(A) := UpValue[B] */ @@ -165,9 +166,7 @@ OP_TESTGT,/* A C test := (R(A) > R/K(C)) */ OP_TESTGE,/* A C test := (R(A) >= R/K(C)) */ OP_TESTT,/* A B test := R(B); if (test) R(A) := R(B) */ -OP_TESTF,/* A B test := not R(B); if (test) R(A) := nil */ - -OP_NILJMP,/* A Bc R(A) := nil; PC++; */ +OP_TESTF,/* A B test := not R(B); if (test) R(A) := R(B) */ OP_CALL,/* A B C R(A), ... ,R(A+C-1) := R(A)(R(A+1), ... ,R(A+B))*/ OP_RETURN,/* A B return R(A), ... ,R(A+B-1) (see (3)) */ diff --git a/lparser.c b/lparser.c index f5d722c4..838e6336 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.160 2001/10/25 19:14:14 roberto Exp $ +** $Id: lparser.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -701,6 +701,16 @@ static void simpleexp (LexState *ls, expdesc *v) { next(ls); break; } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + next(ls); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + next(ls); + break; + } case '{': { /* constructor */ constructor(ls, v); break; diff --git a/lparser.h b/lparser.h index 724230a8..70c44543 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.35 2001/09/07 17:39:10 roberto Exp $ +** $Id: lparser.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -32,6 +32,8 @@ typedef enum { VVOID, /* no value */ VNIL, + VTRUE, + VFALSE, VNUMBER, /* n = value */ VK, /* info = index of constant in `k' */ VLOCAL, /* info = local register */ diff --git a/ltable.c b/ltable.c index 06e42a79..ac721f41 100644 --- a/ltable.c +++ b/ltable.c @@ -52,6 +52,7 @@ #define hashnum(t,n) \ (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t)))) #define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t)))) +#define hashboolean(t,p) (node(t, lmod(p, sizenode(t)))) #define hashpointer(t,p) (node(t, lmod(IntPoint(p), sizenode(t)))) @@ -65,6 +66,8 @@ Node *luaH_mainposition (const Table *t, const TObject *key) { return hashnum(t, nvalue(key)); case LUA_TSTRING: return hashstr(t, tsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); default: /* all other types are hashed as (void *) */ return hashpointer(t, tsvalue(key)); } diff --git a/ltests.c b/ltests.c index 282c58b6..feeeaee9 100644 --- a/ltests.c +++ b/ltests.c @@ -580,17 +580,11 @@ static int testC (lua_State *L) { } else if EQ("lessthan") { int a = getnum; - if (lua_lessthan(L, a, getnum)) - lua_pushnumber(L, 1); - else - lua_pushnil(L); + lua_pushboolean(L, lua_lessthan(L, a, getnum)); } else if EQ("equal") { int a = getnum; - if (lua_equal(L, a, getnum)) - lua_pushnumber(L, 1); - else - lua_pushnil(L); + lua_pushboolean(L, lua_equal(L, a, getnum)); } else if EQ("rawcall") { int narg = getnum; diff --git a/ltm.c b/ltm.c index 5e5f1ab2..62c3b38a 100644 --- a/ltm.c +++ b/ltm.c @@ -19,7 +19,7 @@ const char *const luaT_typenames[] = { - "userdata", "nil", "number", "string", "table", "function" + "userdata", "nil", "number", "boolean", "string", "table", "function" }; diff --git a/lua.h b/lua.h index fd7efb04..61d9e973 100644 --- a/lua.h +++ b/lua.h @@ -64,9 +64,10 @@ typedef int (*lua_CFunction) (lua_State *L); #define LUA_TUSERDATA 0 #define LUA_TNIL 1 #define LUA_TNUMBER 2 -#define LUA_TSTRING 3 -#define LUA_TTABLE 4 -#define LUA_TFUNCTION 5 +#define LUA_TBOOLEAN 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 /* minimum Lua stack available to a C function */ @@ -117,6 +118,7 @@ LUA_API int lua_stackspace (lua_State *L); */ LUA_API int lua_isnumber (lua_State *L, int index); +LUA_API int lua_istrue (lua_State *L, int index); LUA_API int lua_isstring (lua_State *L, int index); LUA_API int lua_iscfunction (lua_State *L, int index); LUA_API int lua_type (lua_State *L, int index); @@ -126,6 +128,7 @@ LUA_API int lua_equal (lua_State *L, int index1, int index2); LUA_API int lua_lessthan (lua_State *L, int index1, int index2); LUA_API lua_Number lua_tonumber (lua_State *L, int index); +LUA_API int lua_toboolean (lua_State *L, int index); LUA_API const char *lua_tostring (lua_State *L, int index); LUA_API size_t lua_strlen (lua_State *L, int index); LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index); @@ -141,6 +144,7 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n); LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); LUA_API void lua_pushstring (lua_State *L, const char *s); LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); +LUA_API void lua_pushboolean (lua_State *L, int b); /* @@ -222,6 +226,7 @@ LUA_API int lua_getweakmode (lua_State *L, int index); #define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) #define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) #define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN) #define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) #define lua_pushliteral(L, s) lua_pushlstring(L, "" s, \ diff --git a/lvm.c b/lvm.c index b49d8365..253c01a4 100644 --- a/lvm.c +++ b/lvm.c @@ -223,7 +223,7 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { else { /* try TM */ if (!call_binTM(L, l, r, L->top, TM_LT)) luaG_ordererror(L, l, r); - return (ttype(L->top) != LUA_TNIL); + return !l_isfalse(L->top); } } @@ -369,6 +369,11 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { setnvalue(ra, (lua_Number)GETARG_sBc(i)); break; } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + break; + } case OP_LOADNIL: { TObject *rb = RB(i); do { @@ -450,11 +455,8 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { break; } case OP_NOT: { - if (ttype(RB(i)) == LUA_TNIL) { - setnvalue(ra, 1); - } else { - setnilvalue(ra); - } + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); break; } case OP_CONCAT: { @@ -508,7 +510,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { case OP_TESTT: { StkId rb = RB(i); lua_assert(GET_OPCODE(*pc) == OP_CJMP); - if (ttype(rb) != LUA_TNIL) { + if (!l_isfalse(rb)) { setobj(ra, rb); dojump(pc, *pc); } @@ -516,19 +518,15 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { break; } case OP_TESTF: { + StkId rb = RB(i); lua_assert(GET_OPCODE(*pc) == OP_CJMP); - if (ttype(RB(i)) == LUA_TNIL) { - setnilvalue(ra); + if (l_isfalse(rb)) { + setobj(ra, rb); dojump(pc, *pc); } pc++; break; } - case OP_NILJMP: { - setnilvalue(ra); - pc++; - break; - } case OP_CALL: { int c; int b = GETARG_B(i); -- cgit v1.2.3-55-g6feb