refactor(joinir): extract get_entry_function helper

Phase 256.8.5: Eliminate duplication of entry function extraction logic
across Pattern2/4/6/7.

Changes:
- Add patterns/common/joinir_helpers.rs with get_entry_function() helper
- Refactor 4 files to use shared helper (eliminate ~40 lines of duplication)
- Consistent error messages across all patterns

Benefits:
- DRY principle: Single source of truth for entry function extraction
- Maintainability: Future changes only need to happen once
- Consistency: All patterns use identical logic and error messages
- Testability: Can be tested independently

Files refactored:
- pattern2_steps/emit_joinir_step_box.rs
- pattern4_with_continue.rs
- pattern6_scan_with_init.rs
- pattern7_split_scan.rs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-20 20:10:48 +09:00
parent edc7355937
commit 636b1406bc
6 changed files with 52 additions and 33 deletions

View File

@ -0,0 +1,41 @@
//! Phase 256.8.5: Common JoinIR helpers for pattern lowering
use crate::mir::join_ir::{JoinFunction, JoinModule};
/// Phase 256.8.5: Extract entry function from JoinModule (SSOT)
///
/// Priority: join_module.entry → fallback to "main"
///
/// # Arguments
///
/// * `join_module` - The JoinModule to extract entry function from
/// * `pattern_name` - Pattern name for error messages (e.g., "pattern2", "pattern6")
///
/// # Returns
///
/// Reference to the entry JoinFunction
///
/// # Errors
///
/// Returns error if entry function not found
///
/// # Example
///
/// ```ignore
/// use super::common::get_entry_function;
///
/// let main_func = get_entry_function(&join_module, "pattern4")?;
/// let join_input_slots = main_func.params.clone();
/// ```
pub(crate) fn get_entry_function<'a>(
join_module: &'a JoinModule,
pattern_name: &str,
) -> Result<&'a JoinFunction, String> {
if let Some(entry_id) = join_module.entry {
join_module.functions.get(&entry_id)
.ok_or_else(|| format!("[{}] Entry function {:?} not found", pattern_name, entry_id))
} else {
join_module.get_function_by_name("main")
.ok_or_else(|| format!("[{}] JoinModule has no 'main' function", pattern_name))
}
}

View File

@ -4,5 +4,7 @@
//! lowering implementations, eliminating code duplication and ensuring consistency.
mod ast_helpers;
mod joinir_helpers; // Phase 256.8.5: JoinModule helpers
pub(crate) use ast_helpers::var;
pub(crate) use joinir_helpers::get_entry_function; // Phase 256.8.5

View File

@ -68,15 +68,9 @@ impl EmitJoinIRStepBox {
use crate::mir::builder::control_flow::joinir::merge::exit_line::ExitMetaCollector;
let exit_bindings = ExitMetaCollector::collect(builder, exit_meta, Some(&inputs.carrier_info), debug);
// Phase 256.8: Use JoinModule.main.params as SSOT (no hardcoded ValueIds)
// Get entry function (priority: join_module.entry → fallback to "main")
let main_func = if let Some(entry_id) = join_module.entry {
join_module.functions.get(&entry_id)
.ok_or_else(|| format!("[emit_joinir] Entry function {:?} not found", entry_id))?
} else {
join_module.get_function_by_name("main")
.ok_or_else(|| "[emit_joinir] JoinModule has no 'main' function".to_string())?
};
// Phase 256.8.5: Use JoinModule.entry.params as SSOT (no hardcoded ValueIds)
use super::super::common::get_entry_function;
let main_func = get_entry_function(&join_module, "emit_joinir")?;
// SSOT: Use actual params allocated by JoinIR lowerer
let join_input_slots = main_func.params.clone();

View File

@ -440,14 +440,8 @@ fn lower_pattern4_joinir(
}
// Phase 256.8.5: Use JoinModule.entry.params as SSOT (no hardcoded ValueIds)
// Get entry function (priority: join_module.entry → fallback to "main")
let main_func = if let Some(entry_id) = join_module.entry {
join_module.functions.get(&entry_id)
.ok_or_else(|| format!("[pattern4] Entry function {:?} not found", entry_id))?
} else {
join_module.get_function_by_name("main")
.ok_or_else(|| "[pattern4] JoinModule has no 'main' function".to_string())?
};
use super::common::get_entry_function;
let main_func = get_entry_function(&join_module, "pattern4")?;
// SSOT: Use actual params allocated by JoinIR lowerer
let join_inputs = main_func.params.clone();

View File

@ -445,14 +445,8 @@ impl MirBuilder {
}
// Phase 256.8.5: Use JoinModule.entry.params as SSOT (no hardcoded ValueIds)
// Get entry function (priority: join_module.entry → fallback to "main")
let main_func = if let Some(entry_id) = join_module.entry {
join_module.functions.get(&entry_id)
.ok_or_else(|| format!("[pattern6] Entry function {:?} not found", entry_id))?
} else {
join_module.get_function_by_name("main")
.ok_or_else(|| "[pattern6] JoinModule has no 'main' function".to_string())?
};
use super::common::get_entry_function;
let main_func = get_entry_function(&join_module, "pattern6")?;
// SSOT: Use actual params allocated by JoinIR lowerer
let join_inputs = main_func.params.clone();

View File

@ -493,14 +493,8 @@ impl MirBuilder {
}
// Phase 256.8.5: Use JoinModule.entry.params as SSOT (no hardcoded ValueIds)
// Get entry function (priority: join_module.entry → fallback to "main")
let main_func = if let Some(entry_id) = join_module.entry {
join_module.functions.get(&entry_id)
.ok_or_else(|| format!("[pattern7] Entry function {:?} not found", entry_id))?
} else {
join_module.get_function_by_name("main")
.ok_or_else(|| "[pattern7] JoinModule has no 'main' function".to_string())?
};
use super::common::get_entry_function;
let main_func = get_entry_function(&join_module, "pattern7")?;
// SSOT: Use actual params allocated by JoinIR lowerer
let join_inputs = main_func.params.clone();