Files
hakorune/docs/development/current/main/phases/phase-134/normalization-p0.md

262 lines
7.9 KiB
Markdown
Raw Normal View History

refactor(control_flow): Phase 134 P0 - Normalization entry point SSOT Consolidate dual entry points into unified NormalizationPlan system: Problem: - Dual entry points: try_normalized_shadow() + suffix_router_box - ~220 lines of duplicated pattern detection logic - Maintenance burden: changes required in two places Solution: - New normalization module with Box-First architecture - NormalizationPlanBox: Single source of truth for pattern detection - NormalizationExecuteBox: Single source of truth for execution Implementation: - src/mir/builder/control_flow/normalization/ (new module) - README.md: Design contract (SSOT) - plan.rs: NormalizationPlan data structure - plan_box.rs: Pattern detection (7 unit tests) - execute_box.rs: Execution logic - mod.rs: Module integration Refactored files: - routing.rs::try_normalized_shadow(): 165 → 87 lines (-78 lines) - suffix_router_box::try_lower_loop_suffix(): 258 → 116 lines (-142 lines) Pattern support maintained: - Phase 131: loop(true) only (consumed: 1) - Phase 132: loop + single post (consumed: 3) - Phase 133: loop + multiple post (consumed: 2+N) Box-First principles: - Plan Box: Detection responsibility only - Execute Box: Execution responsibility only - README.md: Contract documentation (SSOT) - Clear separation enables independent testing Test results: - cargo test --lib: 1186 PASS (10 new tests added) - Phase 133 VM/LLVM EXE: PASS (exit code 6) - Phase 132 LLVM EXE: PASS (exit code 3) - Phase 131 LLVM EXE: PASS (exit code 1) Benefits: - Code duplication eliminated (~220 lines) - Single source of truth for normalization decisions - Improved maintainability and testability - Future-proof extensibility (easy to add new patterns) Default behavior unchanged: Dev-only guard maintained Related: Phase 134 normalization infrastructure improvement 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 22:29:29 +09:00
# Phase 134 P0: Normalization Entry Point Consolidation
**Date**: 2025-12-18
**Status**: ✅ Complete
**Scope**: Unified entry point for Normalized shadow detection and execution
---
## Background
**Problem (Before)**:
- **Dual entry points** with duplicated responsibility:
- `try_normalized_shadow()` in routing.rs (loop-only patterns)
- `suffix_router_box` in patterns/policies/ (loop + post statements)
- **Decision logic scattered**: "What to lower" was decided in two different places
- **Maintenance burden**: Changes to pattern detection required updates in multiple locations
---
## Solution (Phase 134 P0)
**Unified decision point** using Box-First architecture:
1. **NormalizationPlanBox**: SSOT for pattern detection ("what to normalize")
2. **NormalizationExecuteBox**: SSOT for execution ("how to execute")
3. **Both entry points** use the same PlanBox for consistent decisions
---
## Implementation
### New Module Structure
`src/mir/builder/control_flow/normalization/` (5 files created):
- **README.md**: Design documentation and contract (SSOT)
- **plan.rs**: NormalizationPlan data structure
- **plan_box.rs**: NormalizationPlanBox (pattern detection)
- **execute_box.rs**: NormalizationExecuteBox (execution logic)
- **mod.rs**: Module integration
### NormalizationPlan Structure
```rust
pub struct NormalizationPlan {
pub consumed: usize, // Statements to consume from remaining
pub kind: PlanKind, // What to lower
pub requires_return: bool, // Whether pattern includes return
}
pub enum PlanKind {
LoopOnly, // Phase 131: loop(true) alone
LoopWithPost { // Phase 132-133: loop + assigns + return
post_assign_count: usize,
},
}
```
### NormalizationPlanBox API
```rust
pub fn plan_block_suffix(
builder: &MirBuilder,
remaining: &[ASTNode],
func_name: &str,
debug: bool,
) -> Result<Option<NormalizationPlan>, String>
```
**Returns**:
- `Ok(Some(plan))`: Pattern detected, proceed with normalization
- `Ok(None)`: Not a normalized pattern, use legacy fallback
- `Err(_)`: Internal error
### NormalizationExecuteBox API
```rust
pub fn execute(
builder: &mut MirBuilder,
plan: &NormalizationPlan,
remaining: &[ASTNode],
func_name: &str,
debug: bool,
) -> Result<ValueId, String>
```
**Side Effects**:
- Modifies builder state (adds blocks, instructions)
- Updates variable_map with exit values (DirectValue mode)
- May emit return statement (for suffix patterns)
---
## Code Changes
### 1. normalized_shadow_suffix_router_box.rs
**Before** (258 lines):
- Pattern detection logic (50+ lines)
- Merge logic (50+ lines)
- StepTree building and lowering
**After** (116 lines, -142 lines):
- Delegates to NormalizationPlanBox for detection
- Delegates to NormalizationExecuteBox for execution
- Only handles suffix-specific logic (return emission)
### 2. routing.rs try_normalized_shadow()
**Before** (165 lines):
- StepTree building
- AvailableInputsCollector
- Boundary creation
- Merge logic
- Exit reconnection
**After** (87 lines, -78 lines):
- Delegates to NormalizationPlanBox for detection
- Delegates to NormalizationExecuteBox for execution
- Pattern kind validation (loop-only vs loop+post)
---
## Pattern Detection Logic
### Phase 131: Loop-Only
- **Pattern**: `loop(true) { ... break }`
- **Consumed**: 1 statement
- **Example**: `loop(true) { x = 1; break }; return x`
### Phase 132: Loop + Single Post
- **Pattern**: `loop(true) { ... break }; <assign>; return <expr>`
- **Consumed**: 3 statements
- **Example**: `loop(true) { x = 1; break }; x = x + 2; return x`
### Phase 133: Loop + Multiple Post
- **Pattern**: `loop(true) { ... break }; <assign>+; return <expr>`
- **Consumed**: 2 + N statements
- **Example**: `loop(true) { x = 1; break }; x = x + 2; x = x + 3; return x`
---
## Testing
### Unit Tests (7 tests)
Location: `src/mir/builder/control_flow/normalization/plan_box.rs`
✅ test_plan_block_suffix_phase131_loop_only
✅ test_plan_block_suffix_phase132_loop_post_single
✅ test_plan_block_suffix_phase133_loop_post_multi
✅ test_plan_block_suffix_return_boundary
✅ test_plan_block_suffix_no_match_empty
✅ test_plan_block_suffix_no_match_not_loop
✅ test_plan_block_suffix_no_match_no_return
### Lib Tests
```bash
cargo test --lib --package nyash-rust
```
Result: **1186 passed; 0 failed; 56 ignored**
### Regression Smokes
**Phase 133 VM**: `phase133_loop_true_break_once_post_multi_add_vm.sh` - PASS
**Phase 133 LLVM**: `phase133_loop_true_break_once_post_multi_add_llvm_exe.sh` - PASS (exit code 6)
**Phase 132 LLVM**: `phase132_loop_true_break_once_post_add_llvm_exe.sh` - PASS (exit code 3)
**Phase 131 LLVM**: `phase131_loop_true_break_once_llvm_exe.sh` - PASS (exit code 1)
**Phase 131 VM**: `phase131_loop_true_break_once_vm.sh` - PASS
---
## Benefits
### Code Quality
- **-220 lines** of duplicated code eliminated
- **Single responsibility**: Each Box has one clear purpose
- **Testability**: Plan detection can be tested independently
### Maintainability
- **SSOT**: Pattern detection in one place (NormalizationPlanBox)
- **Documentation**: Comprehensive README.md with contract
- **Clear separation**: Detection vs execution
### Future-Proofing
- **Extensible**: Easy to add new pattern kinds
- **Flexible**: ExecuteBox can be swapped for different implementations
- **Traceable**: Debug logging at each decision point
---
## Design Principles Applied
### Box-First
- **Plan Box**: Single responsibility for detection
- **Execute Box**: Single responsibility for execution
- Clear boundaries enable independent evolution
### SSOT (Single Source of Truth)
- **Entry**: NormalizationPlanBox is the only place for normalization decisions
- **Contract**: Documented in normalization/README.md
- **No duplication**: Both entry points use the same logic
### Fail-Fast
- Invalid patterns return `Err` (not silent fallback)
- STRICT mode treats contract violations as panics
- Clear error messages with hints
### Legacy Preservation
- Existing behavior unchanged (dev-only guard)
- Non-normalized patterns return `Ok(None)` → legacy fallback
- No breaking changes to existing smokes
---
## Files Modified
- `src/mir/builder/control_flow/normalization/` (NEW module, 5 files)
- `src/mir/builder/control_flow/mod.rs` (added normalization module)
- `src/mir/builder/control_flow/joinir/patterns/policies/normalized_shadow_suffix_router_box.rs` (refactored, -142 lines)
- `src/mir/builder/control_flow/joinir/routing.rs` (refactored, -78 lines)
**Net Change**: +~300 lines (new module), -220 lines (refactoring) = +80 lines overall
---
## Acceptance Criteria
-**Entry SSOT**: normalization/README.md documents the contract
-**By-name avoidance**: Uses boundary contract SSOT
-**cargo test --lib**: 1186/1186 PASS
-**Phase 133 smokes**: 2/2 PASS (VM + LLVM EXE)
-**Phase 131/132 regression**: PASS
-**Default behavior unchanged**: Dev-only guard maintained
---
## Next Steps
### P1: Additional Patterns (Future)
- **Phase 135+**: Support for more complex post-loop patterns
- **Conditional post**: `if (cond) { assign }; return`
- **Nested structures**: Multiple loops with post statements
### P2: Performance Optimization (Future)
- **Caching**: Pattern detection results
- **Lazy evaluation**: Only build StepTree when needed
- **Parallel detection**: Check multiple patterns simultaneously
### P3: Enhanced Debugging (Future)
- **Structured tracing**: JSON-formatted trace output
- **Visualization**: DOT graph of normalization decisions
- **Metrics**: Track pattern match rates
---
## References
- **Module**: `src/mir/builder/control_flow/normalization/`
- **Contract**: `src/mir/builder/control_flow/normalization/README.md`
- **Tests**: `src/mir/builder/control_flow/normalization/plan_box.rs::tests`
- **Phase 131**: loop(true) break-once Normalized
- **Phase 132**: loop(true) + post-loop minimal
- **Phase 133**: loop(true) + multiple post-loop assigns