feat(joinir): Phase 197 Pattern4 multi-carrier exit fix & AST-based update
Phase 197-B: Multi-Carrier Exit Mechanism - Fixed reconnect_boundary() to use remapper for per-carrier exit values - ExitMeta now uses carrier_param_ids (Jump arguments) instead of carrier_exit_ids (k_exit parameters) - Root cause: k_exit parameters aren't defined when JoinIR functions merge into host MIR Phase 197-C: AST-Based Update Expression - LoopUpdateAnalyzer extracts update patterns from loop body AST - Pattern4 lowerer uses UpdateExpr for semantically correct RHS - sum = sum + i → uses i_next (current iteration value) - count = count + 1 → uses const_1 Files modified: - src/mir/builder/control_flow/joinir/merge/mod.rs - src/mir/join_ir/lowering/loop_with_continue_minimal.rs - src/mir/join_ir/lowering/loop_update_analyzer.rs (new) Test results: - loop_continue_multi_carrier.hako: 25, 5 ✅ - loop_continue_pattern4.hako: 25 ✅ Pattern 1–4 now unified with: - Structure-based detection (LoopFeatures + classify) - Carrier/Exit metadata (CarrierInfo + ExitMeta) - Boundary connection (JoinInlineBoundary + LoopExitBinding) - AST-based update expressions (LoopUpdateAnalyzer) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -99,6 +99,7 @@ impl MirBuilder {
|
||||
debug: bool,
|
||||
) -> Result<Option<ValueId>, String> {
|
||||
use crate::mir::join_ir::lowering::carrier_info::{CarrierInfo, CarrierVar};
|
||||
use crate::mir::join_ir::lowering::loop_update_analyzer::LoopUpdateAnalyzer;
|
||||
use crate::mir::join_ir::lowering::loop_with_continue_minimal::lower_loop_with_continue_minimal;
|
||||
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
||||
use crate::mir::BasicBlockId;
|
||||
@ -143,6 +144,14 @@ impl MirBuilder {
|
||||
carrier_info.carriers.iter().map(|c| &c.name).collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// Phase 197: Analyze carrier update expressions from loop body
|
||||
let carrier_updates = LoopUpdateAnalyzer::analyze_carrier_updates(_body, &carrier_info.carriers);
|
||||
|
||||
eprintln!("[pattern4] Analyzed {} carrier update expressions", carrier_updates.len());
|
||||
for (carrier_name, update_expr) in &carrier_updates {
|
||||
eprintln!("[pattern4] {} → {:?}", carrier_name, update_expr);
|
||||
}
|
||||
|
||||
// Phase 195: Use unified trace
|
||||
trace::trace().varmap("pattern4_start", &self.variable_map);
|
||||
|
||||
@ -162,8 +171,8 @@ impl MirBuilder {
|
||||
variable_definitions: BTreeMap::new(),
|
||||
};
|
||||
|
||||
// Call Pattern 4 lowerer
|
||||
let (join_module, exit_meta) = match lower_loop_with_continue_minimal(scope) {
|
||||
// Call Pattern 4 lowerer (Phase 197: pass carrier_updates for semantic correctness)
|
||||
let (join_module, exit_meta) = match lower_loop_with_continue_minimal(scope, &carrier_info, &carrier_updates) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
// Phase 195: Use unified trace
|
||||
@ -238,8 +247,17 @@ impl MirBuilder {
|
||||
|
||||
// Merge JoinIR blocks into current function
|
||||
// Phase 196: Use dynamically generated exit_bindings and host_inputs
|
||||
// Build join_inputs dynamically to match host_inputs length:
|
||||
// [ValueId(0), ValueId(1), ValueId(2), ...] for i + N carriers
|
||||
let mut join_inputs = vec![ValueId(0)]; // ValueId(0) = i_init in JoinIR
|
||||
for idx in 0..carrier_info.carriers.len() {
|
||||
join_inputs.push(ValueId((idx + 1) as u32)); // ValueId(1..N) = carrier inits
|
||||
}
|
||||
|
||||
eprintln!("[pattern4] join_inputs: {:?}", join_inputs.iter().map(|v| v.0).collect::<Vec<_>>());
|
||||
|
||||
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_with_exit_bindings(
|
||||
vec![ValueId(0), ValueId(1)], // JoinIR's main() parameters (i_init, sum_init)
|
||||
join_inputs, // JoinIR's main() parameters (dynamic)
|
||||
host_inputs, // Host's loop variables (dynamic)
|
||||
exit_bindings,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user