Files
hakorune/docs/development/refactoring/modularization-directory-structure.md
nyash-codex 1730fea206 docs: Add comprehensive modularization implementation plan
Create 5-document modularization strategy for 3 large source files:
- control_flow.rs (1,632 lines → 19 modules)
- generic_case_a.rs (1,056 lines → 7 modules)
- loopform_builder.rs (1,166 lines → 11 modules)

Documents included:

1. **README.md** (352 lines)
   Navigation hub with overview, metrics, timeline, ROI analysis

2. **modularization-implementation-plan.md** (960 lines)
   Complete 20-hour implementation guide with:
   - Phase-by-phase breakdown (13 phases across 3 files)
   - Hour-by-hour effort estimates
   - Risk assessment matrices
   - Success criteria (quantitative & qualitative)
   - Public API changes (zero breaking changes)

3. **modularization-quick-start.md** (253 lines)
   Actionable checklist with:
   - Copy-paste verification commands
   - Emergency rollback procedures
   - Timeline and milestones

4. **modularization-directory-structure.md** (426 lines)
   Visual guide with:
   - Before/after directory trees
   - File size metrics
   - Import path examples
   - Code quality comparison

5. **phase4-merge-function-breakdown.md** (789 lines)
   Detailed implementation for most complex phase:
   - 714-line merge_joinir_mir_blocks() → 6 focused modules
   - 10 detailed implementation steps
   - Common pitfalls and solutions

Key metrics:
- Total effort: 20 hours (2-3 weeks)
- Files: 9 → 37 focused modules
- Largest file: 1,632 → 180 lines (-89%)
- Backward compatible: Zero breaking changes
- ROI: Breakeven in 4 months (5 hrs/month saved)

Priority: control_flow.rs Phase 1-4 (high impact)
Safety: Fully reversible at each phase

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 20:13:31 +09:00

15 KiB

Modularization Directory Structure Diagrams

Visual reference for the proposed directory structures after modularization.


1. control_flow.rs Modularization

Before (Current State)

src/mir/builder/
├── control_flow.rs                    (1,632 lines) ⚠️ MONOLITH
├── if_form.rs
├── loops.rs
└── ... (other files)

After (Proposed Structure)

src/mir/builder/
├── control_flow/
│   ├── mod.rs                         (~150 lines) ✅ Entry points
│   │   ├── pub(super) fn cf_block()
│   │   ├── pub(super) fn cf_if()
│   │   ├── pub(super) fn cf_loop()
│   │   ├── pub(super) fn cf_try_catch()
│   │   └── pub(super) fn cf_throw()
│   │
│   ├── debug.rs                       (~50 lines) ✅ Debug utilities
│   │   └── fn trace_varmap()
│   │
│   ├── utils.rs                       (~50 lines) ✅ Utility functions
│   │   └── fn extract_loop_variable_from_condition()
│   │
│   ├── joinir/
│   │   ├── mod.rs                     (~100 lines) ✅ JoinIR coordinator
│   │   │
│   │   ├── routing.rs                 (~150 lines) ✅ Routing logic
│   │   │   ├── fn try_cf_loop_joinir()
│   │   │   └── fn cf_loop_joinir_impl()
│   │   │
│   │   ├── merge/
│   │   │   ├── mod.rs                 (~100 lines) ✅ Merge coordinator
│   │   │   │   └── pub fn merge_joinir_mir_blocks()
│   │   │   │
│   │   │   ├── id_remapper.rs         (~150 lines) ✅ ID remapping
│   │   │   │   ├── struct JoinIrIdRemapper
│   │   │   │   ├── fn create_remapper()
│   │   │   │   └── fn remap_ids()
│   │   │   │
│   │   │   ├── block_allocator.rs     (~100 lines) ✅ Block allocation
│   │   │   │   └── fn allocate_blocks()
│   │   │   │
│   │   │   ├── value_collector.rs     (~100 lines) ✅ Value collection
│   │   │   │   └── fn collect_values()
│   │   │   │
│   │   │   ├── instruction_rewriter.rs (~150 lines) ✅ Instruction rewriting
│   │   │   │   ├── fn rewrite_instructions()
│   │   │   │   └── fn convert_call_to_jump()
│   │   │   │
│   │   │   └── exit_phi_builder.rs    (~100 lines) ✅ Exit PHI construction
│   │   │       └── fn build_exit_phi()
│   │   │
│   │   └── patterns/
│   │       ├── mod.rs                 (~50 lines) ✅ Pattern dispatcher
│   │       │   └── pub fn dispatch_pattern()
│   │       │
│   │       ├── pattern1_minimal.rs    (~150 lines) ✅ Pattern 1 lowering
│   │       │   └── pub fn cf_loop_pattern1_minimal()
│   │       │
│   │       ├── pattern2_with_break.rs (~130 lines) ✅ Pattern 2 lowering
│   │       │   └── pub fn cf_loop_pattern2_with_break()
│   │       │
│   │       └── pattern3_with_if_phi.rs (~180 lines) ✅ Pattern 3 lowering
│   │           └── pub fn cf_loop_pattern3_with_if_phi()
│   │
│   └── exception/
│       ├── mod.rs                     (~50 lines) ✅ Exception API
│       │
│       ├── try_catch.rs               (~150 lines) ✅ try/catch impl
│       │   └── pub fn cf_try_catch()
│       │
│       └── throw.rs                   (~30 lines) ✅ throw impl
│           └── pub fn cf_throw()
│
├── if_form.rs
├── loops.rs
└── ... (other files - unchanged)

