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>
This commit is contained in:
87
src/mir/builder/control_flow/normalization/plan.rs
Normal file
87
src/mir/builder/control_flow/normalization/plan.rs
Normal file
@ -0,0 +1,87 @@
|
||||
//! Normalization plan data structures (Phase 134 P0)
|
||||
//!
|
||||
//! Defines what to normalize and how many statements to consume.
|
||||
|
||||
/// Plan for normalizing a block suffix
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct NormalizationPlan {
|
||||
/// Number of statements to consume from remaining block
|
||||
pub consumed: usize,
|
||||
|
||||
/// What kind of normalization to perform
|
||||
pub kind: PlanKind,
|
||||
|
||||
/// Whether the pattern includes an explicit return (for unreachable detection)
|
||||
pub requires_return: bool,
|
||||
}
|
||||
|
||||
/// Kind of normalization pattern detected
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PlanKind {
|
||||
/// Phase 131: loop(true) { ... break } alone
|
||||
///
|
||||
/// Pattern: Single loop statement
|
||||
/// Example: `loop(true) { x = 1; break }`
|
||||
LoopOnly,
|
||||
|
||||
/// Phase 132-133: loop(true) + post assignments + return
|
||||
///
|
||||
/// Pattern: loop + N assignments + return
|
||||
/// Example: `loop(true) { x = 1; break }; x = x + 2; return x`
|
||||
LoopWithPost {
|
||||
/// Number of post-loop assignment statements
|
||||
post_assign_count: usize,
|
||||
},
|
||||
}
|
||||
|
||||
impl NormalizationPlan {
|
||||
/// Create a Phase 131 plan (loop-only)
|
||||
pub fn loop_only() -> Self {
|
||||
Self {
|
||||
consumed: 1,
|
||||
kind: PlanKind::LoopOnly,
|
||||
requires_return: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a Phase 132-133 plan (loop + post assignments + return)
|
||||
pub fn loop_with_post(post_assign_count: usize) -> Self {
|
||||
// consumed = 1 (loop) + N (assigns) + 1 (return)
|
||||
let consumed = 1 + post_assign_count + 1;
|
||||
|
||||
Self {
|
||||
consumed,
|
||||
kind: PlanKind::LoopWithPost { post_assign_count },
|
||||
requires_return: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_loop_only_plan() {
|
||||
let plan = NormalizationPlan::loop_only();
|
||||
assert_eq!(plan.consumed, 1);
|
||||
assert_eq!(plan.kind, PlanKind::LoopOnly);
|
||||
assert!(!plan.requires_return);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_loop_with_post_single() {
|
||||
let plan = NormalizationPlan::loop_with_post(1);
|
||||
assert_eq!(plan.consumed, 3); // loop + 1 assign + return
|
||||
assert_eq!(plan.kind, PlanKind::LoopWithPost { post_assign_count: 1 });
|
||||
assert!(plan.requires_return);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_loop_with_post_multiple() {
|
||||
let plan = NormalizationPlan::loop_with_post(2);
|
||||
assert_eq!(plan.consumed, 4); // loop + 2 assigns + return
|
||||
assert_eq!(plan.kind, PlanKind::LoopWithPost { post_assign_count: 2 });
|
||||
assert!(plan.requires_return);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user