refactor(joinir): Extract legacy binding path to routing_legacy_binding.rs

Phase 179-A Step 2: Separate LoopFrontendBinding JSON construction logic
into dedicated module for better organization.

Changes:
- New file: routing_legacy_binding.rs (223 lines)
- routing.rs: cf_loop_joinir_impl() simplified to 15 lines (delegates to legacy path)
- Routing now clearly separates pattern-based vs. legacy binding paths

Benefits:
- Clear separation of concerns (pattern router vs. legacy whitelist)
- routing.rs reduced from 364 to 146 lines (60% reduction)
- Legacy path isolated for future deprecation
This commit is contained in:
nyash-codex
2025-12-08 18:36:13 +09:00
parent 7a01ffe522
commit 95f3aa429e
25 changed files with 626 additions and 755 deletions

View File

@ -102,6 +102,7 @@ impl CommonPatternInitializer {
carriers.push(CarrierVar {
name: var_name.clone(),
host_id: var_id,
join_id: None, // Phase 177-STRUCT-1
});
}
}

View File

@ -205,6 +205,7 @@ mod tests {
vec![CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
}],
);
@ -243,10 +244,12 @@ mod tests {
CarrierVar {
name: "printed".to_string(),
host_id: ValueId(11),
join_id: None,
},
CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
},
],
);
@ -288,6 +291,7 @@ mod tests {
vec![CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
}],
);
@ -315,6 +319,7 @@ mod tests {
vec![CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
}],
);
@ -342,6 +347,7 @@ mod tests {
vec![CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
}],
);
@ -372,6 +378,7 @@ mod tests {
vec![CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
}],
);

View File

@ -10,12 +10,58 @@ use super::trim_pattern_lowerer::TrimPatternLowerer;
/// Phase 194: Detection function for Pattern 2
///
/// Phase 192: Updated to structure-based detection
/// Phase 178: Added string carrier rejection (unsupported by Pattern 2)
/// Phase 187-2: No legacy fallback - rejection means error
///
/// Pattern 2 matches:
/// - Pattern kind is Pattern2Break (has break, no continue)
/// - No string/complex carrier updates (JoinIR doesn't support string concat)
pub fn can_lower(_builder: &MirBuilder, ctx: &super::router::LoopPatternContext) -> bool {
use crate::mir::loop_pattern_detection::LoopPatternKind;
ctx.pattern_kind == LoopPatternKind::Pattern2Break
use crate::mir::join_ir::lowering::loop_update_analyzer::{LoopUpdateAnalyzer, UpdateExpr, UpdateRhs};
use crate::mir::join_ir::lowering::carrier_info::CarrierVar;
use crate::mir::ValueId;
// Basic pattern check
if ctx.pattern_kind != LoopPatternKind::Pattern2Break {
return false;
}
// Phase 178: Check for string/complex carrier updates
// Create dummy carriers from body assignment targets for analysis
let dummy_carriers: Vec<CarrierVar> = ctx.body.iter().filter_map(|node| {
match node {
crate::ast::ASTNode::Assignment { target, .. } => {
if let crate::ast::ASTNode::Variable { name, .. } = target.as_ref() {
Some(CarrierVar {
name: name.clone(),
host_id: ValueId(0), // Dummy
join_id: None,
})
} else {
None
}
}
_ => None,
}
}).collect();
let updates = LoopUpdateAnalyzer::analyze_carrier_updates(ctx.body, &dummy_carriers);
// Check if any update is string/complex
for update in updates.values() {
if let UpdateExpr::BinOp { rhs, .. } = update {
match rhs {
UpdateRhs::StringLiteral(_) | UpdateRhs::Other => {
eprintln!("[pattern2/can_lower] Phase 178: String/complex update detected, rejecting Pattern 2 (unsupported)");
return false;
}
_ => {}
}
}
}
true
}
/// Phase 194: Lowering function for Pattern 2

View File

@ -271,14 +271,17 @@ mod tests {
CarrierVar {
name: "i".to_string(),
host_id: ValueId(1),
join_id: None,
},
CarrierVar {
name: "sum".to_string(),
host_id: ValueId(2),
join_id: None,
},
CarrierVar {
name: "M".to_string(),
host_id: ValueId(3),
join_id: None,
},
],
trim_helper: None,

View File

@ -39,6 +39,8 @@ use super::super::trace;
/// Phase 194+: Detection function for Pattern 4
///
/// Phase 192: Updated to use pattern_kind for consistency
/// Phase 178: Added string carrier rejection (unsupported by Pattern 4)
/// Phase 187-2: No legacy fallback - rejection means error
///
/// Pattern 4 matches loops with continue statements.
///
@ -54,12 +56,55 @@ use super::super::trace;
///
/// 1. **Must have continue**: `ctx.has_continue == true`
/// 2. **No break statements**: `ctx.has_break == false` (for simplicity in Pattern 4)
/// 3. **Phase 178**: No string/complex carrier updates (JoinIR doesn't support string concat)
///
/// If both conditions are met, Pattern 4 is detected.
/// If all conditions are met, Pattern 4 is detected.
pub fn can_lower(_builder: &MirBuilder, ctx: &super::router::LoopPatternContext) -> bool {
// Phase 192: Use pattern_kind for consistency with other patterns
use crate::mir::loop_pattern_detection::LoopPatternKind;
ctx.pattern_kind == LoopPatternKind::Pattern4Continue
use crate::mir::join_ir::lowering::loop_update_analyzer::{LoopUpdateAnalyzer, UpdateExpr, UpdateRhs};
use crate::mir::join_ir::lowering::carrier_info::CarrierVar;
use crate::mir::ValueId;
// Basic pattern check
if ctx.pattern_kind != LoopPatternKind::Pattern4Continue {
return false;
}
// Phase 178: Check for string/complex carrier updates
// Create dummy carriers from body assignment targets for analysis
let dummy_carriers: Vec<CarrierVar> = ctx.body.iter().filter_map(|node| {
match node {
crate::ast::ASTNode::Assignment { target, .. } => {
if let crate::ast::ASTNode::Variable { name, .. } = target.as_ref() {
Some(CarrierVar {
name: name.clone(),
host_id: ValueId(0), // Dummy
join_id: None,
})
} else {
None
}
}
_ => None,
}
}).collect();
let updates = LoopUpdateAnalyzer::analyze_carrier_updates(ctx.body, &dummy_carriers);
// Check if any update is string/complex
for update in updates.values() {
if let UpdateExpr::BinOp { rhs, .. } = update {
match rhs {
UpdateRhs::StringLiteral(_) | UpdateRhs::Other => {
eprintln!("[pattern4/can_lower] Phase 178: String/complex update detected, rejecting Pattern 4 (unsupported)");
return false;
}
_ => {}
}
}
}
true
}
/// Phase 33-19: Lowering function for Pattern 4

View File

@ -184,9 +184,10 @@ pub fn route_loop_pattern(
}
}
// No pattern matched - fall through to legacy path
// No pattern matched - return None (caller will handle error)
// Phase 187-2: Legacy LoopBuilder removed, all loops must use JoinIR
if ctx.debug {
trace::trace().debug("route", &format!("No pattern matched for function '{}', falling back to legacy", ctx.func_name));
trace::trace().debug("route", &format!("No pattern matched for function '{}'", ctx.func_name));
}
Ok(None)
}