feat(joinir): Phase 286 P2.6 - Pattern3 Plan 基盤 + Pattern1 退行修正
## Pattern1 退行修正(構造的 Fail-Fast) - Router に pattern_kind ガード追加(ctx.pattern_kind != Pattern1SimpleWhile → skip) - has_if_else_statement() ヘルパー追加(再帰版、ScopeBox/Loop 内もチェック) - Pattern1 extractor に if-else 拒否追加 ## Pattern3 Plan 基盤 - DomainPlan: Pattern3IfPhiPlan 構造体追加 - Extractor: extract_pattern3_plan() 追加 - Normalizer: normalize_pattern3_if_phi() スタブ追加(レガシー JoinIR へフォールバック) - Router: PLAN_EXTRACTORS に Pattern3 追加 ## テスト結果 - quick 154 PASS - Phase 118 smoke PASS(出力 12、退行解消) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -190,6 +190,7 @@ enum PlanExtractorVariant {
|
||||
/// Order is important: more specific patterns first
|
||||
/// - Pattern6/7: Need fn_body for capture analysis
|
||||
/// - Pattern8: Bool predicate scan (early-exit return, more specific)
|
||||
/// - Pattern3: If-phi merge (carrier with conditional update, more specific than Pattern4)
|
||||
/// - Pattern4: Continue loop (more specific than Pattern1)
|
||||
/// - Pattern9: Accum const loop (2 carriers, more specific than Pattern1)
|
||||
/// - Pattern1: Simple while (fallback)
|
||||
@ -206,6 +207,10 @@ static PLAN_EXTRACTORS: &[PlanExtractorEntry] = &[
|
||||
name: "Pattern8_BoolPredicateScan (Phase 286 P2.4)",
|
||||
extractor: PlanExtractorVariant::Simple(super::extractors::pattern8::extract_pattern8_plan),
|
||||
},
|
||||
PlanExtractorEntry {
|
||||
name: "Pattern3_IfPhi (Phase 286 P2.6)",
|
||||
extractor: PlanExtractorVariant::Simple(super::extractors::pattern3::extract_pattern3_plan),
|
||||
},
|
||||
PlanExtractorEntry {
|
||||
name: "Pattern4_Continue (Phase 286 P2)",
|
||||
extractor: PlanExtractorVariant::Simple(super::extractors::pattern4::extract_pattern4_plan),
|
||||
@ -232,6 +237,16 @@ fn try_plan_extractors(
|
||||
use super::super::trace;
|
||||
|
||||
for entry in PLAN_EXTRACTORS {
|
||||
// Phase 286 P2.6: Pattern1 Plan guard (structural Fail-Fast)
|
||||
// Pattern1 should only match Pattern1SimpleWhile pattern_kind
|
||||
// This prevents Pattern1 from incorrectly matching Pattern3 fixtures
|
||||
if entry.name.contains("Pattern1") {
|
||||
use crate::mir::loop_pattern_detection::LoopPatternKind;
|
||||
if ctx.pattern_kind != LoopPatternKind::Pattern1SimpleWhile {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Try extraction based on variant
|
||||
let plan_opt = match &entry.extractor {
|
||||
PlanExtractorVariant::Simple(extractor) => {
|
||||
@ -266,6 +281,23 @@ fn try_plan_extractors(
|
||||
let log_msg = format!("route=plan strategy=extract pattern={}", entry.name);
|
||||
trace::trace().pattern("route", &log_msg, true);
|
||||
|
||||
// Phase 286 P2.6: Pattern3 PoC exception - allow fallback to legacy
|
||||
// Pattern3 extractor validates structure, but normalizer is stub
|
||||
if entry.name.contains("Pattern3") {
|
||||
match lower_via_plan(builder, domain_plan, ctx) {
|
||||
Ok(value_id) => return Ok(value_id),
|
||||
Err(_) => {
|
||||
if ctx.debug {
|
||||
trace::trace().debug(
|
||||
"route/plan",
|
||||
"Pattern3 Plan normalization stub - fallback to legacy Pattern3",
|
||||
);
|
||||
}
|
||||
continue; // Try next extractor (will eventually reach legacy Pattern3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 286 P2.4.1: Fail-Fast - extract 成功 → normalize/lower 失敗は即 Err
|
||||
// 構造的 Fail-Fast: 文字列判定なし、extract が Some なら fallback 禁止
|
||||
return lower_via_plan(builder, domain_plan, ctx);
|
||||
|
||||
Reference in New Issue
Block a user