Metrics Comparison

Metric Before After Change
Total lines 1,632 ~1,850 +13% (for clarity)
Number of files 1 19 +1800%
Largest file 1,632 ~180 -89%
Average file size 1,632 ~97 -94%
Functions per file 13 1-2 Much clearer

Benefits

  • 714-line merge function → 6 focused modules (100-150 lines each)
  • Pattern lowerers isolated → Easy to add Pattern 4/5/6
  • Debug traces easier to locate → NYASH_OPTION_C_DEBUG output clearer
  • Merge conflicts reduced → Changes isolated to specific files
  • Code navigation improved → Jump to definition works better

2. generic_case_a.rs Modularization

Before (Current State)

src/mir/join_ir/lowering/
├── generic_case_a.rs                      (1,056 lines) ⚠️ LARGE
├── generic_case_a_entry_builder.rs        (4,828 bytes)
├── generic_case_a_whitespace_check.rs     (4,552 bytes)
└── ... (other files)

After (Proposed Structure)

src/mir/join_ir/lowering/
├── generic_case_a/
│   ├── mod.rs                             (~100 lines) ✅ Public API
│   │   ├── pub use skip_ws::lower_case_a_skip_ws_with_scope
│   │   ├── pub use trim::lower_case_a_trim_with_scope
│   │   ├── pub use append_defs::lower_case_a_append_defs_with_scope
│   │   └── pub use stage1_using_resolver::...
│   │
│   ├── skip_ws.rs                         (~220 lines) ✅ skip_ws lowerer
│   │   ├── pub fn lower_case_a_skip_ws_with_scope()
│   │   └── fn lower_case_a_skip_ws_core()
│   │
│   ├── trim.rs                            (~500 lines) ✅ trim lowerer
│   │   ├── pub fn lower_case_a_trim_with_scope()
│   │   └── fn lower_case_a_trim_core()
│   │
│   ├── append_defs.rs                     (~170 lines) ✅ append_defs lowerer
│   │   ├── pub fn lower_case_a_append_defs_with_scope()
│   │   └── fn lower_case_a_append_defs_core()
│   │
│   ├── stage1_using_resolver.rs          (~180 lines) ✅ stage1 lowerer
│   │   ├── pub fn lower_case_a_stage1_usingresolver_with_scope()
│   │   └── fn lower_case_a_stage1_usingresolver_core()
│   │
│   ├── entry_builder.rs                   (~150 lines) ✅ (moved from parent)
│   │   └── struct EntryFunctionBuilder
│   │
│   └── whitespace_check.rs                (~150 lines) ✅ (moved from parent)
│       └── fn check_whitespace()
│
└── ... (other files - unchanged)

