diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-01-27 13:12:52 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-01-27 13:12:52 -0200 |
commit | e79bf02f33c57523833b5b700d0d5b6e6955a5d7 (patch) | |
tree | 3992a6265cb11beedfaee23d13de82b67668b16d /lvm.c | |
parent | 41ed3c47719b29dd02dc9fcf07f79dc6f2c4381d (diff) | |
download | lua-e79bf02f33c57523833b5b700d0d5b6e6955a5d7.tar.gz lua-e79bf02f33c57523833b5b700d0d5b6e6955a5d7.tar.bz2 lua-e79bf02f33c57523833b5b700d0d5b6e6955a5d7.zip |
correct semantics for comparison metamethods (they are only valid
when both operands have the same metamethod).
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 57 |
1 files changed, 42 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.272 2002/12/06 17:09:00 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.273 2002/12/11 12:34:22 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 | */ |
@@ -204,6 +204,33 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
204 | } | 204 | } |
205 | 205 | ||
206 | 206 | ||
207 | static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2, | ||
208 | TMS event) { | ||
209 | const TObject *tm1 = fasttm(L, mt1, event); | ||
210 | const TObject *tm2; | ||
211 | if (tm1 == NULL) return NULL; /* no metamethod */ | ||
212 | if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ | ||
213 | tm2 = fasttm(L, mt2, event); | ||
214 | if (tm2 == NULL) return NULL; /* no metamethod */ | ||
215 | if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ | ||
216 | return tm1; | ||
217 | return NULL; | ||
218 | } | ||
219 | |||
220 | |||
221 | static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2, | ||
222 | TMS event) { | ||
223 | const TObject *tm1 = luaT_gettmbyobj(L, p1, event); | ||
224 | const TObject *tm2; | ||
225 | if (ttisnil(tm1)) return -1; /* no metamethod? */ | ||
226 | tm2 = luaT_gettmbyobj(L, p2, event); | ||
227 | if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ | ||
228 | return -1; | ||
229 | callTMres(L, tm1, p1, p2); | ||
230 | return !l_isfalse(L->top); | ||
231 | } | ||
232 | |||
233 | |||
207 | static int luaV_strcmp (const TString *ls, const TString *rs) { | 234 | static int luaV_strcmp (const TString *ls, const TString *rs) { |
208 | const char *l = getstr(ls); | 235 | const char *l = getstr(ls); |
209 | size_t ll = ls->tsv.len; | 236 | size_t ll = ls->tsv.len; |
@@ -227,29 +254,31 @@ static int luaV_strcmp (const TString *ls, const TString *rs) { | |||
227 | 254 | ||
228 | 255 | ||
229 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { | 256 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { |
257 | int res; | ||
230 | if (ttype(l) != ttype(r)) | 258 | if (ttype(l) != ttype(r)) |
231 | return luaG_ordererror(L, l, r); | 259 | return luaG_ordererror(L, l, r); |
232 | else if (ttisnumber(l)) | 260 | else if (ttisnumber(l)) |
233 | return nvalue(l) < nvalue(r); | 261 | return nvalue(l) < nvalue(r); |
234 | else if (ttisstring(l)) | 262 | else if (ttisstring(l)) |
235 | return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; | 263 | return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; |
236 | else if (call_binTM(L, l, r, L->top, TM_LT)) | 264 | else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) |
237 | return !l_isfalse(L->top); | 265 | return res; |
238 | return luaG_ordererror(L, l, r); | 266 | return luaG_ordererror(L, l, r); |
239 | } | 267 | } |
240 | 268 | ||
241 | 269 | ||
242 | static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { | 270 | static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { |
271 | int res; | ||
243 | if (ttype(l) != ttype(r)) | 272 | if (ttype(l) != ttype(r)) |
244 | return luaG_ordererror(L, l, r); | 273 | return luaG_ordererror(L, l, r); |
245 | else if (ttisnumber(l)) | 274 | else if (ttisnumber(l)) |
246 | return nvalue(l) <= nvalue(r); | 275 | return nvalue(l) <= nvalue(r); |
247 | else if (ttisstring(l)) | 276 | else if (ttisstring(l)) |
248 | return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; | 277 | return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; |
249 | else if (call_binTM(L, l, r, L->top, TM_LE)) /* first try `le' */ | 278 | else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ |
250 | return !l_isfalse(L->top); | 279 | return res; |
251 | else if (call_binTM(L, r, l, L->top, TM_LT)) /* else try `lt' */ | 280 | else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ |
252 | return l_isfalse(L->top); | 281 | return !res; |
253 | return luaG_ordererror(L, l, r); | 282 | return luaG_ordererror(L, l, r); |
254 | } | 283 | } |
255 | 284 | ||
@@ -264,20 +293,18 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) { | |||
264 | case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); | 293 | case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); |
265 | case LUA_TUSERDATA: { | 294 | case LUA_TUSERDATA: { |
266 | if (uvalue(t1) == uvalue(t2)) return 1; | 295 | if (uvalue(t1) == uvalue(t2)) return 1; |
267 | else if ((tm = fasttm(L, uvalue(t1)->uv.metatable, TM_EQ)) == NULL && | 296 | tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable, |
268 | (tm = fasttm(L, uvalue(t2)->uv.metatable, TM_EQ)) == NULL) | 297 | TM_EQ); |
269 | return 0; /* no TM */ | 298 | break; /* will try TM */ |
270 | else break; /* will try TM */ | ||
271 | } | 299 | } |
272 | case LUA_TTABLE: { | 300 | case LUA_TTABLE: { |
273 | if (hvalue(t1) == hvalue(t2)) return 1; | 301 | if (hvalue(t1) == hvalue(t2)) return 1; |
274 | else if ((tm = fasttm(L, hvalue(t1)->metatable, TM_EQ)) == NULL && | 302 | tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); |
275 | (tm = fasttm(L, hvalue(t2)->metatable, TM_EQ)) == NULL) | 303 | break; /* will try TM */ |
276 | return 0; /* no TM */ | ||
277 | else break; /* will try TM */ | ||
278 | } | 304 | } |
279 | default: return gcvalue(t1) == gcvalue(t2); | 305 | default: return gcvalue(t1) == gcvalue(t2); |
280 | } | 306 | } |
307 | if (tm == NULL) return 0; /* no TM? */ | ||
281 | callTMres(L, tm, t1, t2); /* call TM */ | 308 | callTMres(L, tm, t1, t2); /* call TM */ |
282 | return !l_isfalse(L->top); | 309 | return !l_isfalse(L->top); |
283 | } | 310 | } |