[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Lua lvm.c tweak to allow userdata <-> String comparison
- From: Flyer31 Test <flyer31@...>
- Date: Fri, 12 Nov 2021 13:25:44 +0100
Hi List,
for my string-buffer userdata elements I want to use the __eq also for
comparison to normal strings.
E. g. I want to check a Buffer Buf like this in Lua (5.4):
if Buf== 'd' then ... do something... end
In standard Lua 5.4 this will NOT invoke the __eq metafunction of my
string buffer userdata Buf, as all variables with different types are
considered different by default (except integers/numbers, there it
will do further checking).
I got this "tweaked" in Lua by adapting the following two parts in lvm.c:
vmcase(OP_EQK) {
TValue *rb = KB(i);
/* basic types do not use '__eq'; we can use raw equality */
int cond = luaV_rawequalobj(s2v(ra), rb);
docondjump();
vmbreak;
}
This I had to change to:
vmcase(OP_EQK) {
TValue *rb = KB(i);
int cond;
Protect(cond = luaV_equalobj(L, s2v(ra), rb));
docondjump();
vmbreak;
}
(L is needed in my modified luaV_equalobj function for the case that
either parameter a or b is userdata... - metafunction cannot be
accessed without L)
And in the function luaV_equalobj, I had to check for userdata very at
the start of the function, before running into the "normal code":
int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
const TValue *tm;
if( ttypetag(t1) == LUA_VUSERDATA || ttypetag(t2) == LUA_VUSERDATA){
if (uvalue(t1) == uvalue(t2)) return 1;
else if (L == NULL) return 0;
tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
if (tm == NULL)
tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
/* will try TM */
}
else{
... handle all the other types (as in original code)
}
if (tm == NULL) /* no TM? */
return 0; /* objects are different */
else {
luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */
return !l_isfalse(s2v(L->top));
}
}
If I do these two changes in lvm.c, then my metafunction __eq for by
userdata Buf will also be invoked if I check "Buf=='d'" ... . So
concerning working this seems to work fine... . ( < and <= instead of
== anyway work, as this OP_EQK is only present for == ... < and <=
have NO such "OP_LTK" or similar...).
I think the main penalty here is, that now ANY == comparison with some
constant value must use this "Protected call" Protect(cond =
luaV_equalobj(L, s2v(ra), rb)).
Is this a heavy drawback / dangerous operation, or should this work
quite nicely?