Problem
vera/codegen.py is now 2,140 lines — the largest single file in the compiler. The checker (checker.py, ~1,900 lines) and WASM context (wasm.py, ~2,300 lines) both received mixin decomposition during C8a (PRs for #99 and #100). codegen.py is the remaining monolith.
Current responsibilities
The file handles several distinct concerns:
- Compilation pass orchestration — the multi-pass
compile() pipeline
- Function registration — Pass 1 signature collection
- Monomorphization — generic function specialization
- ADT layout — heap layout computation for algebraic data types
- WAT assembly — string-level WASM text format emission
- Cross-module detection — guard rail for undefined function calls
- Module registration — Pass 0 import handling
Proposed decomposition
Following the same mixin pattern used for checker/ and wasm/:
| Module |
Responsibility |
codegen/context.py |
CodegenContext composed class, pass orchestration |
codegen/registration.py |
Function/ADT/type registration (Pass 0 + Pass 1) |
codegen/monomorphize.py |
Generic specialization |
codegen/layout.py |
ADT heap layout, constructor tables |
codegen/wat.py |
WAT text assembly helpers |
codegen/modules.py |
Cross-module compilation (Pass 2.5) |
Test file
tests/test_codegen.py (4,680 lines) should be split to match the new module structure. This is the largest test file in the project — over twice the size of test_checker.py (2,143 lines). The split should follow the same pattern: one test file per codegen submodule.
Design goal alignment
This supports Goal 3 (one canonical form) applied to the compiler itself — each module should have a single clear responsibility. It also supports maintainability as the codegen grows to handle more constructs (#131 nested patterns, #53 effect handlers, #51 GC).
Precedent
Both decompositions used the mixin pattern where a composed context class inherits from focused mixins, preserving the existing API while improving navigability.
Problem
vera/codegen.pyis now 2,140 lines — the largest single file in the compiler. The checker (checker.py, ~1,900 lines) and WASM context (wasm.py, ~2,300 lines) both received mixin decomposition during C8a (PRs for #99 and #100).codegen.pyis the remaining monolith.Current responsibilities
The file handles several distinct concerns:
compile()pipelineProposed decomposition
Following the same mixin pattern used for
checker/andwasm/:codegen/context.pyCodegenContextcomposed class, pass orchestrationcodegen/registration.pycodegen/monomorphize.pycodegen/layout.pycodegen/wat.pycodegen/modules.pyTest file
tests/test_codegen.py(4,680 lines) should be split to match the new module structure. This is the largest test file in the project — over twice the size oftest_checker.py(2,143 lines). The split should follow the same pattern: one test file per codegen submodule.Design goal alignment
This supports Goal 3 (one canonical form) applied to the compiler itself — each module should have a single clear responsibility. It also supports maintainability as the codegen grows to handle more constructs (#131 nested patterns, #53 effect handlers, #51 GC).
Precedent
checker.py->checker/(Decompose checker.py into checker/ submodules #99, v0.0.40): 5 submoduleswasm.py->wasm/(Decompose wasm.py into wasm/ submodules #100, v0.0.41): 7 submodulesBoth decompositions used the mixin pattern where a composed context class inherits from focused mixins, preserving the existing API while improving navigability.