aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-01-27 13:12:52 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-01-27 13:12:52 -0200
commite79bf02f33c57523833b5b700d0d5b6e6955a5d7 (patch)
tree3992a6265cb11beedfaee23d13de82b67668b16d /lvm.c
parent41ed3c47719b29dd02dc9fcf07f79dc6f2c4381d (diff)
downloadlua-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.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/lvm.c b/lvm.c
index ab065d7d..5d4b0445 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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
207static 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
221static 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
207static int luaV_strcmp (const TString *ls, const TString *rs) { 234static 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
229int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { 256int 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
242static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { 270static 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}