lua-users home
lua-l archive

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


I just finished writing the following when I received Rici's message, to which I'll reply after the sample code:

Considering the discussion this thread has generated I'm assuming this isn't much requested. Nevertheless here is my current solution which validates the given index against any of the given metatable names and gives a proper argument error when none match:

----------8<----------

#include <lua.h>
#include <lauxlib.h>

LUALIB_API void *luaL_checkudata_ex(lua_State *L, int ud, const char **tnames) {
  int i;
  void *p = lua_touserdata(L, ud);
  if (p != NULL) {  /* value is a userdata? */
    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
      for (i = 0; tnames[i] != NULL; i++) {  /* compare to each tname given */
        lua_getfield(L, LUA_REGISTRYINDEX, tnames[i]);  /* get correct mt */
        if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */
          lua_pop(L, 2);  /* remove both metatables */
          return p;
        }
      }
    }
  }

  /* compose error message that mentions all typenames */
  {
    /* separate scope to avoid default stack of > LUAL_BUFFERSIZE
     * assuming it even makes a difference ... */
    luaL_Buffer B;
    luaL_buffinit(L, &B);
    for (i = 0; tnames[i] != NULL; i++) {
      luaL_addstring(&B, tnames[i]);
      if (tnames[i+1] != NULL) luaL_addlstring(&B, " or ", 4);
    }
    luaL_pushresult(&B);
    luaL_typerror(L, ud, lua_tostring(L, -1));
    return NULL; /* to avoid warnings */
  }
}

---------->8----------

Rici Lake wrote:
> In fact, there is a mechanism like this in LuaSocket, which you might
> want to look at.
>
> My approach is a bit different, though: I prefer to put the metatable
> itself where object methods can get at it, generally as upvalue 1. This
> allows checking against the metatable of the target object with a simple
> equality test. I also make sure that the environment table of object
> methods is the method table for the object.
>
> With that setup, it's easy to handle polymorphism. The key, as it were,
> is to use tables as keys. For example, each metatable can contain
> interface method tables as keys (mapped to the value true, for example.)
> Alternatively, or simultaneously, a metatable can hold superclass
> metatables as keys. Either of these allows a method to verify membership
> rapidly by looking up its own metatable (upvalue 1) or method table
> (environment table) as a key in the metatable of the target object.
>
> It's easier to draw this on paper than describe it, but I hope that
> helps a bit.
>
> R.

Thanks for your input. Is there any public code available that implements (part of) the scheme you're describing? I don't want to ask you to write a 100+ LOC example but I must say this is a bit too abstract for me ATM. I'll read it again in an hour or two and see if that changes anything ;)

 - Peter Odding