From 5952c51cb9fdcdf11b208b9d7e0559190ca93f10 Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 7 Feb 2026 08:19:25 -0700 Subject: [PATCH] Step 42 TDD test: C++ type generation Tests PrimitiveType mapping (int, string->std::string, bool, float->double), ListType->std::vector, MapType->std::map, SetType->std::unordered_set, OptionalType->std::optional, CustomType, and typed function parameters. Co-Authored-By: Claude Opus 4.6 --- editor/CMakeLists.txt | 3 + editor/tests/step42_test.cpp | 194 +++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 editor/tests/step42_test.cpp diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index e23e831..a88e8e8 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -139,6 +139,9 @@ target_include_directories(step40_test PRIVATE src) add_executable(step41_test tests/step41_test.cpp) target_include_directories(step41_test PRIVATE src) +add_executable(step42_test tests/step42_test.cpp) +target_include_directories(step42_test PRIVATE src) + add_executable(whetstone_editor src/main.cpp) target_include_directories(whetstone_editor PRIVATE src) # find_package(SDL2 REQUIRED) # Commented out for now to avoid build issues diff --git a/editor/tests/step42_test.cpp b/editor/tests/step42_test.cpp new file mode 100644 index 0000000..3979a60 --- /dev/null +++ b/editor/tests/step42_test.cpp @@ -0,0 +1,194 @@ +// Step 42 TDD Test: C++ type generation +// +// Tests that CppGenerator maps SemAnno types to C++ equivalents: +// 1. PrimitiveType "int" → "int", "string" → "std::string", "bool" → "bool", "float" → "double" +// 2. ListType → "std::vector" +// 3. MapType → "std::map" +// 4. SetType → "std::unordered_set" +// 5. OptionalType → "std::optional" +// 6. ArrayType → "std::array" or "T[]" +// 7. CustomType → type name as-is +// 8. Function with typed parameters produces correct C++ declarations +// +// Will fail to compile until CppGenerator is implemented. + +#include +#include +#include +#include "ast/Generator.h" + +static bool contains(const std::string& haystack, const std::string& needle) { + return haystack.find(needle) != std::string::npos; +} + +int main() { + int passed = 0; + int failed = 0; + + // --- Test 1: PrimitiveType int --- + { + PrimitiveType type("t1", "int"); + CppGenerator gen; + std::string output = gen.generate(&type); + assert(contains(output, "int") && "PrimitiveType 'int' should generate 'int'"); + + std::cout << "Test 1 PASS: PrimitiveType 'int' → 'int'" << std::endl; + ++passed; + } + + // --- Test 2: PrimitiveType string → std::string --- + { + PrimitiveType type("t1", "string"); + CppGenerator gen; + std::string output = gen.generate(&type); + assert(contains(output, "std::string") && "PrimitiveType 'string' should generate 'std::string'"); + + std::cout << "Test 2 PASS: PrimitiveType 'string' → 'std::string'" << std::endl; + ++passed; + } + + // --- Test 3: PrimitiveType bool --- + { + PrimitiveType type("t1", "bool"); + CppGenerator gen; + std::string output = gen.generate(&type); + assert(contains(output, "bool") && "PrimitiveType 'bool' should generate 'bool'"); + + std::cout << "Test 3 PASS: PrimitiveType 'bool' → 'bool'" << std::endl; + ++passed; + } + + // --- Test 4: PrimitiveType float → double --- + { + PrimitiveType type("t1", "float"); + CppGenerator gen; + std::string output = gen.generate(&type); + assert(contains(output, "double") && "PrimitiveType 'float' should generate 'double'"); + + std::cout << "Test 4 PASS: PrimitiveType 'float' → 'double'" << std::endl; + ++passed; + } + + // --- Test 5: ListType → std::vector --- + { + ListType listType; + PrimitiveType* elemType = new PrimitiveType("t1", "int"); + listType.setChild("elementType", elemType); + + CppGenerator gen; + std::string output = gen.generate(&listType); + assert(contains(output, "std::vector") && "ListType should generate 'std::vector'"); + assert(contains(output, "int") && "ListType element type should appear"); + + std::cout << "Test 5 PASS: ListType → 'std::vector'" << std::endl; + ++passed; + + delete elemType; + } + + // --- Test 6: MapType → std::map --- + { + MapType mapType; + PrimitiveType* keyType = new PrimitiveType("t1", "string"); + PrimitiveType* valType = new PrimitiveType("t2", "int"); + mapType.setChild("keyType", keyType); + mapType.setChild("valueType", valType); + + CppGenerator gen; + std::string output = gen.generate(&mapType); + assert(contains(output, "std::map") && "MapType should generate 'std::map'"); + assert(contains(output, "std::string") && "Map key type should be std::string"); + assert(contains(output, "int") && "Map value type should be int"); + + std::cout << "Test 6 PASS: MapType → 'std::map'" << std::endl; + ++passed; + + delete valType; + delete keyType; + } + + // --- Test 7: SetType → std::unordered_set --- + { + SetType setType; + PrimitiveType* elemType = new PrimitiveType("t1", "int"); + setType.setChild("elementType", elemType); + + CppGenerator gen; + std::string output = gen.generate(&setType); + assert((contains(output, "std::unordered_set") || contains(output, "std::set")) && + "SetType should generate std::unordered_set or std::set"); + assert(contains(output, "int") && "Set element type should appear"); + + std::cout << "Test 7 PASS: SetType → std::unordered_set or std::set" << std::endl; + ++passed; + + delete elemType; + } + + // --- Test 8: OptionalType → std::optional --- + { + OptionalType optType; + PrimitiveType* innerType = new PrimitiveType("t1", "int"); + optType.setChild("innerType", innerType); + + CppGenerator gen; + std::string output = gen.generate(&optType); + assert(contains(output, "std::optional") && "OptionalType should generate 'std::optional'"); + assert(contains(output, "int") && "Optional inner type should appear"); + + std::cout << "Test 8 PASS: OptionalType → 'std::optional'" << std::endl; + ++passed; + + delete innerType; + } + + // --- Test 9: CustomType → type name --- + { + CustomType type("t1", "Widget"); + CppGenerator gen; + std::string output = gen.generate(&type); + assert(contains(output, "Widget") && "CustomType should generate type name"); + + std::cout << "Test 9 PASS: CustomType → 'Widget'" << std::endl; + ++passed; + } + + // --- Test 10: Function with typed parameters in C++ --- + { + Function fn("f1", "process"); + PrimitiveType* retType = new PrimitiveType("t0", "int"); + fn.setChild("returnType", retType); + + Parameter* p1 = new Parameter("p1", "name"); + PrimitiveType* p1Type = new PrimitiveType("t1", "string"); + p1->setChild("type", p1Type); + fn.addChild("parameters", p1); + + Parameter* p2 = new Parameter("p2", "count"); + PrimitiveType* p2Type = new PrimitiveType("t2", "int"); + p2->setChild("type", p2Type); + fn.addChild("parameters", p2); + + CppGenerator gen; + std::string output = gen.generate(&fn); + + assert(contains(output, "int") && "Return type should appear"); + assert(contains(output, "process") && "Function name should appear"); + assert(contains(output, "std::string") && "String parameter type should be std::string"); + assert(contains(output, "name") && "First parameter name should appear"); + assert(contains(output, "count") && "Second parameter name should appear"); + + std::cout << "Test 10 PASS: Function with typed params generates correct C++ declaration" << std::endl; + ++passed; + + delete p2Type; + delete p2; + delete p1Type; + delete p1; + delete retType; + } + + // --- Summary --- + std::cout << "\n=== Step 42 Results: " << passed << " passed, " << failed << " failed ===" << std::endl; + return failed > 0 ? 1 : 0; +}