diff -ru lua/include/lua.h lua-4.0-bool/include/lua.h --- lua/include/lua.h Tue Oct 31 13:44:07 2000 +++ lua-4.0-bool/include/lua.h Fri Sep 21 00:35:33 2001 @@ -32,7 +32,8 @@ /* pre-defined references */ -#define LUA_NOREF (-2) +#define LUA_NOREF (-3) +#define LUA_REFFALSE (-2) #define LUA_REFNIL (-1) #define LUA_REFREGISTRY 0 @@ -68,10 +69,11 @@ #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_TFALSE 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 @@ -102,6 +104,7 @@ LUA_API int lua_isnumber (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_istrue (lua_State *L, int index); LUA_API int lua_tag (lua_State *L, int index); LUA_API int lua_equal (lua_State *L, int index1, int index2); @@ -119,6 +122,7 @@ ** push functions (C -> stack) */ LUA_API void lua_pushnil (lua_State *L); +LUA_API void lua_pushfalse (lua_State *L); LUA_API void lua_pushnumber (lua_State *L, double 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); @@ -203,6 +207,7 @@ #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_isfalse(L,n) (lua_type(L,n) == LUA_TFALSE) #define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) #define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) diff -ru lua/src/lapi.c lua-4.0-bool/src/lapi.c --- lua/src/lapi.c Mon Oct 30 13:50:09 2000 +++ lua-4.0-bool/src/lapi.c Fri Sep 21 00:36:24 2001 @@ -122,6 +122,11 @@ return (o == NULL) ? 0 : iscfunction(o); } +LUA_API int lua_istrue (lua_State *L, int index) { + StkId o = luaA_indexAcceptable(L, index); + return (o == NULL) ? 0 : istrue(o); +} + LUA_API int lua_isnumber (lua_State *L, int index) { TObject *o = luaA_indexAcceptable(L, index); return (o == NULL) ? 0 : (tonumber(o) == 0); @@ -205,6 +210,12 @@ } +LUA_API void lua_pushfalse (lua_State *L) { + ttype(L->top) = LUA_TFALSE; + api_incr_top(L); +} + + LUA_API void lua_pushnumber (lua_State *L, double n) { nvalue(L->top) = n; ttype(L->top) = LUA_TNUMBER; @@ -289,6 +300,8 @@ LUA_API int lua_getref (lua_State *L, int ref) { if (ref == LUA_REFNIL) ttype(L->top) = LUA_TNIL; + else if (ref == LUA_REFFALSE) + ttype(L->top) = LUA_TFALSE; else if (0 <= ref && ref < L->refSize && (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD)) *L->top = L->refArray[ref].o; @@ -354,6 +367,8 @@ int ref; if (ttype(L->top-1) == LUA_TNIL) ref = LUA_REFNIL; + else if (ttype(L->top-1) == LUA_TFALSE) + ref = LUA_REFFALSE; else { if (L->refFree != NONEXT) { /* is there a free place? */ ref = L->refFree; diff -ru lua/src/lcode.c lua-4.0-bool/src/lcode.c --- lua/src/lcode.c Fri Sep 29 14:42:13 2000 +++ lua-4.0-bool/src/lcode.c Fri Sep 21 00:22:20 2001 @@ -321,7 +321,7 @@ else { /* expression has jumps */ int final; /* position after whole expression */ int j = NO_JUMP; /* eventual jump over values */ - int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ + int p_nil = NO_JUMP; /* position of an eventual PUSHFALSE */ int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) || need_value(fs, v->u.l.t, OP_JMPONT)) { @@ -333,7 +333,7 @@ /* correct stack for compiler and symbolic execution */ luaK_adjuststack(fs, 1); } - p_nil = code_label(fs, OP_PUSHNILJMP, 0); + p_nil = code_label(fs, OP_PUSHFALSESKIP, 0); p_1 = code_label(fs, OP_PUSHINT, 1); luaK_patchlist(fs, j, luaK_getlabel(fs)); } @@ -548,6 +548,12 @@ } break; } +#if 0 + /* ET: + ** These optimizations do not work with two _different_ false values. + ** "if x~=nil" is not the same as "if x" + ** "if x==nil" is not the same as "if not x" + */ case OP_JMPNE: { if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ i = CREATE_S(OP_JMPT, NO_JUMP); @@ -563,6 +569,7 @@ } break; } +#endif case OP_JMPT: case OP_JMPONT: { switch (GET_OPCODE(i)) { @@ -578,8 +585,9 @@ } break; } + case OP_PUSHFALSE: case OP_PUSHNIL: { - if (GETARG_U(i) == 1) { + if (i == CREATE_0(OP_PUSHFALSE) || GETARG_U(i) == 1) { fs->pc--; /* erase previous instruction */ luaK_deltastack(fs, -1); /* correct stack */ return NO_JUMP; @@ -603,8 +611,10 @@ luaK_deltastack(fs, -1); /* correct stack */ return NO_JUMP; } + case OP_PUSHFALSE: case OP_PUSHNIL: { /* `repeat ... until nil' */ - if (GETARG_U(i) == 1) { + if (o == OP_JMPF) /*ET: JMPONF must keep the nil/false value */ + if (i == CREATE_0(OP_PUSHFALSE) || GETARG_U(i) == 1) { i = CREATE_S(OP_JMP, NO_JUMP); optm = 1; } @@ -652,6 +662,7 @@ {iU, 0, 0}, /* OP_RETURN */ {iAB, 0, 0}, /* OP_CALL */ {iAB, 0, 0}, /* OP_TAILCALL */ + {iO, 1, 0}, /* OP_PUSHFALSE */ {iU, VD, 0}, /* OP_PUSHNIL */ {iU, VD, 0}, /* OP_POP */ {iS, 1, 0}, /* OP_PUSHINT */ @@ -691,7 +702,7 @@ {iS, 0, 1}, /* OP_JMPONT */ {iS, 0, 1}, /* OP_JMPONF */ {iS, 0, 0}, /* OP_JMP */ - {iO, 0, 0}, /* OP_PUSHNILJMP */ + {iO, 0, 0}, /* OP_PUSHFALSESKIP */ {iS, 0, 0}, /* OP_FORPREP */ {iS, 0, 3}, /* OP_FORLOOP */ {iS, 2, 0}, /* OP_LFORPREP */ diff -ru lua/src/lib/lbaselib.c lua-4.0-bool/src/lib/lbaselib.c --- lua/src/lib/lbaselib.c Mon Nov 6 14:45:18 2000 +++ lua-4.0-bool/src/lib/lbaselib.c Fri Sep 21 00:37:30 2001 @@ -326,6 +326,9 @@ case LUA_TUSERDATA: sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), lua_touserdata(L, 1)); break; + case LUA_TFALSE: + lua_pushstring(L, "false"); + return 1; case LUA_TNIL: lua_pushstring(L, "nil"); return 1; @@ -375,7 +378,7 @@ static int luaB_assert (lua_State *L) { luaL_checkany(L, 1); - if (lua_isnil(L, 1)) + if (!lua_istrue(L, 1)) luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, "")); return 0; } @@ -453,7 +456,7 @@ 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 -ru lua/src/llex.c lua-4.0-bool/src/llex.c --- lua/src/llex.c Fri Oct 20 18:39:03 2000 +++ lua-4.0-bool/src/llex.c Thu Sep 20 22:04:36 2001 @@ -29,7 +29,7 @@ /* ORDER RESERVED */ static const char *const token2string [] = { - "and", "break", "do", "else", "elseif", "end", "for", + "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", ""}; diff -ru lua/src/llex.h lua-4.0-bool/src/llex.h --- lua/src/llex.h Wed Sep 27 19:41:58 2000 +++ lua-4.0-bool/src/llex.h Thu Sep 20 22:05:24 2001 @@ -23,8 +23,8 @@ */ 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_IF, TK_LOCAL, + TK_AND = FIRST_RESERVED, TK_BREAK, TK_DO, + TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, TK_IF, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, /* other terminal symbols */ TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, diff -ru lua/src/lobject.c lua-4.0-bool/src/lobject.c --- lua/src/lobject.c Fri Oct 20 18:36:32 2000 +++ lua-4.0-bool/src/lobject.c Thu Sep 20 22:03:57 2001 @@ -21,8 +21,8 @@ const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; -const char *const luaO_typenames[] = { - "userdata", "nil", "number", "string", "table", "function" +const char *const luaO_typenames[] = { /* ORDER LUA_T */ + "userdata", "nil", "false", "number", "string", "table", "function" }; @@ -49,8 +49,8 @@ case LUA_TFUNCTION: return clvalue(t1) == clvalue(t2); default: - LUA_ASSERT(ttype(t1) == LUA_TNIL, "invalid type"); - return 1; /* LUA_TNIL */ + LUA_ASSERT(ttype(t1) == LUA_TNIL || ttype(t1) == LUA_TFALSE, "invalid type"); + return 1; /* LUA_TNIL, LUA_TFALSE */ } } diff -ru lua/src/lobject.h lua-4.0-bool/src/lobject.h --- lua/src/lobject.h Mon Oct 30 18:49:19 2000 +++ lua-4.0-bool/src/lobject.h Thu Sep 20 21:56:49 2001 @@ -32,11 +32,11 @@ /* mark for closures active in the stack */ -#define LUA_TMARK 6 +#define LUA_TMARK 7 /* tags for values visible from Lua == first user-created tag */ -#define NUM_TAGS 6 +#define NUM_TAGS 7 /* check whether `t' is a mark */ @@ -148,6 +148,7 @@ #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) +#define istrue(o) (ttype(o) != LUA_TNIL && ttype(o) != LUA_TFALSE) typedef struct Node { diff -ru lua/src/lopcodes.h lua-4.0-bool/src/lopcodes.h --- lua/src/lopcodes.h Tue Oct 24 18:05:59 2000 +++ lua-4.0-bool/src/lopcodes.h Fri Sep 21 00:26:42 2001 @@ -76,6 +76,7 @@ ** J = S argument used as jump offset (relative to pc of next instruction) ** L = unsigned argument used as index of local variable ** N = U argument used as index to `knum' +** (Note: comparisons to nil (true/false tests) handle false too.) */ typedef enum { @@ -88,6 +89,7 @@ OP_CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ OP_TAILCALL,/* A B v_n-v_1 f(at a) (return) f(v1,...,v_n) */ +OP_PUSHFALSE,/* - - false */ OP_PUSHNIL,/* U - nil_1-nil_u */ OP_POP,/* U a_u-a_1 - */ @@ -123,7 +125,7 @@ OP_POW,/* - y x x^y */ OP_CONCAT,/* U v_u-v_1 v1..-..v_u */ OP_MINUS,/* - x -x */ -OP_NOT,/* - x (x==nil)? 1 : nil */ +OP_NOT,/* - x (x==nil)? 1 : false */ OP_JMPNE,/* J y x - (x~=y)? PC+=s */ OP_JMPEQ,/* J y x - (x==y)? PC+=s */ @@ -138,7 +140,7 @@ OP_JMPONF,/* J x (x==nil)? x : - (x==nil)? PC+=s */ OP_JMP,/* J - - PC+=s */ -OP_PUSHNILJMP,/* - - nil PC++; */ +OP_PUSHFALSESKIP,/* - - false PC++; */ OP_FORPREP,/* J */ OP_FORLOOP,/* J */ diff -ru lua/src/lparser.c lua-4.0-bool/src/lparser.c --- lua/src/lparser.c Fri Oct 27 13:39:52 2000 +++ lua-4.0-bool/src/lparser.c Thu Sep 20 22:07:24 2001 @@ -623,6 +623,11 @@ next(ls); break; } + case TK_FALSE: { /* simpleexp -> FALSE */ + luaK_code0(fs, OP_PUSHFALSE); + next(ls); + break; + } case '{': { /* simpleexp -> constructor */ constructor(ls); break; diff -ru lua/src/ltable.c lua-4.0-bool/src/ltable.c --- lua/src/ltable.c Thu Oct 26 14:47:05 2000 +++ lua-4.0-bool/src/ltable.c Thu Sep 20 21:49:34 2001 @@ -57,6 +57,9 @@ case LUA_TFUNCTION: h = IntPoint(clvalue(key)); break; + case LUA_TFALSE: + h = 0; + break; default: return NULL; /* invalid key */ } @@ -138,9 +141,9 @@ ** hash, change `key' for a number with the same hash. */ void luaH_remove (Hash *t, TObject *key) { - if (ttype(key) == LUA_TNUMBER || + if (ttype(key) == LUA_TNUMBER || ttype(key) == LUA_TFALSE || (ttype(key) == LUA_TSTRING && tsvalue(key)->len <= 30)) - return; /* do not remove numbers nor small strings */ + return; /* do not remove false, numbers, or small strings */ else { /* try to find a number `n' with the same hash as `key' */ Node *mp = luaH_mainposition(t, key); diff -ru lua/src/ltests.c lua-4.0-bool/src/ltests.c --- lua/src/ltests.c Tue Oct 31 14:10:24 2000 +++ lua-4.0-bool/src/ltests.c Fri Sep 21 00:37:59 2001 @@ -417,6 +417,9 @@ else if EQ("isnil") { lua_pushnumber(L, lua_isnil(L, getnum)); } + else if EQ("istrue") { + lua_pushnumber(L, lua_istrue(L, getnum)); + } else if EQ("isnull") { lua_pushnumber(L, lua_isnull(L, getnum)); } diff -ru lua/src/ltm.c lua-4.0-bool/src/ltm.c --- lua/src/ltm.c Tue Oct 31 14:10:24 2000 +++ lua-4.0-bool/src/ltm.c Thu Sep 20 22:02:50 2001 @@ -54,6 +54,7 @@ static const char luaT_validevents[NUM_TAGS][TM_N] = { {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */ + {1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TFALSE */ {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */ {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */ {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */ diff -ru lua/src/luac/print.h lua-4.0-bool/src/luac/print.h --- lua/src/luac/print.h Mon Nov 6 21:03:12 2000 +++ lua-4.0-bool/src/luac/print.h Thu Sep 20 22:29:58 2001 @@ -8,6 +8,7 @@ case OP_RETURN: P_OP("RETURN"); P_U; break; case OP_CALL: P_OP("CALL"); P_AB; break; case OP_TAILCALL: P_OP("TAILCALL"); P_AB; break; + case OP_PUSHFALSE: P_OP("PUSHFALSE"); P_NONE; break; case OP_PUSHNIL: P_OP("PUSHNIL"); P_U; break; case OP_POP: P_OP("POP"); P_U; break; case OP_PUSHINT: P_OP("PUSHINT"); P_S; break; @@ -47,7 +48,7 @@ case OP_JMPONT: P_OP("JMPONT"); P_J; break; case OP_JMPONF: P_OP("JMPONF"); P_J; break; case OP_JMP: P_OP("JMP"); P_J; break; - case OP_PUSHNILJMP: P_OP("PUSHNILJMP"); P_NONE; break; + case OP_PUSHFALSESKIP: P_OP("PUSHFALSESKIP"); P_NONE; break; case OP_FORPREP: P_OP("FORPREP"); P_J; break; case OP_FORLOOP: P_OP("FORLOOP"); P_J; break; case OP_LFORPREP: P_OP("LFORPREP"); P_J; break; diff -ru lua/src/lvm.c lua-4.0-bool/src/lvm.c --- lua/src/lvm.c Thu Oct 26 14:47:05 2000 +++ lua-4.0-bool/src/lvm.c Thu Sep 20 22:57:16 2001 @@ -281,7 +281,7 @@ if (!call_binTM(L, top, TM_LT)) luaG_ordererror(L, top-2); L->top--; - return (ttype(L->top) != LUA_TNIL); + return istrue(L->top); } } @@ -388,6 +388,10 @@ luaD_call(L, base+GETARG_A(i), LUA_MULTRET); return base+GETARG_B(i); } + case OP_PUSHFALSE: { + ttype(top++) = LUA_TFALSE; + break; + } case OP_PUSHNIL: { int n = GETARG_U(i); LUA_ASSERT(n>0, "invalid argument"); @@ -578,8 +582,7 @@ break; } case OP_NOT: { - ttype(top-1) = - (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; + ttype(top-1) = istrue(top - 1) ? LUA_TFALSE : LUA_TNUMBER; nvalue(top-1) = 1; break; } @@ -614,20 +617,22 @@ break; } case OP_JMPT: { - if (ttype(--top) != LUA_TNIL) dojump(pc, i); + --top; + if (istrue(top)) dojump(pc, i); break; } case OP_JMPF: { - if (ttype(--top) == LUA_TNIL) dojump(pc, i); + --top; + if (!istrue(top)) dojump(pc, i); break; } case OP_JMPONT: { - if (ttype(top-1) == LUA_TNIL) top--; + if (!istrue(top-1)) top--; else dojump(pc, i); break; } case OP_JMPONF: { - if (ttype(top-1) != LUA_TNIL) top--; + if (istrue(top-1)) top--; else dojump(pc, i); break; } @@ -635,8 +640,8 @@ dojump(pc, i); break; } - case OP_PUSHNILJMP: { - ttype(top++) = LUA_TNIL; + case OP_PUSHFALSESKIP: { + ttype(top++) = LUA_TFALSE; pc++; break; }