lua-users home
lua-l archive

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


2015-08-20 8:49 GMT+02:00 Dirk Laurie <dirk.laurie@gmail.com>:

> I think I understand it now,
...
> I agree that a tool of this power will quickly inspire many ways of
> using it.

If anyone wants to try it out, the module is attached.
Tested under 5.2.4 and 5.3.1. Does not work under 5.1.
/* typetag.c  © Dirk Laurie 2015  MIT license, see Lua source code
  Extends debug library with two new methods.

  debug.gettypetag(val): returns the type tag of `val`
  debug.settypetag(val,tag): returns a new value with the same value 
    field as `val` but with the given type tag, which must be compatible
    with the type of `val`. The return value is not raw-equal to `val`.
    For example, a value that satisfies type(v)==nil but tests true
    can be created this way.

  If TYPETAG_NOBRAKES is not defined, `val` must be of type userdata. 

  See thread starting with
      http://lua-users.org/lists/lua-l/2015-08/msg00256.html
   especially my contribution at 20 Aug 2015 08:49:35 +0200.
   Linux compilation: change `#define LUA_SRC`, then on 64-bit machine
     cc -shared -fPIC -D TAGTYPE_NOBRAKES gettypetag.c -o gettypetag.so
*/

#define LUA_SRC(file) </usr/local/src/lua-5.3.1/src/file>

#include LUA_SRC(lobject.h)
#include LUA_SRC(lstate.h)
#include LUA_SRC(lauxlib.h)

static int lua_settypetag(lua_State *L) {
  int newtype = luaL_checkinteger(L,2);
#ifndef TAGTYPE_NOBRAKES
  luaL_checktype (L, 1, LUA_TUSERDATA);
#endif
  luaL_checktype (L, 1, novariant(newtype));
  lua_settop(L,1);
  (L->top-1)->tt_ = newtype;
  return 1;
}

static int lua_gettypetag(lua_State *L) {
  luaL_checkany(L,1);
  lua_settop(L,1);  
  lua_pushinteger(L,(L->top-1)->tt_);
  return 1;
}

LUAMOD_API int luaopen_typetag(lua_State *L) {
  lua_getglobal(L,"debug");
  lua_pushcfunction(L,lua_settypetag);
  lua_setfield(L,-2,"settypetag");
  lua_pushcfunction(L,lua_gettypetag);
  lua_setfield(L,-2,"gettypetag");
  return 0;
}

/* Test suite with -D TYPETAG_NOBRAKES

y=debug.settypetag(nil,16)
print(y,type(y))  -->  nil nil
print(y==nil)   --> false
if y then print(debug.gettypetag(y)) else print(nil) end   --> 16
x=debug.settypetag(1.0,16) --> type error
x=debug.settypetag(1.0,debug.gettypetag(1))
print(x) --> 4607182418800017408 (5.3 only)
print(("%X"):format(x)) --> 3FF0000000000000 (5.3 only)

*/