This patch improves Lua's support for custom error objects. Changes: * Uncaught error handler in standard Lua interpreter calls tostring() on error object. This ensures that a call stack is displayed even for non-string error objects. It also allows use of the __tostring hook for human-readable error messages. * Base library error() will set the _WHERE field of any table error object to the value of luaL_where(). Uncaught error handler in the standard Lua interpreter will use this, so that for custom error object the error location is shown in the call stack. This is a bit of a hack and implies that any thrown table should be a unique instance of the error (since it will be mutated). Rather than this scheme, the idea solution would be to have the Lua core manage the location separate from the error object. See "Exception Patterns in Lua" (http://memebeam.org/john/lua/exception_patterns.odp) for more information. diff -urN lua-5.1.1/src/lbaselib.c lua-5.1.1_custom_errors/src/lbaselib.c --- lua-5.1.1/src/lbaselib.c 2006年06月02日 11:34:00.000000000 -0400 +++ lua-5.1.1_custom_errors/src/lbaselib.c 2006年09月06日 10:29:52.000000000 -0400 @@ -81,10 +81,14 @@ static int luaB_error (lua_State *L) { int level = luaL_optint(L, 2, 1); lua_settop(L, 1); - if (lua_isstring(L, 1) && level> 0) { /* add extra information? */ + if ((lua_isstring(L, 1) || lua_istable(L, 1)) && level> 0) { /* add extra information? */ luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); + if (lua_isstring(L, 1)) { + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + else + lua_setfield(L, 1, "_WHERE"); } return lua_error(L); } diff -urN lua-5.1.1/src/lua.c lua-5.1.1_custom_errors/src/lua.c --- lua-5.1.1/src/lua.c 2006年06月02日 11:34:00.000000000 -0400 +++ lua-5.1.1_custom_errors/src/lua.c 2006年09月06日 11:26:15.000000000 -0400 @@ -84,7 +84,24 @@ lua_pop(L, 2); return 1; } - lua_pushvalue(L, 1); /* pass error message */ + lua_getglobal(L, "tostring"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 1); + lua_pushvalue(L, 1); /* pass error object */ + } + else { + lua_pushvalue(L, 1); + lua_call(L, 1, 1); /* call tostring on error object */ + } + if (lua_istable(L, 1)) { /* use _WHERE on table error if it exists */ + lua_getfield(L, 1, "_WHERE"); + if (lua_isstring(L, -1)) { + lua_insert(L, -2); + lua_concat(L, 2); + } + else + lua_pop(L, 1); + } lua_pushinteger(L, 2); /* skip this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback */ return 1;

AltStyle によって変換されたページ (->オリジナル) /