Fix line numbers for moonscript files in error messages

This commit is contained in:
Thomas Goyne 2013-09-22 18:44:00 -07:00
parent 646e5deb52
commit 260b37ba8e
2 changed files with 53 additions and 3 deletions

View file

@ -605,6 +605,43 @@ namespace Automation4 {
return lua_gettop(L) - pretop; return lua_gettop(L) - pretop;
} }
static int moon_line(lua_State *L, int lua_line, std::string const& file)
{
if (luaL_dostring(L, "return require 'moonscript.line_tables'")) {
lua_pop(L, 1); // pop error message
return lua_line;
}
push_value(L, file);
lua_rawget(L, -2);
if (!lua_istable(L, -1)) {
lua_pop(L, 2);
return lua_line;
}
lua_rawgeti(L, -1, lua_line);
if (!lua_isnumber(L, -1)) {
lua_pop(L, 3);
return lua_line;
}
auto char_pos = static_cast<size_t>(lua_tonumber(L, -1));
lua_pop(L, 3);
// The moonscript line tables give us a character offset into the file,
// so now we need to map that to a line number
lua_getfield(L, LUA_REGISTRYINDEX, ("raw moonscript: " + file).c_str());
if (!lua_isstring(L, -1)) {
lua_pop(L, 1);
return lua_line;
}
size_t moon_len;
auto moon = lua_tolstring(L, -1, &moon_len);
return std::count(moon, moon + std::min(moon_len, char_pos), '\n') + 1;
}
static int add_stack_trace(lua_State *L) static int add_stack_trace(lua_State *L)
{ {
int level = 1; int level = 1;
@ -635,9 +672,16 @@ namespace Automation4 {
if (ar.what[0] == 't') if (ar.what[0] == 't')
frames.emplace_back("(tail call)"); frames.emplace_back("(tail call)");
else { else {
bool is_moon = false;
std::string file = ar.source; std::string file = ar.source;
if (file == "=[C]") if (file == "=[C]")
file = "<C function>"; file = "<C function>";
else if (boost::ends_with(file, ".moon"))
is_moon = true;
auto real_line = [&](int line) {
return is_moon ? moon_line(L, line, file) : line;
};
std::string function = ar.name ? ar.name : ""; std::string function = ar.name ? ar.name : "";
if (*ar.what == 'm') if (*ar.what == 'm')
@ -645,9 +689,9 @@ namespace Automation4 {
else if (*ar.what == 'C') else if (*ar.what == 'C')
function = '?'; function = '?';
else if (!*ar.namewhat) else if (!*ar.namewhat)
function = str(boost::format("<anonymous function at lines %d-%d>") % ar.linedefined % ar.lastlinedefined); function = str(boost::format("<anonymous function at lines %d-%d>") % real_line(ar.linedefined) % real_line(ar.lastlinedefined - 1));
frames.emplace_back(str(boost::format(" File \"%s\", line %d\n%s") % file % ar.currentline % function)); frames.emplace_back(str(boost::format(" File \"%s\", line %d\n%s") % file % real_line(ar.currentline) % function));
} }
} }

View file

@ -21,8 +21,9 @@
#include "auto4_lua_scriptreader.h" #include "auto4_lua_scriptreader.h"
#include "auto4_lua_utils.h"
#include <libaegisub/io.h> #include <libaegisub/io.h>
#include <libaegisub/fs.h>
#include <fstream> #include <fstream>
#include <lua.hpp> #include <lua.hpp>
@ -53,6 +54,11 @@ namespace Automation4 {
if (!agi::fs::HasExtension(filename, "moon")) if (!agi::fs::HasExtension(filename, "moon"))
return luaL_loadbuffer(L, &buff[0], buff.size(), filename.string().c_str()) == 0; return luaL_loadbuffer(L, &buff[0], buff.size(), filename.string().c_str()) == 0;
// Save the text we'll be loading for the line number rewriting in the
// error handling
push_value(L, buff);
lua_setfield(L, LUA_REGISTRYINDEX, ("raw moonscript: " + filename.string()).c_str());
// We have a MoonScript file, so we need to load it with that // We have a MoonScript file, so we need to load it with that
// It might be nice to have a dedicated lua state for compiling // It might be nice to have a dedicated lua state for compiling
// MoonScript to Lua // MoonScript to Lua