diff --git a/PROGRESS.md b/PROGRESS.md index b490214..f804c37 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -382,7 +382,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi ## What's Next -Sprint 5 in progress. Step 137 (function composition builder) done. Next: Step 138 (type-aware code generation). +Sprint 5 in progress. Step 138 (type-aware code generation) done. Next: Step 139 (library compatibility matrix). --- @@ -483,5 +483,6 @@ Sprint 5 in progress. Step 137 (function composition builder) done. Next: Step 1 | 2026-02-09 | Codex | Step 135: Library-aware completion ordering with auto-import hints for non-primitive symbols. 5/5 tests pass. | | 2026-02-09 | Codex | Step 136: Agent preferImports/strictMode policy checks on mutations with warnings or blocking. 4/4 tests pass. | | 2026-02-09 | Codex | Step 137: Composition builder panel with pipeline generation and code insertion. 4/4 tests pass. | +| 2026-02-09 | Codex | Step 138: Type-aware C++ generation via library call mappings. 2/2 tests pass. | | 2026-02-09 | Codex | Added FEATURE_REQUESTS.md to track security vulnerability awareness and semantic library annotations for future sprints. | | 2026-02-09 | Codex | Added LLM tooling + MCP bridge feature request to FEATURE_REQUESTS.md. | diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 02d432e..d55e566 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -766,6 +766,10 @@ add_executable(step137_test tests/step137_test.cpp) target_include_directories(step137_test PRIVATE src) target_link_libraries(step137_test PRIVATE nlohmann_json::nlohmann_json) +add_executable(step138_test tests/step138_test.cpp) +target_include_directories(step138_test PRIVATE src) +target_link_libraries(step138_test PRIVATE nlohmann_json::nlohmann_json) + find_package(SDL2 CONFIG REQUIRED) find_package(OpenGL REQUIRED) find_package(glad CONFIG REQUIRED) diff --git a/editor/src/TypeAwareMappings.h b/editor/src/TypeAwareMappings.h new file mode 100644 index 0000000..fb84bce --- /dev/null +++ b/editor/src/TypeAwareMappings.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include + +static inline std::string mapTypeForFunctionCall(const std::string& targetLanguage, + const std::string& functionName) { + if (targetLanguage == "cpp") { + static const std::unordered_map cppMap = { + {"numpy.array", "std::vector"}, + {"numpy.zeros", "std::vector"}, + {"numpy.ones", "std::vector"}, + {"pandas.DataFrame", "std::vector>"}, + {"torch.tensor", "std::vector"} + }; + auto it = cppMap.find(functionName); + if (it != cppMap.end()) return it->second; + } + if (targetLanguage == "rust") { + static const std::unordered_map rustMap = { + {"numpy.array", "Vec"}, + {"numpy.zeros", "Vec"}, + {"numpy.ones", "Vec"} + }; + auto it = rustMap.find(functionName); + if (it != rustMap.end()) return it->second; + } + return ""; +} diff --git a/editor/src/ast/CppGenerator.h b/editor/src/ast/CppGenerator.h index cf2c412..b6b73fe 100644 --- a/editor/src/ast/CppGenerator.h +++ b/editor/src/ast/CppGenerator.h @@ -1,5 +1,6 @@ #pragma once #include "ProjectionGenerator.h" +#include "../TypeAwareMappings.h" class CppGenerator : public ProjectionGenerator { public: @@ -106,6 +107,13 @@ public: typeStr = generate(type); } + auto initializer = variable->getChild("initializer"); + if (!type && initializer && initializer->conceptType == "FunctionCall") { + auto* call = static_cast(initializer); + std::string mapped = mapTypeForFunctionCall("cpp", call->functionName); + if (!mapped.empty()) typeStr = mapped; + } + // Check enclosing function for memory annotations that affect variable types std::string wrapper = getMemoryTypeWrapper(variable); if (!wrapper.empty()) { @@ -113,8 +121,6 @@ public: } else { oss << typeStr << " " << variable->name; } - - auto initializer = variable->getChild("initializer"); if (initializer) { oss << " = " << generate(initializer); } diff --git a/editor/tests/step138_test.cpp b/editor/tests/step138_test.cpp new file mode 100644 index 0000000..cbca4a6 --- /dev/null +++ b/editor/tests/step138_test.cpp @@ -0,0 +1,46 @@ +// Step 138 TDD Test: Type-aware code generation +#include "ast/CppGenerator.h" +#include "ast/Module.h" +#include "ast/Variable.h" +#include "ast/Expression.h" +#include + +static void expect(bool cond, const std::string& name, int& passed, int& failed) { + if (cond) { + std::cout << "Test " << (passed + failed + 1) << " PASS: " << name << "\n"; + ++passed; + } else { + std::cout << "Test " << (passed + failed + 1) << " FAIL: " << name << "\n"; + ++failed; + } +} + +int main() { + int passed = 0; + int failed = 0; + + Module mod("m1", "Module", "cpp"); + auto* var = new Variable("v1", "arr"); + auto* call = new FunctionCall(); + call->functionName = "numpy.array"; + var->setChild("initializer", call); + mod.addChild("variables", var); + + CppGenerator gen; + std::string out = gen.generate(&mod); + expect(out.find("std::vector arr") != std::string::npos, + "mapped numpy.array to std::vector", passed, failed); + + Module mod2("m2", "Module", "cpp"); + auto* var2 = new Variable("v2", "val"); + auto* call2 = new FunctionCall(); + call2->functionName = "custom.fn"; + var2->setChild("initializer", call2); + mod2.addChild("variables", var2); + std::string out2 = gen.generate(&mod2); + expect(out2.find("auto val") != std::string::npos, + "unknown call keeps auto", passed, failed); + + std::cout << "\n=== Step 138 Results: " << passed << " passed, " << failed << " failed ===\n"; + return failed == 0 ? 0 : 1; +} diff --git a/sprint5_plan.md b/sprint5_plan.md index 6a47622..a50680e 100644 --- a/sprint5_plan.md +++ b/sprint5_plan.md @@ -139,7 +139,7 @@ what's already available. backed by real library APIs. *New:* `CompositionBuilder.h`, `CompositionPanel` in `main.cpp` -- [ ] **Step 138: Type-aware code generation** +- [x] **Step 138: Type-aware code generation** Enhance generators to use `TypeSignature` information from imported libraries. When generating C++ from Python code that uses numpy, the generator knows `numpy.array` maps to `std::vector` (or Eigen::MatrixXd).