Traditionally, lightuserdata has been intended as a way to represent C
pointers (or even handles [2]) in Lua, often as keys in a Lua table
[1], but another way we might think of lightuserdata is as a
lightweight, not-garbage-collected value type that can fit entirely in
register. nil, boolean, and number are in this same class, and it's
similar to the concept of primitive POD types in C/C++ (e.g. int,
char, enum, etc.). lightuserdata differs from the other types above
in that the bit pattern has no meaning to Lua. The Lua API also
suggests that the size of a lightuserdata is equal to size(void *),
but this may be overly restrictive: on a 32-bit machine with 64-bit
floating point numbers, the Value type (Lua register) has enough room
for 64-bit lightuserdata's. Such large lightuserdata can support, for
example, 64-bit bitwise operations [3] or any other 64-bit value
storage. Although it's technically possible to use double-precision
lua_Number's to store arbitrary 64-bit data values as well, beyond
53-bits these values will no longer be interpretable as numbers and
may not be usable as table keys or support comparison (since NaN ~=
NaN). (Additional caveat: in LuaJIT the upper "NaN" bits of 64-bit
Value's are reserved for special purposes, and this limitation likely
prohibits using all bits of 64-bit lightuserdata's.)
The attached patch makes lightuserdata more of a first-class type in
Lua. It's written only as a quick proof of concept. Number literals
postfixed by "u" are treated as lightuserdata constants, and unsigned
arithmetic operations are supported over lightuserdata's. Bitwise
operations like XOR could be supported via a library function. You
can do things like
assert(type(0x123u) == 'userdata')
print(0x123u) --> userdata: 0x123
local x = 0x123u + 0x1u
assert(x == 0x124u)
print(tolightuserdata(0x123)) --> userdata: 0x123
assert(tonumber(0x123u) == 0x123)
This is just some food for thought. 64-bit (or 128-bit or 256-bit
values for that matter) can of course represented as multiple 32-bit
values if needed. A common need, for example, is representing (x,y,z)
vector values (192-bit) or complex numbers, and the typical solution
is to represent each component in its own register rather than try to
stuff in all in a single register.
[1] http://lua-users.org/lists/lua-l/2007-06/msg00048.html
[2] http://lua-users.org/lists/lua-l/2004-07/msg00389.html
[3] http://lua-users.org/lists/lua-l/2009-07/msg00128.html