Step 335: C++ Generator — Inheritance + Templates (12/12 tests)

Updated CppGenerator, PythonGenerator, JavaGenerator for multiple inheritance
output using getBases(). C++ emits template prefix + access specifiers + virtual.
Python uses direct multi-base. Java uses extends + implements adaptation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bill
2026-02-16 00:29:54 -07:00
parent b75fba72d8
commit 6464c88483
6 changed files with 331 additions and 4 deletions

View File

@@ -2014,4 +2014,8 @@ target_link_libraries(step334_test PRIVATE
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step335_test tests/step335_test.cpp)
target_include_directories(step335_test PRIVATE src)
target_link_libraries(step335_test PRIVATE nlohmann_json::nlohmann_json)
# Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies)

View File

@@ -110,8 +110,36 @@
std::ostringstream oss;
auto annotations = cls->getChildren("annotations");
for (const auto* a : annotations) oss << generate(a) << "\n";
// Template prefix if has GenericType children with isClassTemplate
auto tpChildren = cls->getChildren("typeParameters");
for (const auto* tpc : tpChildren) {
if (tpc->conceptType == "GenericType") {
auto* gt = static_cast<const GenericType*>(tpc);
if (gt->isClassTemplate) {
oss << "template<";
auto params = gt->getChildren("typeParameters");
for (size_t i = 0; i < params.size(); ++i) {
if (i > 0) oss << ", ";
auto* tp = static_cast<const TypeParameter*>(params[i]);
if (tp->isVariadic) oss << "typename... " << tp->name;
else oss << "typename " << tp->name;
}
oss << ">\n";
break;
}
}
}
oss << "class " << cls->name;
if (!cls->superClass.empty()) oss << " : public " << cls->superClass;
auto bases = cls->getBases();
if (!bases.empty()) {
oss << " : ";
for (size_t i = 0; i < bases.size(); ++i) {
if (i > 0) oss << ", ";
oss << bases[i].accessSpecifier;
if (bases[i].isVirtual) oss << " virtual";
oss << " " << bases[i].name;
}
}
oss << " {\npublic:\n";
auto fields = cls->getChildren("fields");
for (const auto* f : fields)

View File

