Archive for the ‘Lua’ Category
Lua constants
By Lua’s nature, it is not possible to create constants. There is a workaround, though, using metatables:
return setmetatable({}, {
__index = tbl,
__newindex = function(t, key, value)
error("attempting to change constant " .. tostring(key) .. " to " .. tostring(value), 2)
end
})
end
constants = {
x = 1,
y = 2,
}
constants = protect(constants)
print(constants.x) --> 3
constants.x = 3 --> error: attempting to change constant x to 3
Lua error message format
I work on the library, which will use Lua. Thinking about the possibility to give a good error structure instead of plain message, I’ve found that lua_pcall has a nice feature to specify custom error handler function:
luaL_loadfile(L, "file.lua");
lua_pcall(L, 0, 0, -2);
Using this there is a way to get a chunk name and it’s error line number:
lua_Debug d;
lua_getstack(L, 1, &d);
lua_getinfo(L, "Sln", &d);
string err = lua_tostring(L, -1);
lua_pop(L, 1);
stringstream msg;
msg << d.short_src << ":" << d.currentline;
if(d.name != 0) {
msg << "(" << d.namewhat << " " << d.name << ")";
}
msg << " > " << err;
lua_pushstring(L, msg.str().c_str());
return 1;
}
Work’s like a charm, except one thing. This is the output from this error handler:
Why? Oh, why the Lua guys are putting assembled error message with chunk name and line number if I use my own error handler? IMHO, this is wrong. There is no other way to give a user nice message except parsing. Actually parsing of such message is easy, but.. the Lua guys have changed error message format a few times already. I’m pissed!
C Lua snippets
Get currently executed chunk name:
lua_getstack(L, 0, &lua_info);
lua_getinfo(L, "n", &lua_info);
string name = lua_info.name;
Opposite to lua_register:
lua_setglobal(L, name.c_str());
stack_dump in C++ flavour
int top = lua_gettop(L);
for(int i = 1; i <= top; i++) {
int t = lua_type(L, i);
switch(t) {
case LUA_TSTRING:
cout << "'" << lua_tostring(L, i) << "'";
break;
case LUA_TBOOLEAN:
cout << (lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER:
cout << lua_tonumber(L, i);
break;
default:
cout << lua_typename(L, t);
break;
}
cout << " ";
}
cout << endl;
}