feat(joinir): Phase 183 LoopBodyLocal role separation + test fixes

Phase 183 Implementation:
- Added is_var_used_in_condition() helper for AST variable detection
- Implemented LoopBodyLocal filtering in TrimLoopLowerer
- Created 4 test files for P1/P2 patterns
- Added 5 unit tests for variable detection

Test Fixes:
- Fixed test_is_outer_scope_variable_pinned (BasicBlockId import)
- Fixed test_pattern2_accepts_loop_param_only (literal node usage)

Refactoring:
- Unified pattern detection documentation
- Consolidated CarrierInfo initialization
- Documented LoopScopeShape construction paths

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-08 23:43:26 +09:00
parent a3df5ecc7a
commit 440f8646b1
66 changed files with 279 additions and 183 deletions

View File

@ -124,7 +124,7 @@ pub fn extract_all_variables(node: &ASTNode) -> HashSet<String> {
/// Future versions may include:
/// - Dominance tree analysis
/// - More sophisticated scope inference
pub fn is_outer_scope_variable(
pub(crate) fn is_outer_scope_variable(
var_name: &str,
scope: Option<&LoopScopeShape>,
) -> bool {

View File

@ -27,7 +27,7 @@ use crate::mir::loop_pattern_detection::loop_condition_scope::LoopConditionScope
/// 昇格リクエスト
pub struct PromotionRequest<'a> {
/// ループのスコープ情報
pub scope: &'a LoopScopeShape,
pub(crate) scope: &'a LoopScopeShape,
/// 条件変数のスコープ分類
pub cond_scope: &'a LoopConditionScope,
/// break 条件の ASTPattern 2 の場合)

View File

@ -131,7 +131,7 @@ impl LoopConditionScopeBox {
/// - If matches loop_param_name → LoopParam
/// - Else if in outer scope (via condition_var_analyzer) → OuterLocal
/// - Else → LoopBodyLocal (conservative default)
pub fn analyze(
pub(crate) fn analyze(
loop_param_name: &str,
condition_nodes: &[&ASTNode],
scope: Option<&LoopScopeShape>,

View File

@ -196,7 +196,7 @@ impl LoopFeatures {
///
/// # Returns
/// * `LoopFeatures` - Feature vector for pattern classification
pub fn extract_features(loop_form: &LoopForm, scope: Option<&LoopScopeShape>) -> LoopFeatures {
pub(crate) fn extract_features(loop_form: &LoopForm, scope: Option<&LoopScopeShape>) -> LoopFeatures {
// Phase 194: Basic feature extraction from LoopForm
let has_break = !loop_form.break_targets.is_empty();
let has_continue = !loop_form.continue_targets.is_empty();
@ -611,7 +611,7 @@ pub fn is_loop_with_continue_pattern(loop_form: &LoopForm) -> bool {
/// # TODO
/// Implement by analyzing header PHI nodes
#[allow(dead_code)]
fn count_carrier_variables(loop_form: &LoopForm) -> usize {
fn count_carrier_variables(_loop_form: &LoopForm) -> usize {
// TODO: Implement carrier variable counting
// Step 1: Access loop_form.header block
// Step 2: Count PHI instructions in header
@ -630,7 +630,7 @@ fn count_carrier_variables(loop_form: &LoopForm) -> usize {
/// # TODO
/// Implement by checking for LoopForm within body blocks
#[allow(dead_code)]
fn has_nested_loops(loop_form: &LoopForm) -> bool {
fn has_nested_loops(_loop_form: &LoopForm) -> bool {
// TODO: Implement nested loop detection
// Step 1: Traverse body blocks
// Step 2: Check for loop headers in body
@ -649,7 +649,7 @@ fn has_nested_loops(loop_form: &LoopForm) -> bool {
/// # TODO
/// Implement by checking header condition complexity
#[allow(dead_code)]
fn has_simple_condition(loop_form: &LoopForm) -> bool {
fn has_simple_condition(_loop_form: &LoopForm) -> bool {
// TODO: Implement condition complexity check
// Step 1: Access loop_form.header block
// Step 2: Find condition instruction
@ -660,7 +660,7 @@ fn has_simple_condition(loop_form: &LoopForm) -> bool {
#[cfg(test)]
mod tests {
use super::*;
// ========================================================================
// Pattern 1: Simple While Loop Tests