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:
@ -14,8 +14,16 @@ use std::collections::HashMap;
|
||||
pub struct CarrierVar {
|
||||
/// Variable name (e.g., "sum", "printed")
|
||||
pub name: String,
|
||||
/// Host ValueId for this variable
|
||||
/// Host ValueId for this variable (MIR側)
|
||||
pub host_id: ValueId,
|
||||
/// Phase 177-STRUCT: JoinIR側でこのキャリアを表すValueId
|
||||
///
|
||||
/// ヘッダPHIのdstや、exitで使う値を記録する。
|
||||
/// これにより、index ベースのマッチングを名前ベースに置き換えられる。
|
||||
///
|
||||
/// - `Some(vid)`: Header PHI生成後にセットされる
|
||||
/// - `None`: まだPHI生成前、または該当なし
|
||||
pub join_id: Option<ValueId>,
|
||||
}
|
||||
|
||||
/// Complete carrier information for a loop
|
||||
@ -77,6 +85,7 @@ impl CarrierInfo {
|
||||
.map(|(name, &id)| CarrierVar {
|
||||
name: name.clone(),
|
||||
host_id: id,
|
||||
join_id: None, // Phase 177-STRUCT-1: Set by header PHI generation
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -133,6 +142,7 @@ impl CarrierInfo {
|
||||
carriers.push(CarrierVar {
|
||||
name,
|
||||
host_id,
|
||||
join_id: None, // Phase 177-STRUCT-1: Set by header PHI generation
|
||||
});
|
||||
}
|
||||
|
||||
@ -432,6 +442,7 @@ mod tests {
|
||||
CarrierVar {
|
||||
name: name.to_string(),
|
||||
host_id: ValueId(id),
|
||||
join_id: None, // Phase 177-STRUCT-1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,10 +38,20 @@ pub enum UpdateExpr {
|
||||
}
|
||||
|
||||
/// Right-hand side of update expression
|
||||
///
|
||||
/// Phase 178: Extended to detect string updates for multi-carrier loops.
|
||||
/// The goal is "carrier detection", not full semantic understanding.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UpdateRhs {
|
||||
/// Numeric constant: count + 1
|
||||
Const(i64),
|
||||
/// Variable reference: sum + i
|
||||
Variable(String),
|
||||
/// Phase 178: String literal: result + "x"
|
||||
StringLiteral(String),
|
||||
/// Phase 178: Other expression (method call, complex expr)
|
||||
/// Used to detect "carrier has an update" without understanding semantics
|
||||
Other,
|
||||
}
|
||||
|
||||
pub struct LoopUpdateAnalyzer;
|
||||
@ -157,6 +167,9 @@ impl LoopUpdateAnalyzer {
|
||||
}
|
||||
|
||||
/// Analyze right-hand side of update expression
|
||||
///
|
||||
/// Phase 178: Extended to detect string updates.
|
||||
/// Goal: "carrier has update" detection, not semantic understanding.
|
||||
fn analyze_rhs(node: &ASTNode) -> Option<UpdateRhs> {
|
||||
match node {
|
||||
// Constant: count + 1
|
||||
@ -165,11 +178,24 @@ impl LoopUpdateAnalyzer {
|
||||
..
|
||||
} => Some(UpdateRhs::Const(*n)),
|
||||
|
||||
// Variable: sum + i
|
||||
// Phase 178: String literal: result + "x"
|
||||
ASTNode::Literal {
|
||||
value: LiteralValue::String(s),
|
||||
..
|
||||
} => Some(UpdateRhs::StringLiteral(s.clone())),
|
||||
|
||||
// Variable: sum + i (also handles: result + ch)
|
||||
ASTNode::Variable { name, .. } => {
|
||||
Some(UpdateRhs::Variable(name.clone()))
|
||||
}
|
||||
|
||||
// Phase 178: Method call or other complex expression
|
||||
// e.g., result + s.substring(pos, end)
|
||||
ASTNode::Call { .. }
|
||||
| ASTNode::MethodCall { .. }
|
||||
| ASTNode::BinaryOp { .. }
|
||||
| ASTNode::UnaryOp { .. } => Some(UpdateRhs::Other),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -218,6 +244,7 @@ mod tests {
|
||||
let carriers = vec![CarrierVar {
|
||||
name: "count".to_string(),
|
||||
host_id: crate::mir::ValueId(0),
|
||||
join_id: None, // Phase 177-STRUCT-1
|
||||
}];
|
||||
|
||||
let updates = LoopUpdateAnalyzer::analyze_carrier_updates(&body, &carriers);
|
||||
|
||||
@ -180,6 +180,16 @@ fn emit_carrier_update(
|
||||
)
|
||||
})?
|
||||
}
|
||||
// Phase 178: String updates detected but not lowered to JoinIR yet
|
||||
// The Rust MIR path handles string concatenation
|
||||
// For JoinIR: just pass through the carrier param (no JoinIR update)
|
||||
UpdateRhs::StringLiteral(_) | UpdateRhs::Other => {
|
||||
eprintln!(
|
||||
"[joinir/pattern2] Phase 178: Carrier '{}' has string/complex update - skipping JoinIR emit, using param passthrough",
|
||||
carrier.name
|
||||
);
|
||||
return Ok(carrier_param); // Pass-through: no JoinIR update
|
||||
}
|
||||
};
|
||||
|
||||
// Allocate result ValueId
|
||||
@ -737,6 +747,7 @@ mod tests {
|
||||
CarrierVar {
|
||||
name: name.to_string(),
|
||||
host_id: ValueId(host_id),
|
||||
join_id: None, // Phase 177-STRUCT-1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -387,6 +387,24 @@ pub fn lower_loop_with_continue_minimal(
|
||||
const_1
|
||||
}
|
||||
}
|
||||
// Phase 178: String updates detected but not lowered to JoinIR yet
|
||||
// Skip JoinIR update - use Select passthrough to keep carrier_merged defined
|
||||
UpdateRhs::StringLiteral(_) | UpdateRhs::Other => {
|
||||
eprintln!(
|
||||
"[loop_with_continue_minimal] Phase 178: Carrier '{}' has string/complex update - skipping BinOp, using Select passthrough",
|
||||
carrier_name
|
||||
);
|
||||
// Emit Select with same values: carrier_merged = Select(_, carrier_param, carrier_param)
|
||||
// This is effectively a passthrough (no JoinIR update)
|
||||
loop_step_func.body.push(JoinInst::Select {
|
||||
dst: carrier_merged,
|
||||
cond: continue_cond, // Condition doesn't matter when both values are same
|
||||
then_val: carrier_param,
|
||||
else_val: carrier_param,
|
||||
type_hint: None,
|
||||
});
|
||||
continue; // Skip the BinOp and normal Select below
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateExpr::Const(n) => {
|
||||
|
||||
Reference in New Issue
Block a user