Metrics Comparison

Metric Before After Change
Total lines 1,056 ~1,470 +39% (for clarity)
Number of files 3 (scattered) 7 (organized) +133%
Largest file 1,056 ~500 -53%
Average file size 352 ~210 -40%
Functions per file 4 1-2 Much clearer

Benefits

  • Each lowerer in its own file → Easy to maintain
  • Companion files integrated → All Case A logic in one directory
  • trim.rs still large (500 lines) → Could be further split if needed
  • Clear public API → mod.rs shows what's exported

3. loopform_builder.rs Modularization

Before (Current State - After Phase 191)

src/mir/phi_core/
├── loopform_builder.rs                    (1,166 lines) ⚠️ LARGE
├── loopform_context.rs                    (✅ already modularized)
├── loopform_variable_models.rs            (✅ already modularized)
├── loopform_utils.rs                      (✅ already modularized)
├── loopform_exit_phi.rs                   (✅ already modularized)
└── ... (other files)

After (Proposed Structure)

src/mir/phi_core/
├── loopform/
│   ├── mod.rs                             (~100 lines) ✅ Public API
│   │   ├── pub use context::LoopFormContext
│   │   ├── pub use variable_models::{CarrierVariable, PinnedVariable}
│   │   ├── pub use exit_phi::build_exit_phis_for_control
│   │   └── pub use builder_core::LoopFormBuilder
│   │
│   ├── context.rs                         (~150 lines) ✅ (existing)
│   │   └── pub struct LoopFormContext
│   │
│   ├── variable_models.rs                 (~150 lines) ✅ (existing)
│   │   ├── pub struct CarrierVariable
│   │   ├── pub struct PinnedVariable
│   │   └── pub struct LoopBypassFlags
│   │
│   ├── utils.rs                           (~100 lines) ✅ (existing)
│   │   ├── pub fn is_loopform_debug_enabled()
│   │   └── pub fn get_loop_bypass_flags()
│   │
│   ├── exit_phi.rs                        (~150 lines) ✅ (existing)
│   │   └── pub fn build_exit_phis_for_control()
│   │
│   ├── passes/
│   │   ├── mod.rs                         (~50 lines) ✅ 4-pass coordinator
│   │   │   └── pub fn run_4_pass_architecture()
│   │   │
│   │   ├── pass1_discovery.rs             (~150 lines) ✅ Variable discovery
│   │   │   └── pub fn discover_variables()
│   │   │
│   │   ├── pass2_header_phi.rs            (~150 lines) ✅ Header PHI
│   │   │   └── pub fn build_header_phi()
│   │   │
│   │   ├── pass3_latch.rs                 (~100 lines) ✅ Latch processing
│   │   │   └── pub fn process_latch()
│   │   │
│   │   └── pass4_exit_phi.rs              (~150 lines) ✅ Exit PHI
│   │       └── pub fn build_exit_phi()
│   │
│   └── builder_core.rs                    (~200 lines) ✅ Core builder
│       └── pub struct LoopFormBuilder
│
└── ... (other files - unchanged)

Metrics Comparison

Metric Before After Change
Total lines 1,166 (main file) ~1,450 +24% (for clarity)
Number of files 5 (partially modularized) 11 (fully modularized) +120%
Largest file 1,166 ~200 -83%
Average file size 233 ~132 -43%

Benefits

  • Completes Phase 191 modularization → Finishes what was started
  • 4-pass architecture explicit → Each pass in its own file
  • Already partially modularized → Lower risk than control_flow.rs
  • Clear separation of concerns → Context, models, passes, builder

File Size Distribution Comparison

control_flow.rs

Before:
█████████████████████████████████████████████████████████████████ 1,632 lines

After:
merge/instruction_rewriter.rs: ███████ 150 lines
pattern1_minimal.rs:           ███████ 150 lines
routing.rs:                    ███████ 150 lines
pattern3_with_if_phi.rs:       ████████ 180 lines
try_catch.rs:                  ███████ 150 lines
... (14 more files < 150 lines each)

generic_case_a.rs

Before:
███████████████████████████████████████████████████ 1,056 lines

