Files
whetstone_DSL/sprint162_plan.md

184 lines
8.3 KiB
Markdown
Raw Normal View History

# 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:535562 | Good |
| Rust | Yes | RustGenerator.h:427444 | Good — struct + impl |
| Go | Yes | GoGenerator.h:412425 | Good — struct + receivers |
| Java | Yes | JavaGenerator.h:447483 | Good — handles abstract/extends |
| JavaScript | Yes | JavaScriptGenerator.h:454469 | Good — ES6 class syntax |
| TypeScript | Yes (inherited from JS) | — | Good |
| Elisp | Yes | ElispGenerator.h:497513 | 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:447483,
JavaScript:454469) 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 (`<string>` 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 <string>` 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 (18541858), 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 18541858 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.