refactor(joinir): Phase 92 P1 - 箱化モジュール化・レガシー削除
P1-1: ConditionalStep lowering を1箱に隔離 - 新規作成: src/mir/join_ir/lowering/common/conditional_step_emitter.rs - emit_conditional_step_update() を carrier_update_emitter.rs から移動 - Fail-Fast 不変条件チェック追加(then_delta != else_delta) - 副作用を減らしたクリーンなインターフェース - 包括的なテストスイート(3テスト) P1-0: 境界SSOTの固定 - routing.rs: skeleton 設定をrouting層から削除 - pattern2_with_break.rs: skeleton 取得をlower()内部に閉じ込め - parity_checker から skeleton を直接取得 - skeleton の使用を Pattern2 のみに限定 P1-2: escape recognizer をSSOTに戻す - escape_pattern_recognizer.rs: 未使用フィールド削除 - quote_char, escape_char 削除(使われていない) - 責務を cond/delta 抽出のみに限定 - pattern_recognizer.rs: デフォルト値を使用 P1-3: E2Eテスト作成(実行は後回し) - apps/tests/test_pattern5b_escape_minimal.hako 作成 - body-local 変数対応後に検証予定 テスト結果: - conditional_step_emitter tests: 3 passed - Pattern2 tests: 18 passed - Regression: 0 failures 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -12,17 +12,20 @@
|
||||
use crate::ast::{ASTNode, BinaryOperator, LiteralValue};
|
||||
|
||||
/// Information about a detected escape skip pattern
|
||||
///
|
||||
/// Phase 92 P1-2: Responsibility limited to cond/delta extraction only.
|
||||
/// Body-local variable handling (`ch`) should be done by canonicalizer/caller.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EscapeSkipPatternInfo {
|
||||
pub counter_name: String,
|
||||
pub normal_delta: i64,
|
||||
pub escape_delta: i64,
|
||||
pub quote_char: char,
|
||||
pub escape_char: char,
|
||||
pub body_stmts: Vec<ASTNode>,
|
||||
/// Phase 92 P0-3: The condition expression for conditional increment
|
||||
/// e.g., `ch == '\\'` for escape sequence handling
|
||||
pub escape_cond: Box<ASTNode>,
|
||||
/// Body statements before break check (for reference)
|
||||
/// Note: Caller should handle body-local variable extraction (e.g., `ch`)
|
||||
pub body_stmts: Vec<ASTNode>,
|
||||
}
|
||||
|
||||
/// Detect escape sequence handling pattern in loop body
|
||||
@ -71,10 +74,8 @@ pub fn detect_escape_skip_pattern(body: &[ASTNode]) -> Option<EscapeSkipPatternI
|
||||
counter_name,
|
||||
normal_delta,
|
||||
escape_delta,
|
||||
quote_char: '"', // Default for JSON/CSV (Phase 91 MVP)
|
||||
escape_char: '\\', // Default for JSON/CSV (Phase 91 MVP)
|
||||
body_stmts,
|
||||
escape_cond, // Phase 92 P0-3: Condition for JoinIR Select
|
||||
body_stmts,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -717,18 +717,34 @@ pub(crate) fn can_lower(builder: &MirBuilder, ctx: &super::router::LoopPatternCo
|
||||
///
|
||||
/// Wrapper around cf_loop_pattern2_with_break to match router signature
|
||||
/// Phase 200-C: Pass fn_body to cf_loop_pattern2_with_break
|
||||
/// Phase 92 P0-3: Pass skeleton for ConditionalStep support
|
||||
/// Phase 92 P1-0: Retrieve skeleton internally for ConditionalStep support
|
||||
pub(crate) fn lower(
|
||||
builder: &mut MirBuilder,
|
||||
ctx: &super::router::LoopPatternContext,
|
||||
) -> Result<Option<ValueId>, String> {
|
||||
// Phase 92 P1-0: Retrieve skeleton from parity checker if dev mode enabled
|
||||
// verify_router_parity is a method on MirBuilder, accessible directly
|
||||
let skeleton = if crate::config::env::joinir_dev_enabled() {
|
||||
let (_parity_result, skeleton_opt) = builder.verify_router_parity(
|
||||
ctx.condition,
|
||||
ctx.body,
|
||||
ctx.func_name,
|
||||
ctx,
|
||||
);
|
||||
// Note: parity check errors are already logged by verify_router_parity
|
||||
// We only need the skeleton for ConditionalStep support
|
||||
skeleton_opt
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
builder.cf_loop_pattern2_with_break_impl(
|
||||
ctx.condition,
|
||||
ctx.body,
|
||||
ctx.func_name,
|
||||
ctx.debug,
|
||||
ctx.fn_body,
|
||||
ctx.skeleton, // Phase 92 P0-3: Pass skeleton for ConditionalStep
|
||||
skeleton.as_ref(), // Phase 92 P1-0: Pass skeleton reference
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -304,19 +304,10 @@ impl MirBuilder {
|
||||
};
|
||||
|
||||
// Phase 137-4: Router parity verification (after ctx is created)
|
||||
// Phase 92 P0-2: Get skeleton from canonicalizer for Option A
|
||||
let skeleton_holder: Option<crate::mir::loop_canonicalizer::LoopSkeleton>;
|
||||
// Phase 92 P1-0: Skeleton setting removed - patterns retrieve skeleton internally if needed
|
||||
if crate::config::env::joinir_dev_enabled() {
|
||||
let (result, skeleton_opt) = self.verify_router_parity(condition, body, func_name, &ctx);
|
||||
let (result, _skeleton_opt) = self.verify_router_parity(condition, body, func_name, &ctx);
|
||||
result?;
|
||||
skeleton_holder = skeleton_opt;
|
||||
if skeleton_holder.is_some() {
|
||||
// Phase 92 P0-2: Set skeleton reference in context (must use holder lifetime)
|
||||
// Note: This is safe because skeleton_holder lives for the entire scope
|
||||
ctx.skeleton = skeleton_holder.as_ref();
|
||||
}
|
||||
} else {
|
||||
skeleton_holder = None;
|
||||
}
|
||||
|
||||
if let Some(result) = route_loop_pattern(self, &ctx)? {
|
||||
|
||||
Reference in New Issue
Block a user