- Segueix el treball en el debugger

This commit is contained in:
2026-03-30 06:41:13 +02:00
parent 0547378331
commit 8a4110e821
4 changed files with 245 additions and 3 deletions

242
lua.cpp
View File

@@ -7,7 +7,191 @@
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <string>
#include <mutex>
#include <queue>
#include <thread>
#include <atomic>
#include <iostream>
#include <nlohmann/json.hpp>
std::unordered_map<std::string, std::vector<int>> g_breakpoints;
std::mutex g_breakMutex;
std::queue<std::string> g_debugCommands;
std::mutex g_cmdMutex;
std::atomic<bool> g_running = true;
std::atomic<bool> g_paused = false;
std::string g_pauseFile;
int g_pauseLine = 0;
namespace fs = std::filesystem;
using json = nlohmann::json;
std::string pathToChunk(const std::string& path) {
std::filesystem::path p(path);
// 1. Normalizar la ruta
p = p.lexically_normal();
// 2. Buscar el directorio "data"
auto it = std::find(p.begin(), p.end(), "data");
if (it == p.end())
return ""; // no es un script Lua válido
// 3. Construir la parte relativa después de "data"
std::filesystem::path rel;
for (++it; it != p.end(); ++it)
rel /= *it;
// 4. Quitar ".lua"
std::string s = rel.string();
if (s.ends_with(".lua"))
s = s.substr(0, s.size() - 4);
// 5. Convertir "/" → "."
for (char& c : s)
if (c == '/')
c = '.';
return s;
}
std::string chunkToPath(const std::string& chunk) {
// 1. Convertir "ia.test" → "ia/test"
std::string rel;
rel.reserve(chunk.size() + 10);
for (char c : chunk)
rel += (c == '.' ? '/' : c);
// 2. Añadir prefijo y sufijo
rel = "data/" + rel + ".lua";
// 3. Convertir a ruta absoluta
std::filesystem::path abs = std::filesystem::current_path() / rel;
return abs.lexically_normal().string();
}
void processDebugCommand(const std::string& line) {
//printf("COMANDO PROCESADO: %s\n", line.c_str());
if (!line.starts_with("@@DEBUGCMD@@"))
return;
json j = json::parse(line.substr(12));
std::string cmd = j["cmd"];
if (cmd == "setBreakpoints") {
std::string file = j["file"];
std::vector<int> lines = j["lines"];
std::lock_guard<std::mutex> lock(g_breakMutex);
std::string chunk = pathToChunk(file);
//printf("Es un BREAKPOINT: %s, %i\n", chunk.c_str(), lines[0]);
g_breakpoints[chunk] = lines;
}
else if (cmd == "continue") {
printf("CONTINUA\n\n");
g_paused = false;
}
}
bool isBreakpoint(const std::string& file, int line) {
std::lock_guard<std::mutex> lock(g_breakMutex);
//if (!g_breakpoints.empty()) {
// printf("file: %s\n", file.c_str());
//}
auto it = g_breakpoints.find(file);
if (it == g_breakpoints.end())
return false;
for (int bp : it->second) {
if (bp == line)
return true;
}
return false;
}
void sendBreakEvent(const std::string& file, int line) {
json j = {
{"type", "break"},
{"file", file},
{"line", line}
};
std::cout << "@@DEBUG@@" << j.dump() << std::endl;
std::cout.flush();
}
std::string waitForDebugCommand() {
//printf("HOLA");
while (true) {
{
std::lock_guard<std::mutex> lock(g_cmdMutex);
if (!g_debugCommands.empty()) {
std::string cmd = g_debugCommands.front();
g_debugCommands.pop();
return cmd;
}
}
SDL_Delay(1);
}
}
/*void debugCommandThread() {
std::string line;
while (true) {
if (!std::getline(std::cin, line)) {
break; // stdin cerrado
}
if (!g_running)
break;
std::lock_guard<std::mutex> lock(g_cmdMutex);
g_debugCommands.push(line);
}
}*/
extern "C" void luaHook(lua_State* L, lua_Debug* ar) {
lua_getinfo(L, "Sl", ar);
if (ar->currentline <= 0)
return;
const char* src = ar->source;
// Lua usa "@filename" para archivos reales
//if (src[0] == '@')
// src++;
int line = ar->currentline;
if (isBreakpoint(src, line)) {
g_paused = true;
g_pauseFile = src;
g_pauseLine = line;
std::string realPath = chunkToPath(src);
sendBreakEvent(realPath, line);
//sendBreakEvent(src, line);
// Esperar comandos del Debug Adapter
while (g_paused) {
std::string cmd = waitForDebugCommand();
printf("PROCESANDO COMANDO: %s\n", cmd.c_str());
processDebugCommand(cmd);
}
}
}
extern "C" {
@@ -785,7 +969,7 @@ extern "C" {
lua_newtable(L);
// name field (canonical absolute path)
lua_pushstring(L, fs::canonical(entry.path()).u8string().c_str());
lua_pushstring(L, (const char*)fs::canonical(entry.path()).u8string().c_str());
lua_setfield(L, -2, "name");
// dir field
@@ -1112,6 +1296,23 @@ bool lua_is_playing() {
return is_playing;
}
void lua_process_debugger_commands() {
while (true) {
std::string cmd;
{
std::lock_guard<std::mutex> lock(g_cmdMutex);
if (g_debugCommands.empty())
break;
cmd = g_debugCommands.front();
g_debugCommands.pop();
}
processDebugCommand(cmd);
}
}
void push_lua_funcs() {
lua_newtable(L);
lua_setglobal(L, "mini");
@@ -1512,6 +1713,7 @@ int MiniLoader(lua_State *L) {
void lua_init(const char *main_lua_file) {
L = luaL_newstate();
luaL_openlibs(L);
lua_sethook(L, luaHook, LUA_MASKLINE, 0);
push_lua_funcs();
lua_register(L, "mini_loader", MiniLoader);
luaL_dostring(L, "table.insert(package.searchers,2,mini_loader)\n");
@@ -1544,11 +1746,14 @@ void lua_init(const char *main_lua_file) {
lua_pop(L,1);
lua_pop(L,1);
//std::thread(debugCommandThread).detach();
printf("stdin isatty: %d\n", isatty(0));
is_playing = true;
}
void lua_call_init() {
if (!init_exists) return;
lua_process_debugger_commands();
lua_getglobal(L, "mini");
lua_getfield(L, -1, "init");
if (lua_pcall(L, 0, 0, 0)) {
@@ -1560,6 +1765,7 @@ void lua_call_init() {
void lua_call_update() {
if (!update_exists) return;
lua_process_debugger_commands();
delta_time = float(SDL_GetTicks() - last_update)/1000.0f;
last_update = SDL_GetTicks();
lua_getglobal(L, "mini");
@@ -1571,8 +1777,42 @@ void lua_call_update() {
}
}
#include <poll.h>
std::jthread stdinThread([](std::stop_token st) {
std::string line;
struct pollfd pfd;
pfd.fd = 0; // stdin
pfd.events = POLLIN; // queremos saber si hay datos
while (!st.stop_requested()) {
int ret = poll(&pfd, 1, 10); // timeout 10 ms
if (ret > 0 && (pfd.revents & POLLIN)) {
if (!std::getline(std::cin, line)) {
break; // EOF
}
{
std::lock_guard<std::mutex> lock(g_cmdMutex);
g_debugCommands.push(line);
printf("COMANDO RECIBIDO: %s\n", line.c_str());
}
} else {
SDL_Delay(1);
}
}
});
void lua_quit() {
if (!is_playing) return;
is_playing = false;
lua_close(L);
}
void lua_kill_thread() {
g_running = false;
stdinThread.request_stop();
}