# Sprint 162 Plan: Fix Class Emission in All Language Generators ## Context A/B test run on 2026-02-25 (see `docs/ab_test_ast_vs_language_first_2026-02-25.md`) exposed that `whetstone_run_pipeline` Python→C++ emitted an empty namespace when given a Python class as input. A full audit of all 8 language generators revealed the root cause is systemic and identical across every language: **`visitModule` never calls `getChildren("classes")`.** Every generator's `visitModule` iterates variables and functions only. Parsers correctly populate the "classes" role during parsing — `ClassDeclaration` nodes are in the AST — but the module walk skips them entirely. Classes are silently dropped from all generated output across all 8 languages. The `visitClassDeclaration` implementations are mostly already written and correct: | Language | `visitClassDeclaration` | Line range | Status | |----------|------------------------|------------|--------| | Python | Yes | PythonGenerator.h:535–562 | Good | | Rust | Yes | RustGenerator.h:427–444 | Good — struct + impl | | Go | Yes | GoGenerator.h:412–425 | Good — struct + receivers | | Java | Yes | JavaGenerator.h:447–483 | Good — handles abstract/extends | | JavaScript | Yes | JavaScriptGenerator.h:454–469 | Good — ES6 class syntax | | TypeScript | Yes (inherited from JS) | — | Good | | Elisp | Yes | ElispGenerator.h:497–513 | Good — cl-defstruct | | **C++** | **No** | CppGenerator.h | **Missing entirely** | The fix for 7 languages is adding `getChildren("classes")` iteration to `visitModule` — approximately 3 lines each. C++ additionally needs `visitClassDeclaration` written from scratch. Java and JavaScript have a secondary issue: their `visitModule` reconstructs classes from function-name heuristics instead of the AST. That heuristic path must be replaced with the real `getChildren("classes")` iteration. This sprint fixes all 8 generators in one pass. After this sprint, any language can emit a class from a parsed AST, and cross-language class transpilation (e.g. Python → C++, Python → Rust) works end-to-end. --- ## Goals 1. Add `getChildren("classes")` iteration to `visitModule` in all 8 generators 2. Write `visitClassDeclaration` for C++ (the only language missing it entirely) 3. Replace the function-name heuristic in Java and JavaScript `visitModule` with real AST class iteration 4. End-to-end: the exact Python PriorityQueue from the A/B test must produce compilable output in C++, Rust, and Go via `run_pipeline` --- ## Steps ### Step 1854: Fix `visitModule` in Python, Rust, Go, Elisp generators (12 tests) For each of these four generators, add a loop after the existing functions iteration in `visitModule`: ```cpp for (auto& cls : node->getChildren("classes")) { result += dispatchGenerate(cls); } ``` No other changes — `visitClassDeclaration` already works correctly in all four. Tests (12, 3 per language): Python class round-trips through parse→generate, Rust class produces `struct` + `impl` block, Go class produces `type X struct` with method receivers, Elisp class produces `cl-defstruct` — and for each, a module containing both a function and a class emits both (function not lost, class not lost). ### Step 1855: Fix `visitModule` in Java and JavaScript generators (10 tests) Java and JavaScript use a function-name heuristic to reconstruct classes (partitioning function names to guess class membership) instead of reading `getChildren("classes")`. Replace the heuristic path with the real AST iteration. For both generators, `visitModule` should iterate `getChildren("classes")` using `dispatchGenerate(cls)` — same pattern as Step 1854. The existing `visitClassDeclaration` implementations (Java:447–483, JavaScript:454–469) remain unchanged. TypeScript inherits from JavaScript and requires no separate change. Tests (10): Java class produces correct `public class X { }` syntax, Java class with extends emits `extends`, Java abstract class emits `abstract`, JavaScript class produces ES6 `class X { }` syntax, JavaScript class with superclass emits `extends`, TypeScript class works via inheritance, Java module with function + class emits both, JavaScript module with function + class emits both, no heuristic path remains (grep for the old partition logic returns nothing), regression: existing function-only modules still work correctly. ### Step 1856: Write `visitClassDeclaration` for C++ generator (12 tests) C++ is the only language missing `visitClassDeclaration` entirely. Add it to `CppGenerator.h`. The implementation must emit a complete header-only C++ class: - `struct` for pure data classes (no methods other than comparators) - `class` with `public:` section for classes with methods - Fields with inferred types: Python `str` → `std::string`, `int` → `int`, `bool` → `bool`, `float` → `double`, unknown → `auto /* TODO: specify type */` - Method declarations with `auto` parameter/return types when not inferrable - Required `#include` directives (`` when string fields present, etc.) Also add `getChildren("classes")` to C++ `visitModule` (same 3-line pattern as Step 1854). Tests (12): empty class emits valid C++ `class X { };`, class with string field emits `std::string`, class with int field emits `int`, class with unknown field emits `auto` with TODO comment, class with methods emits method declarations, visitModule emits both functions and classes, `#include ` present when string field exists, pragma once present at module level, C++ class output parseable by Whetstone's own CppParser, class with `__init__`-style constructor emits C++ constructor, class with only fields uses `struct`, class with methods uses `class` with `public:`. ### Step 1857: End-to-end — Python PriorityQueue → C++, Rust, Go (10 tests) Create `editor/src/Sprint162EndToEnd.h`. Uses the exact Python source from the failing 2026-02-25 A/B run. Runs it through `run_pipeline` targeting C++, Rust, and Go. All three must produce non-empty, parseable output containing the class definitions. Expected C++ output: contains `class WorkItem`, `class PriorityQueue`, `enqueue`, `dequeue`, `std::string`, `int`. Expected Rust output: contains `struct WorkItem`, `impl PriorityQueue`, `fn enqueue`, `fn dequeue`. Expected Go output: contains `type WorkItem struct`, `type PriorityQueue struct`, method receivers for `enqueue` and `dequeue`. Tests (10): C++ output non-empty, C++ contains "class WorkItem", C++ contains "class PriorityQueue", C++ contains "std::string", Rust output non-empty, Rust contains "struct WorkItem", Rust contains "impl PriorityQueue", Go output non-empty, Go contains "type WorkItem struct", Go contains "type PriorityQueue struct". ### Step 1858: Sprint 162 Integration Summary (8 tests) Create `editor/src/Sprint162IntegrationSummary.h`. Record: steps_completed=5 (1854–1858), root_cause="visitModule skips getChildren(classes) in all 8 generators", languages_fixed=8, new_code_written="CppGenerator::visitClassDeclaration only — all other visitClassDeclaration implementations pre-existing", ab_test_reference= "docs/ab_test_ast_vs_language_first_2026-02-25.md", success=true. Full sprint regression: steps 1854–1858 pass. All existing function-level pipeline tests pass (no regression). Tests (8): struct constructable, steps_completed==5, languages_fixed==8, root_cause non-empty, all 8 generators emit classes, Python round-trip works, C++ round-trip works, success==true. --- ## Architecture Gate - No new files required except Sprint162IntegrationSummary.h and the C++ visitClassDeclaration (added inline to CppGenerator.h, ≤ 600 line limit) - No new vcpkg dependencies - The 3-line `getChildren("classes")` fix must be applied consistently across all generators — no one-off solutions - Existing function-level output must be unchanged in all generators (regression tests in Step 1858 enforce this) - Type inference for C++ must be conservative: unknown → `auto` + comment, never silently wrong - Java/JavaScript heuristic class reconstruction must be fully removed, not left alongside the new path --- ## Note on Scope This sprint does NOT require writing new `visitClassDeclaration` implementations for Python, Rust, Go, Java, JavaScript, TypeScript, or Elisp. Those already exist and are correct. The entire fix for those 7 languages is the `getChildren("classes")` loop in `visitModule`. Only C++ requires new implementation work.