diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-12 11:56:22 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-12 11:56:22 -0300 |
| commit | eeab473fc8fdce39c3a0a495a6a790d7906c7bdc (patch) | |
| tree | f260370b15d8a196f4168d3e64dafb35c8083282 /lvm.c | |
| parent | 6b8cdc9cdd545508af85d1de2013ea0fc64792b0 (diff) | |
| download | lua-eeab473fc8fdce39c3a0a495a6a790d7906c7bdc.tar.gz lua-eeab473fc8fdce39c3a0a495a6a790d7906c7bdc.tar.bz2 lua-eeab473fc8fdce39c3a0a495a6a790d7906c7bdc.zip | |
new fallback __le (less equal), for partial order
Diffstat (limited to 'lvm.c')
| -rw-r--r-- | lvm.c | 62 |
1 files changed, 41 insertions, 21 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.235 2002/06/05 12:34:19 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.236 2002/06/06 18:17:33 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 | */ |
| @@ -207,14 +207,13 @@ static int luaV_strcmp (const TString *ls, const TString *rs) { | |||
| 207 | size_t lr = rs->tsv.len; | 207 | size_t lr = rs->tsv.len; |
| 208 | for (;;) { | 208 | for (;;) { |
| 209 | int temp = strcoll(l, r); | 209 | int temp = strcoll(l, r); |
| 210 | if (temp < 0) return CMP_LT; | 210 | if (temp != 0) return temp; |
| 211 | else if (temp > 0) return CMP_GT; | ||
| 212 | else { /* strings are equal up to a `\0' */ | 211 | else { /* strings are equal up to a `\0' */ |
| 213 | size_t len = strlen(l); /* index of first `\0' in both strings */ | 212 | size_t len = strlen(l); /* index of first `\0' in both strings */ |
| 214 | if (len == lr) /* r is finished? */ | 213 | if (len == lr) /* r is finished? */ |
| 215 | return (len == ll) ? CMP_EQ : CMP_GT; /* l is eq. or gt. than r */ | 214 | return (len == ll) ? 0 : 1; |
| 216 | else if (len == ll) /* l is finished? */ | 215 | else if (len == ll) /* l is finished? */ |
| 217 | return CMP_LT; /* l is smaller than r (because r is not finished) */ | 216 | return -1; /* l is smaller than r (because r is not finished) */ |
| 218 | /* both strings longer than `len'; go on comparing (after the `\0') */ | 217 | /* both strings longer than `len'; go on comparing (after the `\0') */ |
| 219 | len++; | 218 | len++; |
| 220 | l += len; ll -= len; r += len; lr -= len; | 219 | l += len; ll -= len; r += len; lr -= len; |
| @@ -223,24 +222,30 @@ static int luaV_strcmp (const TString *ls, const TString *rs) { | |||
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | 224 | ||
| 226 | int luaV_cmp (lua_State *L, const TObject *l, const TObject *r, int cond) { | 225 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { |
| 227 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) { | 226 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) |
| 228 | lua_Number n1 = nvalue(l); | 227 | return nvalue(l) < nvalue(r); |
| 229 | lua_Number n2 = nvalue(r); | ||
| 230 | if (n1 < n2) return (cond & CMP_LT); | ||
| 231 | else if (n1 > n2) return (cond & CMP_GT); | ||
| 232 | else if (n1 == n2) return (cond & CMP_EQ); | ||
| 233 | else return (cond & CMP_N); | ||
| 234 | } | ||
| 235 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) | 228 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) |
| 236 | return luaV_strcmp(tsvalue(l), tsvalue(r)) & cond; | 229 | return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; |
| 237 | else { /* try TM */ | 230 | else { /* try TM */ |
| 238 | if (cond & CMP_EQ ? cond & CMP_LT : cond & CMP_GT) { /* `<=' or `>' ? */ | ||
| 239 | const TObject *temp = l; l = r; r = temp; /* exchange terms */ | ||
| 240 | } | ||
| 241 | if (!call_binTM(L, l, r, L->top, TM_LT)) | 231 | if (!call_binTM(L, l, r, L->top, TM_LT)) |
| 242 | luaG_ordererror(L, l, r); | 232 | luaG_ordererror(L, l, r); |
| 243 | return (cond & CMP_EQ) ? l_isfalse(L->top) : !l_isfalse(L->top); | 233 | return !l_isfalse(L->top); |
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | |||
| 238 | static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { | ||
| 239 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) | ||
| 240 | return nvalue(l) <= nvalue(r); | ||
| 241 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) | ||
| 242 | return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; | ||
| 243 | else { /* try TM */ | ||
| 244 | if (call_binTM(L, l, r, L->top, TM_LE)) /* first try `le' */ | ||
| 245 | return !l_isfalse(L->top); | ||
| 246 | else if (!call_binTM(L, r, l, L->top, TM_LT)) /* else try `lt' */ | ||
| 247 | luaG_ordererror(L, l, r); | ||
| 248 | return l_isfalse(L->top); | ||
| 244 | } | 249 | } |
| 245 | } | 250 | } |
| 246 | 251 | ||
| @@ -463,8 +468,23 @@ StkId luaV_execute (lua_State *L) { | |||
| 463 | else dojump(pc, GETARG_sBx(*pc) + 1); | 468 | else dojump(pc, GETARG_sBx(*pc) + 1); |
| 464 | break; | 469 | break; |
| 465 | } | 470 | } |
| 466 | case OP_CMP: { | 471 | case OP_LT: { |
| 467 | if (!(luaV_cmp(L, ra, RKC(i), GETARG_B(i)))) pc++; | 472 | if (luaV_lessthan(L, ra, RKC(i)) != GETARG_B(i)) pc++; |
| 473 | else dojump(pc, GETARG_sBx(*pc) + 1); | ||
| 474 | break; | ||
| 475 | } | ||
| 476 | case OP_LE: { | ||
| 477 | if (luaV_lessequal(L, ra, RKC(i)) != GETARG_B(i)) pc++; | ||
| 478 | else dojump(pc, GETARG_sBx(*pc) + 1); | ||
| 479 | break; | ||
| 480 | } | ||
| 481 | case OP_GT: { | ||
| 482 | if (luaV_lessthan(L, RKC(i), ra) != GETARG_B(i)) pc++; | ||
| 483 | else dojump(pc, GETARG_sBx(*pc) + 1); | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | case OP_GE: { | ||
| 487 | if (luaV_lessequal(L, RKC(i), ra) != GETARG_B(i)) pc++; | ||
| 468 | else dojump(pc, GETARG_sBx(*pc) + 1); | 488 | else dojump(pc, GETARG_sBx(*pc) + 1); |
| 469 | break; | 489 | break; |
| 470 | } | 490 | } |
