diff --git a/lua.cpp b/lua.cpp index e537b71..7e0165b 100644 --- a/lua.cpp +++ b/lua.cpp @@ -474,6 +474,112 @@ json expandTable(lua_State* L, int ref) { }; } +json setVariable(lua_State* L, int frame, const std::string& scope, + const std::string& name, const std::string& valueStr) +{ + lua_Debug ar; + + if (!lua_getstack(L, frame, &ar)) { + return { {"error", "invalid frame"} }; + } + + lua_getinfo(L, "nSl", &ar); + + // Convertir valueStr a valor Lua + auto pushValue = [&](const std::string& s) { + // número + char* end; + double num = strtod(s.c_str(), &end); + if (*end == '\0') { + lua_pushnumber(L, num); + return; + } + + // boolean + if (s == "true") { lua_pushboolean(L, 1); return; } + if (s == "false") { lua_pushboolean(L, 0); return; } + + // nil + if (s == "nil") { lua_pushnil(L); return; } + + // string + lua_pushstring(L, s.c_str()); + }; + + if (scope == "locals") { + int i = 1; + const char* localName; + while ((localName = lua_getlocal(L, &ar, i)) != NULL) { + lua_pop(L, 1); // pop old value + + if (name == localName) { + pushValue(valueStr); + lua_setlocal(L, &ar, i); + return { {"value", valueStr} }; + } + + i++; + } + } + + if (scope == "upvalues") { + lua_getinfo(L, "f", &ar); // push function + + int i = 1; + const char* upName; + while ((upName = lua_getupvalue(L, -1, i)) != NULL) { + lua_pop(L, 1); // pop old value + + if (name == upName) { + pushValue(valueStr); + lua_setupvalue(L, -1, i); + lua_pop(L, 1); // pop function + return { {"value", valueStr} }; + } + + i++; + } + + lua_pop(L, 1); // pop function + } + + if (scope == "globals") { + pushValue(valueStr); + lua_setglobal(L, name.c_str()); + return { {"value", valueStr} }; + } + + return { {"error", "variable not found"} }; +} + +json setTableField(lua_State* L, int ref, const std::string& key, const std::string& valueStr) +{ + // Recuperar la tabla desde tu sistema de referencias + if (!pushTableFromRef(L, ref)) { + return { {"error", "invalid table ref"} }; + } + + // Convertir el valor + auto pushValue = [&](const std::string& s) { + char* end; + double num = strtod(s.c_str(), &end); + if (*end == '\0') { lua_pushnumber(L, num); return; } + if (s == "true") { lua_pushboolean(L, 1); return; } + if (s == "false") { lua_pushboolean(L, 0); return; } + if (s == "nil") { lua_pushnil(L); return; } + lua_pushstring(L, s.c_str()); + }; + + pushValue(valueStr); + + // tabla[key] = valor + lua_setfield(L, -2, key.c_str()); + + lua_pop(L, 1); // pop tabla + + return { {"value", valueStr} }; +} + json evalExpression(lua_State* L, const std::string& expr) { lua_Debug ar; if (!lua_getstack(L, 0, &ar)) { @@ -586,110 +692,95 @@ json evalExpression(lua_State* L, const std::string& expr) { return result; } -json setVariable(lua_State* L, int frame, const std::string& scope, - const std::string& name, const std::string& valueStr) -{ - lua_Debug ar; - - if (!lua_getstack(L, frame, &ar)) { - return { {"error", "invalid frame"} }; +json evalAssign(lua_State* L, int frame, const std::string& expr) { + // 1. Separar LHS y RHS + size_t eq = expr.find('='); + if (eq == std::string::npos) { + return { {"error", "not an assignment"} }; } - lua_getinfo(L, "nSl", &ar); + std::string lhs = expr.substr(0, eq); + std::string rhs = expr.substr(eq + 1); - // Convertir valueStr a valor Lua - auto pushValue = [&](const std::string& s) { - // número - char* end; - double num = strtod(s.c_str(), &end); - if (*end == '\0') { - lua_pushnumber(L, num); - return; - } - - // boolean - if (s == "true") { lua_pushboolean(L, 1); return; } - if (s == "false") { lua_pushboolean(L, 0); return; } - - // nil - if (s == "nil") { lua_pushnil(L); return; } - - // string - lua_pushstring(L, s.c_str()); + // limpiar espacios + auto trim = [](std::string& s) { + size_t a = s.find_first_not_of(" \t"); + size_t b = s.find_last_not_of(" \t"); + if (a == std::string::npos) { s = ""; return; } + s = s.substr(a, b - a + 1); }; - if (scope == "locals") { - int i = 1; - const char* localName; - while ((localName = lua_getlocal(L, &ar, i)) != NULL) { - lua_pop(L, 1); // pop old value + trim(lhs); + trim(rhs); - if (name == localName) { - pushValue(valueStr); - lua_setlocal(L, &ar, i); - return { {"value", valueStr} }; - } + // 2. Evaluar RHS usando tu evalExpression + json rhsValue = evalExpression(L, rhs); + if (rhsValue.contains("error")) { + return rhsValue; + } - i++; + std::string rhsStr = rhsValue["value"]; + + // 3. Determinar si LHS es: + // - variable simple: x + // - acceso tabla: player.health + // - acceso profundo: a.b.c + if (lhs.find('.') == std::string::npos) { + // variable simple → locals, upvalues o globals + // Intentar locals + json r = setVariable(L, frame, "locals", lhs, rhsStr); + if (!r.contains("error")) return r; + + // Intentar upvalues + r = setVariable(L, frame, "upvalues", lhs, rhsStr); + if (!r.contains("error")) return r; + + // Intentar globals + r = setVariable(L, frame, "globals", lhs, rhsStr); + return r; + } + + // 4. Acceso tabla: a.b.c + // separar en partes + std::vector parts; + { + std::stringstream ss(lhs); + std::string item; + while (std::getline(ss, item, '.')) { + trim(item); + parts.push_back(item); } } - if (scope == "upvalues") { - lua_getinfo(L, "f", &ar); // push function - - int i = 1; - const char* upName; - while ((upName = lua_getupvalue(L, -1, i)) != NULL) { - lua_pop(L, 1); // pop old value - - if (name == upName) { - pushValue(valueStr); - lua_setupvalue(L, -1, i); - lua_pop(L, 1); // pop function - return { {"value", valueStr} }; - } - - i++; - } - - lua_pop(L, 1); // pop function + if (parts.size() < 2) { + return { {"error", "invalid table assignment"} }; } - if (scope == "globals") { - pushValue(valueStr); - lua_setglobal(L, name.c_str()); - return { {"value", valueStr} }; + // La clave final + std::string finalKey = parts.back(); + parts.pop_back(); + + // 5. Evaluar la ruta de tabla (a.b.c → obtener tabla c) + // usando tu evalExpression + std::string tableExpr; + for (size_t i = 0; i < parts.size(); i++) { + if (i > 0) tableExpr += "."; + tableExpr += parts[i]; } - return { {"error", "variable not found"} }; -} - -json setTableField(lua_State* L, int ref, const std::string& key, const std::string& valueStr) -{ - // Recuperar la tabla desde tu sistema de referencias - if (!pushTableFromRef(L, ref)) { - return { {"error", "invalid table ref"} }; + json tableValue = evalExpression(L, tableExpr); + if (tableValue.contains("error")) { + return tableValue; } - // Convertir el valor - auto pushValue = [&](const std::string& s) { - char* end; - double num = strtod(s.c_str(), &end); - if (*end == '\0') { lua_pushnumber(L, num); return; } - if (s == "true") { lua_pushboolean(L, 1); return; } - if (s == "false") { lua_pushboolean(L, 0); return; } - if (s == "nil") { lua_pushnil(L); return; } - lua_pushstring(L, s.c_str()); - }; + if (tableValue["type"] != "table") { + return { {"error", "LHS is not a table"} }; + } - pushValue(valueStr); + int ref = tableValue["ref"]; - // tabla[key] = valor - lua_setfield(L, -2, key.c_str()); - - lua_pop(L, 1); // pop tabla - - return { {"value", valueStr} }; + // 6. Asignar dentro de la tabla + return setTableField(L, ref, finalKey, rhsStr); } void sendDebugResponse(const std::string& type, const json& payload) { @@ -743,6 +834,7 @@ void processDebugCommand(const std::string& line) { printf("CONTINUA\n\n"); g_stepMode = STEP_NONE; g_paused = false; + raisewindow(); } else if (cmd == "pause") { g_stepMode = STEP_INTO; @@ -807,6 +899,19 @@ void processDebugCommand(const std::string& line) { }; sendDebugResponse("eval", payload); } + else if (cmd == "evalAssign") { + int frame = j.value("frame", 0); + std::string expr = j["expr"]; + + json result = evalAssign(L, frame, expr); + + json payload = { + { "kind", "eval" }, + { "result", result } + }; + + sendDebugResponse("eval", payload); + } else if (cmd == "setVariable") { int frame = j.value("frame", 0); std::string scope = j["scope"]; @@ -840,6 +945,37 @@ bool checkBreakpointCondition(lua_State* L, const Breakpoint& bp) { return false; } +std::string expandLogMessage(lua_State* L, const std::string& msg) { + std::string out; + size_t i = 0; + + while (i < msg.size()) { + if (msg[i] == '{') { + size_t j = msg.find('}', i + 1); + if (j == std::string::npos) break; + + std::string expr = msg.substr(i + 1, j - i - 1); + + json r = evalExpression(L, expr); + out += r.value("value", "nil"); + + i = j + 1; + } else { + out += msg[i++]; + } + } + + return out; +} + +void sendLogOutput(const std::string& text) { + json payload = { + { "kind", "log" }, + { "text", text } + }; + sendDebugResponse("log", payload); +} + bool isBreakpoint(const std::string& file, int line) { std::lock_guard lock(g_breakMutex); @@ -849,9 +985,14 @@ bool isBreakpoint(const std::string& file, int line) { for (auto& bp : it->second) { if (bp.line == line) { - if (checkBreakpointCondition(L, bp)) { + if (!bp.logMessage.empty()) { + std::string msg = expandLogMessage(L, bp.logMessage); + sendLogOutput(msg); + return false; // NO parar + } else if (checkBreakpointCondition(L, bp)) { return true; } + } } diff --git a/mini.cpp b/mini.cpp index 276f4ab..fcad19a 100644 --- a/mini.cpp +++ b/mini.cpp @@ -146,6 +146,11 @@ int16_t beats, num_beats = 0; void createNewProject(); +void raisewindow() { + SDL_RaiseWindow(mini_win); + //SDL_SetWindowInputFocus(mini_win); +} + char* get_value_from_line(char* line) { char* equal_character = strchr(line, '='); if (equal_character == NULL) return NULL; diff --git a/mini.h b/mini.h index 7b1eefe..74dcd46 100644 --- a/mini.h +++ b/mini.h @@ -124,6 +124,8 @@ void loop(); int scrw(); int scrh(); +void raisewindow(); + uint8_t newsurf(int w, int h); uint8_t loadsurf(const char* filename, const bool external = false); void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors=0);