After:
trim.rs:                       ████████████████████████ 500 lines
skip_ws.rs:                    ██████████ 220 lines
stage1_using_resolver.rs:      ████████ 180 lines
append_defs.rs:                ████████ 170 lines
... (3 more files < 150 lines each)

loopform_builder.rs

Before:
████████████████████████████████████████████████████████ 1,166 lines

After:
builder_core.rs:               █████████ 200 lines
context.rs:                    ███████ 150 lines
variable_models.rs:            ███████ 150 lines
exit_phi.rs:                   ███████ 150 lines
pass1_discovery.rs:            ███████ 150 lines
... (6 more files < 150 lines each)

Import Path Changes

control_flow.rs

Before

use crate::mir::builder::MirBuilder;

impl MirBuilder {
    pub(super) fn cf_loop(...) -> Result<ValueId, String> {
        // 1,632 lines of code
    }
}

After

// src/mir/builder/control_flow/mod.rs
use crate::mir::builder::MirBuilder;

impl MirBuilder {
    pub(super) fn cf_loop(...) -> Result<ValueId, String> {
        // Delegates to routing module
        joinir::routing::try_cf_loop_joinir(self, ...)
    }
}

// src/mir/builder/control_flow/joinir/routing.rs
pub(in crate::mir::builder::control_flow) fn try_cf_loop_joinir(
    builder: &mut MirBuilder,
    ...
) -> Result<Option<ValueId>, String> {
    // 150 lines of focused code
}

generic_case_a.rs

Before

// src/mir/join_ir/lowering/generic_case_a.rs
pub(crate) fn lower_case_a_skip_ws_with_scope(...) -> Option<JoinModule> {
    // 200+ lines
}

After

// src/mir/join_ir/lowering/generic_case_a/mod.rs
pub(crate) use skip_ws::lower_case_a_skip_ws_with_scope;

// src/mir/join_ir/lowering/generic_case_a/skip_ws.rs
pub(crate) fn lower_case_a_skip_ws_with_scope(...) -> Option<JoinModule> {
    // 220 lines
}

loopform_builder.rs

Before

// src/mir/phi_core/loopform_builder.rs
pub use loopform_context::LoopFormContext;

pub fn build_exit_phis_for_control<O: LoopFormOps>(...) {
    // 1,166 lines
}

After

// src/mir/phi_core/loopform/mod.rs
pub use context::LoopFormContext;
pub use exit_phi::build_exit_phis_for_control;

// src/mir/phi_core/loopform/exit_phi.rs
pub fn build_exit_phis_for_control<O: LoopFormOps>(...) {
    // 150 lines
}

Navigation Improvements

Before (Monolith Files)

Developer: "Where is the merge function?"
Answer: "control_flow.rs, line 864-1578 (search through 1,632 lines)"

Developer: "Where is Pattern 3 lowering?"
Answer: "control_flow.rs, line 696-863 (search through 1,632 lines)"

Developer: "What does merge_joinir_mir_blocks do?"
Answer: "Read 714 lines to understand"

After (Modularized)

Developer: "Where is the merge function?"
Answer: "control_flow/joinir/merge/mod.rs (100 lines coordinator)"

Developer: "Where is Pattern 3 lowering?"
Answer: "control_flow/joinir/patterns/pattern3_with_if_phi.rs (180 lines)"

Developer: "What does merge_joinir_mir_blocks do?"
Answer: "Read merge/mod.rs (100 lines) → delegates to 6 sub-modules"

Conclusion

The modularization dramatically improves code organization:

  • control_flow.rs: 1,632 lines → 19 files (avg 97 lines)
  • generic_case_a.rs: 1,056 lines → 7 files (avg 210 lines)
  • loopform_builder.rs: 1,166 lines → 11 files (avg 132 lines)

Total Impact: 3,854 lines → 37 focused modules

Developer Experience:

  • Easier navigation (jump to definition works better)
  • Clearer separation of concerns
  • Less merge conflicts
  • Easier to add new patterns/lowerers
  • Better code review experience (smaller diffs)

Last Updated: 2025-12-05