From fc4c343d882223906058c83e977d8a3ca41b3e58 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Tue, 16 Dec 2025 07:37:23 +0900 Subject: [PATCH] =?UTF-8?q?refactor(mir):=20Phase=20137-6-S1=20-=20choose?= =?UTF-8?q?=5Fpattern=5Fkind=20SSOT=E5=85=A5=E5=8F=A3=E3=82=92=E6=96=B0?= =?UTF-8?q?=E8=A8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 目的 Pattern 選択ロジックを SSOT 化し、将来の Canonicalizer 委譲に備える ## 変更内容 ### 新規関数: `choose_pattern_kind()` - 場所: `src/mir/builder/control_flow/joinir/routing.rs` - 責務: Pattern 選択の SSOT 入口 - 実装: 既存の LoopFeatures ベース選択ロジックを集約 ### LoopPatternContext の更新 - `new()` で `choose_pattern_kind()` を使用 - 既存の分散した選択ロジックを SSOT に統一 ## 効果 - ✅ Pattern 選択ロジックの SSOT 化(1箇所に集約) - ✅ 将来の Canonicalizer 委譲に備えた構造確立 - ✅ 既定挙動完全不変(既存テスト全て PASS) ## テスト結果 - ✅ `cargo build --release`: 成功 - ✅ スモークテスト(simple_*): 5/5 PASS - ✅ 退行なし 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/grammar/generated.rs | 34 +++++++++++++++---- .../control_flow/joinir/loop_context.rs | 12 +++---- .../control_flow/joinir/patterns/router.rs | 6 ++-- .../builder/control_flow/joinir/routing.rs | 24 +++++++++++++ 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/grammar/generated.rs b/src/grammar/generated.rs index 25bb6e51..d94cb9c1 100644 --- a/src/grammar/generated.rs +++ b/src/grammar/generated.rs @@ -36,15 +36,37 @@ pub static OPERATORS_DIV_RULES: &[(&str, &str, &str, &str)] = &[ ]; pub fn lookup_keyword(word: &str) -> Option<&'static str> { for (k, t) in KEYWORDS { - if *k == word { - return Some(*t); - } + if *k == word { return Some(*t); } } None } pub static SYNTAX_ALLOWED_STATEMENTS: &[&str] = &[ - "box", "global", "function", "static", "if", "loop", "break", "return", "print", "nowait", - "include", "local", "outbox", "try", "throw", "using", "from", + "box", + "global", + "function", + "static", + "if", + "loop", + "break", + "return", + "print", + "nowait", + "include", + "local", + "outbox", + "try", + "throw", + "using", + "from", ]; -pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &["add", "sub", "mul", "div", "and", "or", "eq", "ne"]; +pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &[ + "add", + "sub", + "mul", + "div", + "and", + "or", + "eq", + "ne", +]; \ No newline at end of file diff --git a/src/mir/builder/control_flow/joinir/loop_context.rs b/src/mir/builder/control_flow/joinir/loop_context.rs index 459bd205..023f4071 100644 --- a/src/mir/builder/control_flow/joinir/loop_context.rs +++ b/src/mir/builder/control_flow/joinir/loop_context.rs @@ -88,11 +88,7 @@ impl<'a> LoopProcessingContext<'a> { /// /// This should be called after running the canonicalizer. /// After this call, `verify_parity()` can be used to check consistency. - pub fn set_canonicalizer_result( - &mut self, - skeleton: LoopSkeleton, - decision: RoutingDecision, - ) { + pub fn set_canonicalizer_result(&mut self, skeleton: LoopSkeleton, decision: RoutingDecision) { self.skeleton = Some(skeleton); self.decision = Some(decision); } @@ -304,8 +300,10 @@ mod tests { let mut ctx = make_simple_context(&condition, &body); // Set canonicalizer result with fail-fast decision - let decision = - RoutingDecision::fail_fast(vec![CapabilityTag::ConstStep], "Test fail-fast".to_string()); + let decision = RoutingDecision::fail_fast( + vec![CapabilityTag::ConstStep], + "Test fail-fast".to_string(), + ); ctx.set_canonicalizer_result( LoopSkeleton { steps: vec![], diff --git a/src/mir/builder/control_flow/joinir/patterns/router.rs b/src/mir/builder/control_flow/joinir/patterns/router.rs index 3e9188c3..bb51b8d8 100644 --- a/src/mir/builder/control_flow/joinir/patterns/router.rs +++ b/src/mir/builder/control_flow/joinir/patterns/router.rs @@ -70,6 +70,7 @@ impl<'a> LoopPatternContext<'a> { /// Phase 192: Extract features and classify pattern from AST /// Phase 193: Feature extraction delegated to ast_feature_extractor module /// Phase 131-11: Detects infinite loop condition + /// Phase 137-6-S1: Use choose_pattern_kind() SSOT entry point pub(crate) fn new( condition: &'a ASTNode, body: &'a [ASTNode], @@ -84,8 +85,9 @@ impl<'a> LoopPatternContext<'a> { // Phase 131-11: Pass condition for infinite loop detection let features = ast_features::extract_features(condition, body, has_continue, has_break); - // Phase 192: Classify pattern based on features - let pattern_kind = crate::mir::loop_pattern_detection::classify(&features); + // Phase 137-6-S1: Use SSOT pattern selection entry point + use crate::mir::builder::control_flow::joinir::routing::choose_pattern_kind; + let pattern_kind = choose_pattern_kind(condition, body); Self { condition, diff --git a/src/mir/builder/control_flow/joinir/routing.rs b/src/mir/builder/control_flow/joinir/routing.rs index 2ea0274b..49168882 100644 --- a/src/mir/builder/control_flow/joinir/routing.rs +++ b/src/mir/builder/control_flow/joinir/routing.rs @@ -5,6 +5,30 @@ use crate::ast::ASTNode; use crate::mir::builder::MirBuilder; use crate::mir::ValueId; +/// Pattern 選択の SSOT 入口 +/// +/// 既存の分散した選択ロジックをここに集約する。 +/// 将来的には Canonicalizer decision に委譲する。 +/// +/// Phase 137-6-S1: 現時点では既存の router ロジック(LoopFeatures ベース)を使用 +pub(in crate::mir::builder) fn choose_pattern_kind( + condition: &ASTNode, + body: &[ASTNode], +) -> crate::mir::loop_pattern_detection::LoopPatternKind { + use crate::mir::builder::control_flow::joinir::patterns::ast_feature_extractor as ast_features; + use crate::mir::loop_pattern_detection; + + // Phase 193: Use AST Feature Extractor Box for break/continue detection + let has_continue = ast_features::detect_continue_in_body(body); + let has_break = ast_features::detect_break_in_body(body); + + // Phase 193: Extract features using modularized extractor + let features = ast_features::extract_features(condition, body, has_continue, has_break); + + // Phase 192: Classify pattern based on features + loop_pattern_detection::classify(&features) +} + impl MirBuilder { /// Phase 49: Try JoinIR Frontend for mainline integration ///