Showing posts with label Lua. Show all posts
Showing posts with label Lua. Show all posts

2012-08-10

Lua output redirection

While ago I was working on Lua based implementation of the scripting library. One of the requirements was a total control of output and error messages, to allow it's automatic handling. One of the issues I've faced is that some output was going to stdout even if there is redefined print Lua function.

I thought about two quick solutions:
- redirect standard streams;
- redefine printf and it's adjacent functions.

Since standard streams, both stdout and stderr, in my case were already redefined (for remote debugging purposes), I didn't had much to choose from.

Looking into Lua 5.1 sources, I've found that stdout was simply hard-coded in some places. During up-streaming this patch to Lua 5.2 surprisingly most of the hard-coded stream names went away, and it looks like it would be possible to use redefined print without losing anything. I haven't tested this though. Following just works for Lua 5.1.x and above.

2009-05-05

Lua constants

By Lua's nature, it is not possible to create constants. There is a workaround, though, using metatables:

function protect(tbl)
    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

2009-05-01

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:

lua_pushcfunction(L, error_handler);
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:

int error_handler(lua_State* L) {
    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:
[string "test"]:1 > [string "test"]:1: attempt to index global 'a' (a nil value)

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!

2009-04-16

C Lua snippets

Get currently executed chunk name:
lua_Debug lua_info;
lua_getstack(L, 0, &lua_info);
lua_getinfo(L, "n", &lua_info);
string name = lua_info.name;
Opposite to lua_register:
lua_pushnil(L);
lua_setglobal(L, name.c_str());
stack_dump in C++ flavour ;)
static void stack_dump (lua_State *L) {
    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;
}