From 7739b563f38b1d63d5492e8446cad986cff6faf9 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Tue, 31 Mar 2026 18:21:05 +0200 Subject: [PATCH] =?UTF-8?q?-=20[NEW]=20[debugger]=20Quan=20hi=20ha=20una?= =?UTF-8?q?=20excepci=C3=B3,=20ho=20notifica=20al=20adapter=20i=20li=20don?= =?UTF-8?q?a=20la=20info=20necessaria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lua.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- mini.cpp | 1 + 2 files changed, 174 insertions(+), 8 deletions(-) diff --git a/lua.cpp b/lua.cpp index 7e0165b..697572d 100644 --- a/lua.cpp +++ b/lua.cpp @@ -7,7 +7,7 @@ #include #include #include - +#include #include #include #include @@ -32,6 +32,17 @@ struct FrameInfo { //std::vector upvalues; }; +struct StackFrameInfo { + std::string file; + int line; + std::string function; +}; +std::string lastExceptionTraceback; +std::vector lastExceptionStack; +std::string lastExceptionMessage; +bool hasException = false; + +std::set exceptionFilters;// {"all"}; std::vector g_frames; lua_State *L; @@ -792,6 +803,78 @@ void sendDebugResponse(const std::string& type, const json& payload) { std::cout << "@@DEBUG@@" << msg.dump() << std::endl; } +void parseLuaTraceback(const char* tb, std::vector& out) { + out.clear(); + if (!tb) return; + + std::stringstream ss(tb); + std::string line; + + bool inFrames = false; + + while (std::getline(ss, line)) { + // Quitar espacios iniciales y tabs + while (!line.empty() && (line[0] == ' ' || line[0] == '\t')) + line.erase(line.begin()); + + // Saltar la primera línea (mensaje de error) + if (!inFrames) { + if (line.rfind("stack traceback:", 0) == 0) { + inFrames = true; + } + continue; + } + + // Formato esperado: + // [string "modules.ia.hero"]:189: in field 'ia' + // + // O: + // [string "main"]:34: in function <[string "main"]:32> + + if (line.rfind("[string \"", 0) != 0) + continue; + + // Extraer chunk name + size_t q1 = line.find('"'); + size_t q2 = line.find('"', q1 + 1); + if (q1 == std::string::npos || q2 == std::string::npos) + continue; + + std::string chunk = line.substr(q1 + 1, q2 - q1 - 1); + + // Extraer línea + size_t colon1 = line.find(':', q2 + 1); + if (colon1 == std::string::npos) + continue; + + size_t colon2 = line.find(':', colon1 + 1); + if (colon2 == std::string::npos) + continue; + + int lineNumber = std::stoi(line.substr(colon1 + 1, colon2 - colon1 - 1)); + + // Extraer nombre de función (si existe) + std::string func = "unknown"; + + size_t inField = line.find("in field '"); + if (inField != std::string::npos) { + size_t start = inField + 10; + size_t end = line.find("'", start); + func = line.substr(start, end - start); + } + + size_t inFunc = line.find("in function <"); + if (inFunc != std::string::npos) { + func = "anonymous"; + } + + // Convertir chunk → ruta real + std::string filePath = chunkToPath(chunk); + + out.push_back({ filePath, lineNumber, func }); + } +} + void processDebugCommand(const std::string& line) { //printf("COMANDO PROCESADO: %s\n", line.c_str()); if (!line.starts_with("@@DEBUGCMD@@")) @@ -855,8 +938,33 @@ void processDebugCommand(const std::string& line) { g_paused = false; } else if (cmd == "stackTrace") { - json result = getStackTrace(L); - sendDebugResponse("stackTrace", result); + if (hasException) { + parseLuaTraceback(lastExceptionTraceback.c_str(), lastExceptionStack); + + json frames = json::array(); + + for (size_t i = 0; i < lastExceptionStack.size(); i++) { + frames.push_back({ + { "id", (int)i + 1 }, + { "name", lastExceptionStack[i].function }, + { "line", lastExceptionStack[i].line }, + { "column", 1 }, + { "source", { + { "path", lastExceptionStack[i].file } + }} + }); + } + + json result = { + { "stackFrames", frames }, + { "totalFrames", frames.size() } + }; + + sendDebugResponse("stackTrace", result); + } else { + json result = getStackTrace(L); + sendDebugResponse("stackTrace", result); + } } else if (cmd == "locals") { int frame = j.value("frame", 0); @@ -931,7 +1039,12 @@ void processDebugCommand(const std::string& line) { sendDebugResponse("setVariable", result); } - + else if (cmd == "setExceptionFilters") { + exceptionFilters.clear(); + for (auto& f : j["filters"]) { + exceptionFilters.insert(f.get()); + } + } } bool checkBreakpointCondition(lua_State* L, const Breakpoint& bp) { @@ -2719,19 +2832,71 @@ void lua_call_init() { } } +void sendExceptionStoppedEvent(const std::string& msg) { + json payload = { + { "reason", "exception" }, + { "text", msg } + }; + sendDebugResponse("stopped", payload); +} + +int luaErrorHandler(lua_State* L) { + const char* msg = lua_tostring(L, 1); + if (!msg) msg = "Unknown error"; + + // Construir traceback + luaL_traceback(L, L, msg, 1); + + const char* tb = lua_tostring(L, -1); + if (tb) { + lastExceptionTraceback = tb; + } else { + lastExceptionTraceback = msg; + } + + // Devolver el traceback a Lua (aunque luego Lua lo sustituya) + return 1; +} + void lua_call_update() { if (!update_exists) return; function_has_breakpoints = false; while (!funBreakStack.empty()) funBreakStack.pop(); - lua_process_debugger_commands(); + //lua_process_debugger_commands(); delta_time = float(SDL_GetTicks() - last_update)/1000.0f; last_update = SDL_GetTicks(); lua_getglobal(L, "mini"); lua_getfield(L, -1, "update"); - if (lua_pcall(L, 0, 0, 0)) { - log_msg(LOG_LUART, "%s\n", lua_tostring(L, -1)); - lua_pop(L,1); + + lua_pushcfunction(L, luaErrorHandler); + lua_insert(L, -2); // poner handler debajo de la función + int status = lua_pcall(L, 0, 0, -2); + lua_pop(L, 1); // quitar handler + + if (status != LUA_OK) { + //log_msg(LOG_LUART, "%s\n", lua_tostring(L, -1)); + //lua_pop(L,1); is_playing = false; + + lastExceptionMessage = lastExceptionTraceback; + + // Limpiar stack anterior + //lastExceptionStack.clear(); + + // Parsear traceback en frames + //parseLuaTraceback(tb, lastExceptionStack); + + lua_pop(L, 1); // pop traceback y error + + hasException = true; + + if (exceptionFilters.count("all") || exceptionFilters.count("uncaught")) { + sendExceptionStoppedEvent(lastExceptionMessage); + return; + } + + sendLogOutput(lastExceptionMessage); + return; } } diff --git a/mini.cpp b/mini.cpp index fcad19a..dc6fc5b 100644 --- a/mini.cpp +++ b/mini.cpp @@ -791,6 +791,7 @@ int main(int argc,char*argv[]){ if (SDL_GetTicks()-dt>13) { dt = SDL_GetTicks(); + lua_process_debugger_commands(); if (lua_is_playing()) { lua_call_update(); } else {