@@ -451,10 +451,21 @@ public:
for (const auto* a : annotations) oss << generate(a) << "\n";
if (cls->isAbstract) oss << "abstract ";
oss << "class " << cls->name;
if (!cls->superClass.empty()) oss << " extends " << cls->superClass;
auto bases = cls->getBases();
if (!bases.empty()) {
// First base → extends, rest → implements (Java adaptation)
oss << " extends " << bases[0].name;
if (bases.size() > 1) {
oss << " implements ";
for (size_t i = 1; i < bases.size(); ++i) {
if (i > 1) oss << ", ";
oss << bases[i].name;
}
}
}
auto interfaces = cls->getChildren("interfaces");
if (!interfaces.empty()) {
oss << " implements ";
oss << (bases.size() > 1 ? ", " : " implements ");
for (size_t i = 0; i < interfaces.size(); ++i) {
if (i > 0) oss << ", ";
oss << generate(interfaces[i]);

View File

@@ -538,7 +538,15 @@ public:
auto annotations = cls->getChildren("annotations");
for (const auto* a : annotations) oss << generate(a) << "\n";
oss << "class " << cls->name;
if (!cls->superClass.empty()) oss << "(" << cls->superClass << ")";
auto bases = cls->getBases();
if (!bases.empty()) {
oss << "(";
for (size_t i = 0; i < bases.size(); ++i) {
if (i > 0) oss << ", ";
oss << bases[i].name;
}
oss << ")";
}
oss << ":\n";
auto fields = cls->getChildren("fields");
auto methods = cls->getChildren("methods");

View File

@@ -0,0 +1,221 @@
// Step 335: C++ Generator — Inheritance + Templates (12 tests)
// Tests C++ output for multiple inheritance, virtual, template classes,
// cross-language adaptation
#include <cassert>
#include <iostream>
#include <string>
#include "ast/ClassDeclaration.h"
#include "ast/GenericType.h"
#include "ast/AsyncNodes.h"
#include "ast/CppGenerator.h"
#include "ast/PythonGenerator.h"
#include "ast/JavaGenerator.h"
#include "ast/RustGenerator.h"
#include "ast/Serialization.h"
int main() {
int passed = 0;
// Test 1: C++ multiple inheritance output
{
auto* cls = new ClassDeclaration("cls1", "Widget");
cls->addBase("Base", "public");
cls->addBase("Mixin", "public");
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("class Widget") != std::string::npos);
assert(out.find("public Base") != std::string::npos);
assert(out.find("public Mixin") != std::string::npos);
delete cls;
std::cout << "Test 1 PASSED: C++ multiple inheritance output\n";
passed++;
}
// Test 2: Access specifier output
{
auto* cls = new ClassDeclaration("cls2", "D");
cls->addBase("A", "public");
cls->addBase("B", "protected");
cls->addBase("C", "private");
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("public A") != std::string::npos);
assert(out.find("protected B") != std::string::npos);
assert(out.find("private C") != std::string::npos);
delete cls;
std::cout << "Test 2 PASSED: Access specifier output\n";
passed++;
}
// Test 3: Virtual keyword present
{
auto* cls = new ClassDeclaration("cls3", "D");
cls->addBase("Base", "public", true);
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("virtual") != std::string::npos);
assert(out.find("Base") != std::string::npos);
delete cls;
std::cout << "Test 3 PASSED: Virtual keyword present\n";
passed++;
}
// Test 4: Template class output
{
auto* cls = new ClassDeclaration("cls4", "Container");
auto* gt = new GenericType("gt1", "Container");
gt->isClassTemplate = true;
auto* tp = new TypeParameter("tp1", "T");
gt->addChild("typeParameters", tp);
cls->addChild("typeParameters", gt);
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("template") != std::string::npos);
assert(out.find("typename T") != std::string::npos || out.find("T") != std::string::npos);
assert(out.find("class Container") != std::string::npos);
delete cls;
std::cout << "Test 4 PASSED: Template class output\n";
passed++;
}
// Test 5: CRTP output
{
auto* cls = new ClassDeclaration("cls5", "Derived");
cls->addBase("Base<Derived>", "public");
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("Base<Derived>") != std::string::npos);
delete cls;
std::cout << "Test 5 PASSED: CRTP output\n";
passed++;
}
// Test 6: Cross-language C++ → Python (multiple bases → direct multiple inheritance)
{
auto* cls = new ClassDeclaration("cls6", "D");
cls->addBase("A", "public");
cls->addBase("B", "public");
PythonGenerator gen;
std::string out = gen.generate(cls);
// Python should show both bases
assert(out.find("class D") != std::string::npos);
assert(out.find("A") != std::string::npos);
assert(out.find("B") != std::string::npos);
delete cls;
std::cout << "Test 6 PASSED: C++ → Python multiple inheritance\n";
passed++;
}
// Test 7: Cross-language C++ → Java (multiple bases → extends + implements)
{
auto* cls = new ClassDeclaration("cls7", "Widget");
cls->addBase("Base", "public");
cls->addBase("Drawable", "public");
JavaGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("class Widget") != std::string::npos);
// Java should at least show first as extends
assert(out.find("Base") != std::string::npos);
delete cls;
std::cout << "Test 7 PASSED: C++ → Java inheritance output\n";
passed++;
}
// Test 8: Cross-language C++ → Rust (no inheritance, traits)
{
auto* cls = new ClassDeclaration("cls8", "Widget");
cls->addBase("Base", "public");
RustGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("Widget") != std::string::npos);
// Rust uses struct, not class inheritance
assert(!out.empty());
delete cls;
std::cout << "Test 8 PASSED: C++ → Rust struct output\n";
passed++;
}
// Test 9: Template class with variadic
{
auto* cls = new ClassDeclaration("cls9", "Tuple");
auto* gt = new GenericType("gt2", "Tuple");
gt->isClassTemplate = true;
auto* tp1 = new TypeParameter("tp2", "Head");
auto* tp2 = new TypeParameter("tp3", "Tail");
tp2->isVariadic = true;
gt->addChild("typeParameters", tp1);
gt->addChild("typeParameters", tp2);
cls->addChild("typeParameters", gt);
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("template") != std::string::npos);
assert(out.find("Tail") != std::string::npos);
assert(out.find("...") != std::string::npos); // variadic pack
delete cls;
std::cout << "Test 9 PASSED: Variadic template class output\n";
passed++;
}
// Test 10: Combined template + multiple inheritance output
{
auto* cls = new ClassDeclaration("cls10", "MyGen");
cls->addBase("ProjectionGenerator", "public");
cls->addBase("SemannoAnnotationImpl<MyGen>", "public");
auto* gt = new GenericType("gt3", "MyGen");
gt->isClassTemplate = true;
auto* tp = new TypeParameter("tp4", "T");
gt->addChild("typeParameters", tp);
cls->addChild("typeParameters", gt);
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("template") != std::string::npos);
assert(out.find("class MyGen") != std::string::npos);
assert(out.find("ProjectionGenerator") != std::string::npos);
assert(out.find("SemannoAnnotationImpl<MyGen>") != std::string::npos);
delete cls;
std::cout << "Test 10 PASSED: Combined template + multiple inheritance\n";
passed++;
}
// Test 11: Method with visibility in class
{
auto* cls = new ClassDeclaration("cls11", "Foo");
cls->addBase("Bar", "public");
auto* meth = new MethodDeclaration("m1", "doStuff");
meth->className = "Foo";
meth->isVirtual = true;
cls->addChild("methods", meth);
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("virtual") != std::string::npos);
assert(out.find("doStuff") != std::string::npos);
delete cls;
std::cout << "Test 11 PASSED: Method with visibility in class\n";
passed++;
}
// Test 12: Roundtrip: AST → generate → verify structure
{
auto* cls = new ClassDeclaration("cls12", "Stack");
cls->addBase("Container", "public");
cls->addBase("Serializable", "public");
cls->isAbstract = true;
auto* field = new Variable("v1", "size_");
cls->addChild("fields", field);
CppGenerator gen;
std::string out = gen.generate(cls);
assert(out.find("class Stack") != std::string::npos);
assert(out.find("Container") != std::string::npos);
assert(out.find("Serializable") != std::string::npos);
assert(out.find("size_") != std::string::npos);
assert(out.length() > 20);
delete cls;
std::cout << "Test 12 PASSED: Full class generation roundtrip\n";
passed++;
}
std::cout << "\nResults: " << passed << "/12 tests passed\n";
return (passed == 12) ? 0 : 1;
}

