diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-26 14:59:39 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-26 14:59:39 -0300 |
| commit | b80077b8f3e27a94c6afa895b41a9f8b52c42e61 (patch) | |
| tree | 8a7c21ee0acfed553ef1d92bdfd7b1f728f35a91 | |
| parent | e70f275f32a5339a86be6f8b9d08c20cb874b205 (diff) | |
| download | lua-b80077b8f3e27a94c6afa895b41a9f8b52c42e61.tar.gz lua-b80077b8f3e27a94c6afa895b41a9f8b52c42e61.tar.bz2 lua-b80077b8f3e27a94c6afa895b41a9f8b52c42e61.zip | |
Change in the handling of 'L->top' when calling metamethods
Instead of updating 'L->top' in every place that may call a
metamethod, the metamethod functions themselves (luaT_trybinTM and
luaT_callorderTM) correct the top. (When calling metamethods from
the C API, however, the callers must preserve 'L->top'.)
| -rw-r--r-- | lapi.c | 2 | ||||
| -rw-r--r-- | lobject.c | 2 | ||||
| -rw-r--r-- | lopcodes.c | 2 | ||||
| -rw-r--r-- | ltm.c | 12 | ||||
| -rw-r--r-- | ltm.h | 1 | ||||
| -rw-r--r-- | lvm.c | 44 | ||||
| -rw-r--r-- | testes/api.lua | 17 | ||||
| -rw-r--r-- | testes/coroutine.lua | 2 | ||||
| -rw-r--r-- | testes/events.lua | 15 | ||||
| -rw-r--r-- | testes/strings.lua | 7 |
10 files changed, 75 insertions, 29 deletions
| @@ -329,12 +329,14 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { | |||
| 329 | o1 = index2value(L, index1); | 329 | o1 = index2value(L, index1); |
| 330 | o2 = index2value(L, index2); | 330 | o2 = index2value(L, index2); |
| 331 | if (isvalid(L, o1) && isvalid(L, o2)) { | 331 | if (isvalid(L, o1) && isvalid(L, o2)) { |
| 332 | ptrdiff_t top = savestack(L, L->top); | ||
| 332 | switch (op) { | 333 | switch (op) { |
| 333 | case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; | 334 | case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; |
| 334 | case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; | 335 | case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; |
| 335 | case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; | 336 | case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; |
| 336 | default: api_check(L, 0, "invalid option"); | 337 | default: api_check(L, 0, "invalid option"); |
| 337 | } | 338 | } |
| 339 | L->top = restorestack(L, top); | ||
| 338 | } | 340 | } |
| 339 | lua_unlock(L); | 341 | lua_unlock(L); |
| 340 | return i; | 342 | return i; |
| @@ -127,7 +127,9 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, | |||
| 127 | StkId res) { | 127 | StkId res) { |
| 128 | if (!luaO_rawarith(L, op, p1, p2, s2v(res))) { | 128 | if (!luaO_rawarith(L, op, p1, p2, s2v(res))) { |
| 129 | /* could not perform raw operation; try metamethod */ | 129 | /* could not perform raw operation; try metamethod */ |
| 130 | ptrdiff_t top = savestack(L, L->top); | ||
| 130 | luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); | 131 | luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); |
| 132 | L->top = restorestack(L, top); | ||
| 131 | } | 133 | } |
| 132 | } | 134 | } |
| 133 | 135 | ||
| @@ -101,7 +101,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
| 101 | ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ | 101 | ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ |
| 102 | ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ | 102 | ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ |
| 103 | ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ | 103 | ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ |
| 104 | ,opmode(0, 0, 0, 1, iABC) /* OP_VARARGPREP */ | 104 | ,opmode(0, 1, 0, 1, iABC) /* OP_VARARGPREP */ |
| 105 | ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ | 105 | ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| @@ -147,11 +147,9 @@ static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
| 147 | 147 | ||
| 148 | void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, | 148 | void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, |
| 149 | StkId res, TMS event) { | 149 | StkId res, TMS event) { |
| 150 | L->top = L->ci->top; | ||
| 150 | if (!callbinTM(L, p1, p2, res, event)) { | 151 | if (!callbinTM(L, p1, p2, res, event)) { |
| 151 | switch (event) { | 152 | switch (event) { |
| 152 | case TM_CONCAT: | ||
| 153 | luaG_concaterror(L, p1, p2); | ||
| 154 | /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ | ||
| 155 | case TM_BAND: case TM_BOR: case TM_BXOR: | 153 | case TM_BAND: case TM_BOR: case TM_BXOR: |
| 156 | case TM_SHL: case TM_SHR: case TM_BNOT: { | 154 | case TM_SHL: case TM_SHR: case TM_BNOT: { |
| 157 | if (ttisnumber(p1) && ttisnumber(p2)) | 155 | if (ttisnumber(p1) && ttisnumber(p2)) |
| @@ -167,6 +165,13 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
| 167 | } | 165 | } |
| 168 | 166 | ||
| 169 | 167 | ||
| 168 | void luaT_tryconcatTM (lua_State *L) { | ||
| 169 | StkId top = L->top; | ||
| 170 | if (!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT)) | ||
| 171 | luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); | ||
| 172 | } | ||
| 173 | |||
| 174 | |||
| 170 | void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, | 175 | void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, |
| 171 | StkId res, int flip, TMS event) { | 176 | StkId res, int flip, TMS event) { |
| 172 | if (flip) | 177 | if (flip) |
| @@ -186,6 +191,7 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, | |||
| 186 | 191 | ||
| 187 | int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, | 192 | int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, |
| 188 | TMS event) { | 193 | TMS event) { |
| 194 | L->top = L->ci->top; | ||
| 189 | if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ | 195 | if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ |
| 190 | return !l_isfalse(s2v(L->top)); | 196 | return !l_isfalse(s2v(L->top)); |
| 191 | #if defined(LUA_COMPAT_LT_LE) | 197 | #if defined(LUA_COMPAT_LT_LE) |
| @@ -75,6 +75,7 @@ LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f, | |||
| 75 | const TValue *p1, const TValue *p2, StkId p3); | 75 | const TValue *p1, const TValue *p2, StkId p3); |
| 76 | LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, | 76 | LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, |
| 77 | StkId res, TMS event); | 77 | StkId res, TMS event); |
| 78 | LUAI_FUNC void luaT_tryconcatTM (lua_State *L); | ||
| 78 | LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1, | 79 | LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1, |
| 79 | const TValue *p2, StkId res, int inv, TMS event); | 80 | const TValue *p2, StkId res, int inv, TMS event); |
| 80 | LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, | 81 | LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, |
| @@ -515,8 +515,11 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | |||
| 515 | } | 515 | } |
| 516 | if (tm == NULL) /* no TM? */ | 516 | if (tm == NULL) /* no TM? */ |
| 517 | return 0; /* objects are different */ | 517 | return 0; /* objects are different */ |
| 518 | luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ | 518 | else { |
| 519 | return !l_isfalse(s2v(L->top)); | 519 | L->top = L->ci->top; |
| 520 | luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ | ||
| 521 | return !l_isfalse(s2v(L->top)); | ||
| 522 | } | ||
| 520 | } | 523 | } |
| 521 | 524 | ||
| 522 | 525 | ||
| @@ -548,7 +551,7 @@ void luaV_concat (lua_State *L, int total) { | |||
| 548 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 551 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| 549 | if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || | 552 | if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || |
| 550 | !tostring(L, s2v(top - 1))) | 553 | !tostring(L, s2v(top - 1))) |
| 551 | luaT_trybinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT); | 554 | luaT_tryconcatTM(L); |
| 552 | else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ | 555 | else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ |
| 553 | cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ | 556 | cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ |
| 554 | else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ | 557 | else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ |
| @@ -747,7 +750,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 747 | break; | 750 | break; |
| 748 | } | 751 | } |
| 749 | case OP_CONCAT: { | 752 | case OP_CONCAT: { |
| 750 | StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ | 753 | StkId top = L->top - 1; /* top when 'luaT_tryconcatTM' was called */ |
| 751 | int a = GETARG_A(inst); /* first element to concatenate */ | 754 | int a = GETARG_A(inst); /* first element to concatenate */ |
| 752 | int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ | 755 | int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ |
| 753 | setobjs2s(L, top - 2, top); /* put TM result in proper position */ | 756 | setobjs2s(L, top - 2, top); /* put TM result in proper position */ |
| @@ -801,7 +804,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 801 | setfltvalue(s2v(ra), fop(L, nb, fimm)); \ | 804 | setfltvalue(s2v(ra), fop(L, nb, fimm)); \ |
| 802 | } \ | 805 | } \ |
| 803 | else \ | 806 | else \ |
| 804 | Protect(luaT_trybiniTM(L, v1, imm, flip, ra, tm)); } | 807 | ProtectNT(luaT_trybiniTM(L, v1, imm, flip, ra, tm)); } |
| 805 | 808 | ||
| 806 | 809 | ||
| 807 | /* | 810 | /* |
| @@ -836,7 +839,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 836 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ | 839 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ |
| 837 | } \ | 840 | } \ |
| 838 | else \ | 841 | else \ |
| 839 | Protect(luaT_trybinTM(L, v1, v2, ra, tm)); } | 842 | ProtectNT(luaT_trybinTM(L, v1, v2, ra, tm)); } |
| 840 | 843 | ||
| 841 | 844 | ||
| 842 | /* | 845 | /* |
| @@ -877,7 +880,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 877 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ | 880 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ |
| 878 | } \ | 881 | } \ |
| 879 | else \ | 882 | else \ |
| 880 | Protect(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } } | 883 | ProtectNT(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } } |
| 881 | 884 | ||
| 882 | 885 | ||
| 883 | /* | 886 | /* |
| @@ -891,7 +894,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 891 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ | 894 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ |
| 892 | } \ | 895 | } \ |
| 893 | else \ | 896 | else \ |
| 894 | Protect(luaT_trybinTM(L, v1, v2, ra, tm)); } | 897 | ProtectNT(luaT_trybinTM(L, v1, v2, ra, tm)); } |
| 895 | 898 | ||
| 896 | 899 | ||
| 897 | /* | 900 | /* |
| @@ -906,7 +909,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 906 | setivalue(s2v(ra), op(L, i1, i2)); \ | 909 | setivalue(s2v(ra), op(L, i1, i2)); \ |
| 907 | } \ | 910 | } \ |
| 908 | else \ | 911 | else \ |
| 909 | Protect(luaT_trybiniTM(L, v1, i2, TESTARG_k(i), ra, tm)); } | 912 | ProtectNT(luaT_trybiniTM(L, v1, i2, TESTARG_k(i), ra, tm)); } |
| 910 | 913 | ||
| 911 | 914 | ||
| 912 | /* | 915 | /* |
| @@ -920,7 +923,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 920 | setivalue(s2v(ra), op(L, i1, i2)); \ | 923 | setivalue(s2v(ra), op(L, i1, i2)); \ |
| 921 | } \ | 924 | } \ |
| 922 | else \ | 925 | else \ |
| 923 | Protect(luaT_trybinTM(L, v1, v2, ra, tm)); } | 926 | ProtectNT(luaT_trybinTM(L, v1, v2, ra, tm)); } |
| 924 | 927 | ||
| 925 | 928 | ||
| 926 | /* | 929 | /* |
| @@ -937,7 +940,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 937 | else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ | 940 | else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ |
| 938 | cond = opf(s2v(ra), rb); \ | 941 | cond = opf(s2v(ra), rb); \ |
| 939 | else \ | 942 | else \ |
| 940 | Protect(cond = other(L, s2v(ra), rb)); \ | 943 | ProtectNT(cond = other(L, s2v(ra), rb)); \ |
| 941 | docondjump(); } | 944 | docondjump(); } |
| 942 | 945 | ||
| 943 | 946 | ||
| @@ -956,7 +959,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 956 | } \ | 959 | } \ |
| 957 | else { \ | 960 | else { \ |
| 958 | int isf = GETARG_C(i); \ | 961 | int isf = GETARG_C(i); \ |
| 959 | Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ | 962 | ProtectNT(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ |
| 960 | } \ | 963 | } \ |
| 961 | docondjump(); } | 964 | docondjump(); } |
| 962 | 965 | ||
| @@ -1094,7 +1097,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1094 | vmfetch(); | 1097 | vmfetch(); |
| 1095 | lua_assert(base == ci->func + 1); | 1098 | lua_assert(base == ci->func + 1); |
| 1096 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); | 1099 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); |
| 1097 | lua_assert(ci->top < L->stack + L->stacksize); | 1100 | /* invalidate top for instructions not expecting it */ |
| 1101 | lua_assert(isIT(i) || (L->top = base)); | ||
| 1098 | vmdispatch (GET_OPCODE(i)) { | 1102 | vmdispatch (GET_OPCODE(i)) { |
| 1099 | vmcase(OP_MOVE) { | 1103 | vmcase(OP_MOVE) { |
| 1100 | setobjs2s(L, ra, RB(i)); | 1104 | setobjs2s(L, ra, RB(i)); |
| @@ -1359,7 +1363,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1359 | if (TESTARG_k(i)) { | 1363 | if (TESTARG_k(i)) { |
| 1360 | ic = -ic; ev = TM_SHL; | 1364 | ic = -ic; ev = TM_SHL; |
| 1361 | } | 1365 | } |
| 1362 | Protect(luaT_trybiniTM(L, rb, ic, 0, ra, ev)); | 1366 | ProtectNT(luaT_trybiniTM(L, rb, ic, 0, ra, ev)); |
| 1363 | } | 1367 | } |
| 1364 | vmbreak; | 1368 | vmbreak; |
| 1365 | } | 1369 | } |
| @@ -1371,7 +1375,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1371 | setivalue(s2v(ra), luaV_shiftl(ic, ib)); | 1375 | setivalue(s2v(ra), luaV_shiftl(ic, ib)); |
| 1372 | } | 1376 | } |
| 1373 | else | 1377 | else |
| 1374 | Protect(luaT_trybiniTM(L, rb, ic, 1, ra, TM_SHL)); | 1378 | ProtectNT(luaT_trybiniTM(L, rb, ic, 1, ra, TM_SHL)); |
| 1375 | vmbreak; | 1379 | vmbreak; |
| 1376 | } | 1380 | } |
| 1377 | vmcase(OP_ADD) { | 1381 | vmcase(OP_ADD) { |
| @@ -1422,7 +1426,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1422 | setivalue(s2v(ra), luaV_shiftl(ib, -ic)); | 1426 | setivalue(s2v(ra), luaV_shiftl(ib, -ic)); |
| 1423 | } | 1427 | } |
| 1424 | else | 1428 | else |
| 1425 | Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); | 1429 | ProtectNT(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); |
| 1426 | vmbreak; | 1430 | vmbreak; |
| 1427 | } | 1431 | } |
| 1428 | vmcase(OP_SHL) { | 1432 | vmcase(OP_SHL) { |
| @@ -1433,7 +1437,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1433 | setivalue(s2v(ra), luaV_shiftl(ib, ic)); | 1437 | setivalue(s2v(ra), luaV_shiftl(ib, ic)); |
| 1434 | } | 1438 | } |
| 1435 | else | 1439 | else |
| 1436 | Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); | 1440 | ProtectNT(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); |
| 1437 | vmbreak; | 1441 | vmbreak; |
| 1438 | } | 1442 | } |
| 1439 | vmcase(OP_UNM) { | 1443 | vmcase(OP_UNM) { |
| @@ -1447,7 +1451,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1447 | setfltvalue(s2v(ra), luai_numunm(L, nb)); | 1451 | setfltvalue(s2v(ra), luai_numunm(L, nb)); |
| 1448 | } | 1452 | } |
| 1449 | else | 1453 | else |
| 1450 | Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); | 1454 | ProtectNT(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); |
| 1451 | vmbreak; | 1455 | vmbreak; |
| 1452 | } | 1456 | } |
| 1453 | vmcase(OP_BNOT) { | 1457 | vmcase(OP_BNOT) { |
| @@ -1457,7 +1461,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1457 | setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); | 1461 | setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); |
| 1458 | } | 1462 | } |
| 1459 | else | 1463 | else |
| 1460 | Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); | 1464 | ProtectNT(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); |
| 1461 | vmbreak; | 1465 | vmbreak; |
| 1462 | } | 1466 | } |
| 1463 | vmcase(OP_NOT) { | 1467 | vmcase(OP_NOT) { |
| @@ -1493,7 +1497,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1493 | vmcase(OP_EQ) { | 1497 | vmcase(OP_EQ) { |
| 1494 | int cond; | 1498 | int cond; |
| 1495 | TValue *rb = vRB(i); | 1499 | TValue *rb = vRB(i); |
| 1496 | Protect(cond = luaV_equalobj(L, s2v(ra), rb)); | 1500 | ProtectNT(cond = luaV_equalobj(L, s2v(ra), rb)); |
| 1497 | docondjump(); | 1501 | docondjump(); |
| 1498 | vmbreak; | 1502 | vmbreak; |
| 1499 | } | 1503 | } |
diff --git a/testes/api.lua b/testes/api.lua index 5da03641..0966ed19 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
| @@ -241,6 +241,23 @@ assert(a == 20 and b == false) | |||
| 241 | a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a1, 2, 20) | 241 | a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a1, 2, 20) |
| 242 | assert(a == 20 and b == true) | 242 | assert(a == 20 and b == true) |
| 243 | 243 | ||
| 244 | |||
| 245 | do -- testing lessthan and lessequal with metamethods | ||
| 246 | local mt = {__lt = function (a,b) return a[1] < b[1] end, | ||
| 247 | __le = function (a,b) return a[1] <= b[1] end, | ||
| 248 | __eq = function (a,b) return a[1] == b[1] end} | ||
| 249 | local function O (x) | ||
| 250 | return setmetatable({x}, mt) | ||
| 251 | end | ||
| 252 | |||
| 253 | local a, b = T.testC("compare LT 2 3; pushint 10; return 2", O(1), O(2)) | ||
| 254 | assert(a == true and b == 10) | ||
| 255 | local a, b = T.testC("compare LE 2 3; pushint 10; return 2", O(3), O(2)) | ||
| 256 | assert(a == false and b == 10) | ||
| 257 | local a, b = T.testC("compare EQ 2 3; pushint 10; return 2", O(3), O(3)) | ||
| 258 | assert(a == true and b == 10) | ||
| 259 | end | ||
| 260 | |||
| 244 | -- testing length | 261 | -- testing length |
| 245 | local t = setmetatable({x = 20}, {__len = function (t) return t.x end}) | 262 | local t = setmetatable({x = 20}, {__len = function (t) return t.x end}) |
| 246 | a,b,c = T.testC([[ | 263 | a,b,c = T.testC([[ |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index e04207c8..00531d8e 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
| @@ -809,7 +809,7 @@ assert(run(function () | |||
| 809 | -- tests for coroutine API | 809 | -- tests for coroutine API |
| 810 | if T==nil then | 810 | if T==nil then |
| 811 | (Message or print)('\n >>> testC not active: skipping coroutine API tests <<<\n') | 811 | (Message or print)('\n >>> testC not active: skipping coroutine API tests <<<\n') |
| 812 | return | 812 | print "OK"; return |
| 813 | end | 813 | end |
| 814 | 814 | ||
| 815 | print('testing coroutine API') | 815 | print('testing coroutine API') |
diff --git a/testes/events.lua b/testes/events.lua index cf68d1e9..7fb54c9a 100644 --- a/testes/events.lua +++ b/testes/events.lua | |||
| @@ -217,9 +217,16 @@ t.__le = function (a,b,c) | |||
| 217 | return a<=b, "dummy" | 217 | return a<=b, "dummy" |
| 218 | end | 218 | end |
| 219 | 219 | ||
| 220 | t.__eq = function (a,b,c) | ||
| 221 | assert(c == nil) | ||
| 222 | if type(a) == 'table' then a = a.x end | ||
| 223 | if type(b) == 'table' then b = b.x end | ||
| 224 | return a == b, "dummy" | ||
| 225 | end | ||
| 226 | |||
| 220 | function Op(x) return setmetatable({x=x}, t) end | 227 | function Op(x) return setmetatable({x=x}, t) end |
| 221 | 228 | ||
| 222 | local function test () | 229 | local function test (a, b, c) |
| 223 | assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1))) | 230 | assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1))) |
| 224 | assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1))) | 231 | assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1))) |
| 225 | assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a'))) | 232 | assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a'))) |
| @@ -232,9 +239,13 @@ local function test () | |||
| 232 | assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1)) | 239 | assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1)) |
| 233 | assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) | 240 | assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) |
| 234 | assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a'))) | 241 | assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a'))) |
| 242 | assert(Op(1) == Op(1) and Op(1) ~= Op(2)) | ||
| 243 | assert(Op('a') == Op('a') and Op('a') ~= Op('b')) | ||
| 244 | assert(a == a and a ~= b) | ||
| 245 | assert(Op(3) == c) | ||
| 235 | end | 246 | end |
| 236 | 247 | ||
| 237 | test() | 248 | test(Op(1), Op(2), Op(3)) |
| 238 | 249 | ||
| 239 | 250 | ||
| 240 | -- test `partial order' | 251 | -- test `partial order' |
diff --git a/testes/strings.lua b/testes/strings.lua index 0e7874bf..aa039c4f 100644 --- a/testes/strings.lua +++ b/testes/strings.lua | |||
| @@ -167,8 +167,11 @@ do -- tests for '%p' format | |||
| 167 | local t1 = {}; local t2 = {} | 167 | local t1 = {}; local t2 = {} |
| 168 | assert(string.format("%p", t1) ~= string.format("%p", t2)) | 168 | assert(string.format("%p", t1) ~= string.format("%p", t2)) |
| 169 | end | 169 | end |
| 170 | assert(string.format("%p", string.rep("a", 10)) == | 170 | do -- short strings |
| 171 | string.format("%p", string.rep("a", 10))) -- short strings | 171 | local s1 = string.rep("a", 10) |
| 172 | local s2 = string.rep("a", 10) | ||
| 173 | assert(string.format("%p", s1) == string.format("%p", s2)) | ||
| 174 | end | ||
| 172 | do -- long strings | 175 | do -- long strings |
| 173 | local s1 = string.rep("a", 300); local s2 = string.rep("a", 300) | 176 | local s1 = string.rep("a", 300); local s2 = string.rep("a", 300) |
| 174 | assert(string.format("%p", s1) ~= string.format("%p", s2)) | 177 | assert(string.format("%p", s1) ~= string.format("%p", s2)) |
