diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-05-06 12:51:41 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-05-06 12:51:41 -0300 |
commit | 0dbf0c5953a3d72deebc7e41840a0e73b46de8bc (patch) | |
tree | b4a525660cba017d7985c37393f50d6b8bee9e4b /lvm.c | |
parent | 85dcb411a8454de0bc1c2c60a24af1588e436c23 (diff) | |
download | lua-0dbf0c5953a3d72deebc7e41840a0e73b46de8bc.tar.gz lua-0dbf0c5953a3d72deebc7e41840a0e73b46de8bc.tar.bz2 lua-0dbf0c5953a3d72deebc7e41840a0e73b46de8bc.zip |
new format for test intructions (handle NaN correctly)
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 68 |
1 files changed, 28 insertions, 40 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.227 2002/04/24 20:07:46 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.228 2002/05/02 13:06:20 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -189,20 +189,21 @@ static void call_arith (lua_State *L, StkId p1, const TObject *p2, | |||
189 | } | 189 | } |
190 | 190 | ||
191 | 191 | ||
192 | static int luaV_strlessthan (const TString *ls, const TString *rs) { | 192 | static int luaV_strcmp (const TString *ls, const TString *rs) { |
193 | const char *l = getstr(ls); | 193 | const char *l = getstr(ls); |
194 | size_t ll = ls->tsv.len; | 194 | size_t ll = ls->tsv.len; |
195 | const char *r = getstr(rs); | 195 | const char *r = getstr(rs); |
196 | size_t lr = rs->tsv.len; | 196 | size_t lr = rs->tsv.len; |
197 | for (;;) { | 197 | for (;;) { |
198 | int temp = strcoll(l, r); | 198 | int temp = strcoll(l, r); |
199 | if (temp != 0) return (temp < 0); | 199 | if (temp < 0) return CMP_LT; |
200 | else if (temp > 0) return CMP_GT; | ||
200 | else { /* strings are equal up to a `\0' */ | 201 | else { /* strings are equal up to a `\0' */ |
201 | size_t len = strlen(l); /* index of first `\0' in both strings */ | 202 | size_t len = strlen(l); /* index of first `\0' in both strings */ |
202 | if (len == lr) /* r is finished? */ | 203 | if (len == lr) /* r is finished? */ |
203 | return 0; /* l is equal or greater than r */ | 204 | return (len == ll) ? CMP_EQ : CMP_GT; /* l is eq. or gt. than r */ |
204 | else if (len == ll) /* l is finished? */ | 205 | else if (len == ll) /* l is finished? */ |
205 | return 1; /* l is smaller than r (because r is not finished) */ | 206 | return CMP_LT; /* l is smaller than r (because r is not finished) */ |
206 | /* both strings longer than `len'; go on comparing (after the `\0') */ | 207 | /* both strings longer than `len'; go on comparing (after the `\0') */ |
207 | len++; | 208 | len++; |
208 | l += len; ll -= len; r += len; lr -= len; | 209 | l += len; ll -= len; r += len; lr -= len; |
@@ -211,15 +212,24 @@ static int luaV_strlessthan (const TString *ls, const TString *rs) { | |||
211 | } | 212 | } |
212 | 213 | ||
213 | 214 | ||
214 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { | 215 | int luaV_cmp (lua_State *L, const TObject *l, const TObject *r, int cond) { |
215 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) | 216 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) { |
216 | return (nvalue(l) < nvalue(r)); | 217 | lua_Number n1 = nvalue(l); |
218 | lua_Number n2 = nvalue(r); | ||
219 | if (n1 < n2) return (cond & CMP_LT); | ||
220 | else if (n1 > n2) return (cond & CMP_GT); | ||
221 | else if (n1 == n2) return (cond & CMP_EQ); | ||
222 | else return (cond & CMP_N); | ||
223 | } | ||
217 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) | 224 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) |
218 | return luaV_strlessthan(tsvalue(l), tsvalue(r)); | 225 | return luaV_strcmp(tsvalue(l), tsvalue(r)) & cond; |
219 | else { /* try TM */ | 226 | else { /* try TM */ |
227 | if (cond & CMP_EQ ? cond & CMP_LT : cond & CMP_GT) { /* `<=' or `>' ? */ | ||
228 | const TObject *temp = l; l = r; r = temp; /* exchange terms */ | ||
229 | } | ||
220 | if (!call_binTM(L, l, r, L->top, TM_LT)) | 230 | if (!call_binTM(L, l, r, L->top, TM_LT)) |
221 | luaG_ordererror(L, l, r); | 231 | luaG_ordererror(L, l, r); |
222 | return !l_isfalse(L->top); | 232 | return (cond & CMP_EQ) ? l_isfalse(L->top) : !l_isfalse(L->top); |
223 | } | 233 | } |
224 | } | 234 | } |
225 | 235 | ||
@@ -437,40 +447,18 @@ StkId luaV_execute (lua_State *L) { | |||
437 | dojump(pc, GETARG_sBx(i)); | 447 | dojump(pc, GETARG_sBx(i)); |
438 | break; | 448 | break; |
439 | } | 449 | } |
440 | case OP_TESTEQ: { /* skip next instruction if test fails */ | 450 | case OP_EQ: { /* skip next instruction if test fails */ |
441 | if (!luaO_equalObj(ra, RKC(i))) pc++; | 451 | if (luaO_equalObj(ra, RKC(i)) != GETARG_B(i)) pc++; |
442 | break; | ||
443 | } | ||
444 | case OP_TESTNE: { | ||
445 | if (luaO_equalObj(ra, RKC(i))) pc++; | ||
446 | break; | ||
447 | } | ||
448 | case OP_TESTLT: { | ||
449 | if (!luaV_lessthan(L, ra, RKC(i))) pc++; | ||
450 | break; | ||
451 | } | ||
452 | case OP_TESTLE: { /* b <= c === !(c<b) */ | ||
453 | if (luaV_lessthan(L, RKC(i), ra)) pc++; | ||
454 | break; | ||
455 | } | ||
456 | case OP_TESTGT: { /* b > c === (c<b) */ | ||
457 | if (!luaV_lessthan(L, RKC(i), ra)) pc++; | ||
458 | break; | 452 | break; |
459 | } | 453 | } |
460 | case OP_TESTGE: { /* b >= c === !(b<c) */ | 454 | case OP_CMP: { |
461 | if (luaV_lessthan(L, ra, RKC(i))) pc++; | 455 | if (!(luaV_cmp(L, ra, RKC(i), GETARG_B(i)))) pc++; |
462 | break; | 456 | break; |
463 | } | 457 | } |
464 | case OP_TESTT: { | 458 | case OP_TEST: { |
465 | StkId rb = RB(i); | 459 | StkId rc = RKC(i); |
466 | if (l_isfalse(rb)) pc++; | 460 | if (l_isfalse(rc) == GETARG_B(i)) pc++; |
467 | else setobj(ra, rb); | 461 | else setobj(ra, rc); |
468 | break; | ||
469 | } | ||
470 | case OP_TESTF: { | ||
471 | StkId rb = RB(i); | ||
472 | if (!l_isfalse(rb)) pc++; | ||
473 | else setobj(ra, rb); | ||
474 | break; | 462 | break; |
475 | } | 463 | } |
476 | case OP_CALL: { | 464 | case OP_CALL: { |