refactor(mir): Phase 93 リファクタリング - 箱化モジュール化
## 概要 Phase 93 P0実装後のコード整理。スケジュール決定ロジックとbreak semanticsを 明確化し、デバッグログを統一。 ## 変更内容 ### 1. スケジュール決定ロジックの関数化 (step_schedule.rs) - `ScheduleDecision`構造体追加(判定結果+理由+デバッグコンテキスト) - `decide_pattern2_schedule()` - スケジュール決定のSSOT - `build_pattern2_schedule_from_decision()` - 新しい決定ベースAPI - 判定理由が4種類で明確化(ConditionOnly → body-local → loop-local → default) - 後方互換性維持(`Pattern2ScheduleContext`はwrapperに) ### 2. ConditionOnlyRecipe強化 (condition_only_emitter.rs) - `BreakSemantics` enum追加(WhenMatch vs WhenNotMatch) - `generate_break_condition()` - semanticsに基づくAST生成 - `from_trim_helper_condition_only()` - factory method追加 - break semanticsがrecipeに明示的に含まれる ### 3. trim_loop_lowering.rs簡素化 - `generate_condition_only_break_condition()`削除(DRY原則) - `recipe.generate_break_condition()`で統一 - break条件生成ロジックが1箇所に集約 ### 4. デバッグログ統一 - `[phase93/schedule]` - スケジュール決定 - `[phase93/condition-only]` - ConditionOnlyレシピ作成 - `[phase93/break-cond]` - break条件生成 - 既存の`joinir_dev_enabled()`使用(新規env var不要) ## テスト結果 - step_schedule: 10 tests PASS - condition_only_emitter: 4 tests PASS - 後方互換性維持 ## 統計 - 3ファイル変更 - +249行 / -57行 = +192 net 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -369,29 +369,35 @@ impl TrimLoopLowerer {
|
||||
);
|
||||
|
||||
// Step 7: Generate break condition based on pattern type
|
||||
// Phase 93 P0: ConditionOnly uses non-negated condition (break when is_ch_match is TRUE)
|
||||
// Normal Trim uses negated condition (break when !is_ch_match, i.e., ch is NOT whitespace)
|
||||
let trim_break_condition = if condition_only_recipe.is_some() {
|
||||
// ConditionOnly: "break when match" semantics
|
||||
// Generate: is_ch_match (TRUE when we should break)
|
||||
Self::generate_condition_only_break_condition(trim_helper)
|
||||
// Phase 93 Refactoring: Use recipe.generate_break_condition() for unified logic
|
||||
let trim_break_condition = if let Some(ref recipe) = condition_only_recipe {
|
||||
// Use recipe's break semantics (WhenMatch or WhenNotMatch)
|
||||
trace.emit_if(
|
||||
"trim",
|
||||
"break-cond",
|
||||
&format!(
|
||||
"Generated break condition from recipe: {} (semantics: {:?})",
|
||||
trim_helper.carrier_name,
|
||||
recipe.break_semantics
|
||||
),
|
||||
verbose,
|
||||
);
|
||||
recipe.generate_break_condition()
|
||||
} else {
|
||||
// Normal Trim: "break when NOT match" semantics
|
||||
// Generate: !is_ch_match (TRUE when we should break)
|
||||
trace.emit_if(
|
||||
"trim",
|
||||
"break-cond",
|
||||
&format!(
|
||||
"Generated normal trim break condition: !{}",
|
||||
trim_helper.carrier_name
|
||||
),
|
||||
verbose,
|
||||
);
|
||||
Self::generate_trim_break_condition(trim_helper)
|
||||
};
|
||||
|
||||
trace.emit_if(
|
||||
"trim",
|
||||
"cond",
|
||||
&format!(
|
||||
"Break condition: {} (ConditionOnly={})",
|
||||
trim_helper.carrier_name,
|
||||
condition_only_recipe.is_some()
|
||||
),
|
||||
verbose,
|
||||
);
|
||||
|
||||
// Step 8: Return result with all updates
|
||||
Ok(Some(TrimLoweringResult {
|
||||
condition: trim_break_condition,
|
||||
@ -533,27 +539,11 @@ impl TrimLoopLowerer {
|
||||
TrimPatternLowerer::generate_trim_break_condition(trim_helper)
|
||||
}
|
||||
|
||||
/// Generate ConditionOnly break condition
|
||||
///
|
||||
/// Phase 93 P0: For ConditionOnly patterns where break happens WHEN the condition is TRUE.
|
||||
///
|
||||
/// Returns: is_carrier (non-negated carrier check)
|
||||
/// Used for "break when match" semantics (e.g., find-first pattern)
|
||||
fn generate_condition_only_break_condition(
|
||||
trim_helper: &crate::mir::loop_pattern_detection::trim_loop_helper::TrimLoopHelper,
|
||||
) -> ASTNode {
|
||||
use crate::ast::Span;
|
||||
// Return just the carrier variable (non-negated)
|
||||
// When is_ch_match is TRUE, we should break
|
||||
ASTNode::Variable {
|
||||
name: trim_helper.carrier_name.clone(),
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Setup ConditionEnv bindings for Trim carrier
|
||||
///
|
||||
/// Phase 180-3: Extracted from Pattern2 (lines 345-377)
|
||||
/// Phase 93 Refactoring: Use explicit factory methods for recipe creation
|
||||
///
|
||||
/// Creates bindings for:
|
||||
/// 1. Carrier variable (e.g., "is_ch_match")
|
||||
@ -569,15 +559,16 @@ impl TrimLoopLowerer {
|
||||
let verbose = crate::config::env::joinir_dev_enabled() || trace.is_joinir_enabled();
|
||||
|
||||
// Phase 93 P0: Do NOT add is_ch_match to ConditionBinding
|
||||
// Instead, create a ConditionOnlyRecipe for recalculation every iteration
|
||||
let recipe = ConditionOnlyRecipe::from_trim_helper(trim_helper);
|
||||
// Phase 93 Refactoring: Use explicit factory method for ConditionOnly pattern
|
||||
let recipe = ConditionOnlyRecipe::from_trim_helper_condition_only(trim_helper);
|
||||
|
||||
trace.emit_if(
|
||||
"trim",
|
||||
"condition-only",
|
||||
&format!(
|
||||
"Phase 93 P0: Created ConditionOnlyRecipe for '{}' (will be recalculated each iteration, not carried via ConditionBinding)",
|
||||
trim_helper.carrier_name
|
||||
"[phase93/condition-only] Created ConditionOnlyRecipe for '{}' (semantics: {:?}, will be recalculated each iteration)",
|
||||
trim_helper.carrier_name,
|
||||
recipe.break_semantics
|
||||
),
|
||||
verbose,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user