View File

@@ -1491,6 +1491,61 @@ diamond inheritance detection via static hasDiamondInheritance() with BFS traver
access specifiers, virtual inheritance, JSON roundtrip, diamond detection, legacy
migration, addBase helper, full serialization roundtrip
### Step 333: Template Class Declarations
**Status:** PASS (12/12 tests)
Extended GenericType with isClassTemplate flag and TypeParameter with isVariadic for
variadic template packs. Added isCRTPClass() helper for CRTP pattern detection. Full
serialization round-trip for both flags.
**Files modified:**
- `editor/src/ast/GenericType.h` — isCRTPClass() helper, isClassTemplate/isVariadic
already had fields, replaced stub isCRTP()
- `editor/src/ast/Serialization.h` — isClassTemplate for GenericType, isVariadic for
TypeParameter in propertiesToJson/createNode/setPropertiesFromJson
- `editor/src/CompactAST.h` — getNodeName for GenericType ("template:name"), TypeParameter
- `editor/CMakeLists.txt` — step333_test target
**Files created:**
- `editor/tests/step333_test.cpp` — 12 tests: isClassTemplate flag, isVariadic,
CRTP detection, JSON roundtrip, CompactAST output
### Step 334: C++ Parser — Inheritance + Templates
**Status:** PASS (12/12 tests)
Extended CppParser to extract multiple base classes from tree-sitter CST, including
access specifiers and virtual keyword. Iterates ALL children (named + unnamed) of
base_class_clause to detect virtual (unnamed node), access_specifier, and type identifiers.
**Files modified:**
- `editor/src/ast/CppParser.h` — Rewrote base_class_clause parsing to iterate all
children with pending access/virtual state machine
- `editor/CMakeLists.txt` — step334_test target with tree-sitter libraries
**Files created:**
- `editor/tests/step334_test.cpp` — 12 tests: single/multiple inheritance, access
specifiers, virtual, template classes, CRTP detection, struct default public
### Step 335: C++ Generator — Inheritance + Templates
**Status:** PASS (12/12 tests)
Updated CppGenerator, PythonGenerator, and JavaGenerator to emit correct inheritance
syntax using getBases(). C++ outputs access specifiers + virtual keyword + template
prefix. Python outputs direct multiple inheritance. Java uses first base as extends,
rest as implements.
**Files modified:**
- `editor/src/ast/CppGeneratorTypes.h` — visitClassDeclaration: template prefix from
GenericType.isClassTemplate, multiple inheritance with access specifiers + virtual
- `editor/src/ast/PythonGenerator.h` — visitClassDeclaration: getBases() for multi-base
- `editor/src/ast/JavaGenerator.h` — visitClassDeclaration: extends + implements adaptation
- `editor/CMakeLists.txt` — step335_test target
**Files created:**
- `editor/tests/step335_test.cpp` — 12 tests: C++ multi-inheritance, access specifiers,
virtual, template class, CRTP, cross-language (Python/Java/Rust), variadic templates,
combined template + inheritance, method visibility, full roundtrip
---
# Roadmap Planning — Sprints 12-25+