lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

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);

This I had to change to:

      vmcase(OP_EQK) {
        TValue *rb = KB(i);
        int cond;
        Protect(cond = luaV_equalobj(L, s2v(ra), rb));

(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 */
... 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?