diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md index 36a12b59..d05b1996 100644 --- a/docs/development/current/main/10-Now.md +++ b/docs/development/current/main/10-Now.md @@ -2,8 +2,8 @@ ## Current Focus -- Phase: `docs/development/current/main/phases/phase-29ao/README.md` (closeout) -- Next: Phase 29ap (planned; see `docs/development/current/main/phases/phase-29ao/README.md`) +- Phase: `docs/development/current/main/phases/phase-29ap/README.md` +- Next: Phase 29ap P1 (planned; see `docs/development/current/main/phases/phase-29ap/README.md`) ## Gate (SSOT) diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md index aae8d3ba..86e811f5 100644 --- a/docs/development/current/main/30-Backlog.md +++ b/docs/development/current/main/30-Backlog.md @@ -5,7 +5,7 @@ Scope: 「次にやる候補」を短く列挙するメモ。入口は `docs/dev ## Active -- Phase 29ap (planned): legacy削減の段階計画(extractor/router)+ composer SSOT +- Phase 29ap: `docs/development/current/main/phases/phase-29ap/README.md` (Next: P1 planned) - JoinIR regression gate SSOT: `docs/development/current/main/phases/phase-29ae/README.md` - CorePlan hardening (docs-first): `docs/development/current/main/phases/phase-29al/README.md` diff --git a/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md b/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md index 566bbdea..24462ad5 100644 --- a/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md +++ b/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md @@ -33,8 +33,8 @@ Related: ## 1.1 Current (active) -- Active phase: `docs/development/current/main/phases/phase-29ao/README.md` -- Next step: Phase 29ap (planned; P55 done) +- Active phase: `docs/development/current/main/phases/phase-29ap/README.md` +- Next step: Phase 29ap P1 (planned) ## 2. すでに固めた SSOT(再発防止の土台) diff --git a/docs/development/current/main/phases/phase-29ap/README.md b/docs/development/current/main/phases/phase-29ap/README.md new file mode 100644 index 00000000..2d5b2af1 --- /dev/null +++ b/docs/development/current/main/phases/phase-29ap/README.md @@ -0,0 +1,32 @@ +--- +Status: Active +Scope: Legacy extractor reduction (planner+composer SSOT) +Related: +- docs/development/current/main/design/coreplan-migration-roadmap-ssot.md +- docs/development/current/main/design/coreplan-migration-done-criteria-ssot.md +- docs/development/current/main/design/coreloop-composer-v0-v1-boundary-ssot.md +- docs/development/current/main/phases/phase-29ae/README.md +--- + +# Phase 29ap: Legacy extractor reduction (Step-E) + +Goal: Reduce legacy extractor fallbacks while keeping planner+composer as the SSOT path. + +Gate (SSOT): +- `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh` + +## P0: Reduce legacy extractors (Pattern1/3) ✅ + +- Scope: + - Remove Pattern1/3 extractor fallbacks in `single_planner`. + - Remove Pattern3 JoinIR router entry so plan line is the only path. + - Pattern1 JoinIR entry is retained for now (stdlib loops still rely on it). +- Guardrails: + - Outcome remains `Ok(None)` for non-matching cases. + - No new logs or error strings. + +## Next (planned) + +- P1: Pattern6/7 JoinIR wrapper → composer entry only +- P2: Router pattern-name branching reduction (planner outcome + composer SSOT) +- P3: Facts/Feature expansion if needed diff --git a/src/mir/builder/control_flow/joinir/patterns/router.rs b/src/mir/builder/control_flow/joinir/patterns/router.rs index cb55aabe..d0f5ca57 100644 --- a/src/mir/builder/control_flow/joinir/patterns/router.rs +++ b/src/mir/builder/control_flow/joinir/patterns/router.rs @@ -180,7 +180,7 @@ fn lower_via_plan( /// - Cons: Extraction can be expensive (but amortized over lowering) /// /// ## StructureBased (Feature Classification) -/// - Used by: Pattern1, Pattern2, Pattern3, Pattern4, Pattern5, Pattern8, Pattern9 +/// - Used by: Pattern1, Pattern2, Pattern4 (legacy) /// - Strategy: Check pattern_kind (from LoopPatternContext), plus optional structural checks /// - Pros: Fast classification, reuses centralized feature detection /// - Cons: Two sources of truth (classify + structural checks) @@ -201,7 +201,7 @@ pub(crate) enum CanLowerStrategy { ExtractionBased, /// Structure-based detection: Check pattern_kind from LoopPatternContext - /// Used by Pattern1, Pattern2, Pattern3, Pattern4, Pattern5, Pattern8, Pattern9 + /// Used by Pattern1, Pattern2, Pattern4 StructureBased, } @@ -222,26 +222,20 @@ pub(crate) struct LoopPatternEntry { /// /// **IMPORTANT**: Patterns are tried in array order (SSOT). /// Array order defines priority - earlier entries are tried first. -/// Pattern4 → Pattern8 → Pattern9 → Pattern3 → Pattern1 → Pattern2 +/// Pattern4 → Pattern8 → Pattern9 → Pattern1 → Pattern2 /// /// # Current Patterns (Structure-based detection, established Phase 131-11+) /// /// Pattern detection strategies (updated Phase 286): /// - Pattern6/7: ExtractionBased (Plan line, Phase 273+) -/// - Pattern5/8/9: ExtractionBased (extraction functions, Plan line Phase 286+) -/// - Pattern1-4: StructureBased (LoopFeatures classification, legacy) +/// - Pattern8/9: ExtractionBased (extraction functions, Plan line Phase 286+) +/// - Pattern1/2/4: StructureBased (LoopFeatures classification, legacy) /// /// - Pattern 4: Loop with Continue (loop_continue_pattern4.hako) /// - Detection: pattern_kind == Pattern4Continue /// - Structure: has_continue && !has_break /// -/// - Pattern 3: Loop with If-Else PHI (loop_if_phi.hako) -/// - Detection: pattern_kind == Pattern3IfPhi -/// - Structure: has_if_else_phi && !has_break && !has_continue -/// -/// - Pattern 1: Simple While Loop (loop_min_while.hako) -/// - Detection: pattern_kind == Pattern1SimpleWhile -/// - Structure: !has_break && !has_continue && !has_if_else_phi +/// - Pattern3: moved to plan-based routing (planner+composer SSOT) /// /// - Pattern 2: Loop with Conditional Break (joinir_min_loop.hako) /// - Detection: pattern_kind == Pattern2Break @@ -274,11 +268,6 @@ pub(crate) static LOOP_PATTERNS: &[LoopPatternEntry] = &[ detect: super::pattern9_accum_const_loop::can_lower, lower: super::pattern9_accum_const_loop::lower, }, - LoopPatternEntry { - name: "Pattern3_WithIfPhi", - detect: super::pattern3_with_if_phi::can_lower, - lower: super::pattern3_with_if_phi::lower, - }, LoopPatternEntry { name: "Pattern1_Minimal", detect: super::pattern1_minimal::can_lower, @@ -302,17 +291,17 @@ pub(crate) static LOOP_PATTERNS: &[LoopPatternEntry] = &[ /// This router uses multiple detection strategies: /// - Plan-based (Pattern6/7): extract_*_plan() → DomainPlan (Phase 273+ SSOT) /// - Extraction-based (Pattern8/9): extract_*() functions (already implemented) -/// - Structure-based (Pattern1-5): ctx.pattern_kind classification (legacy) +/// - Structure-based (Pattern1/2/4): ctx.pattern_kind classification (legacy) /// /// # Plan Line SSOT for Pattern6/7 (Phase 273+) /// /// This function implements the following routing strategy: /// 1. Try Plan-based Pattern6 (extract_scan_with_init_plan) → DomainPlan /// 2. Try Plan-based Pattern7 (extract_split_scan_plan) → DomainPlan -/// 3. Fall through to legacy Pattern1-5 table for other patterns +/// 3. Fall through to legacy Pattern1/2/4/8/9 table for other patterns /// /// The Plan line (Extractor → Normalizer → Verifier → Lowerer) is the -/// current operational SSOT for Pattern6/7. Legacy patterns (1-5) use +/// current operational SSOT for Pattern6/7. Legacy patterns (1/2/4/8/9) use /// the traditional LoopPatternContext-based routing. /// /// Plan-based architecture (Phase 273 P1-P3): @@ -324,7 +313,7 @@ pub(crate) static LOOP_PATTERNS: &[LoopPatternEntry] = &[ /// SSOT Entry Points: /// - Pattern6: src/mir/builder/control_flow/plan/normalizer.rs (ScanWithInit normalization) /// - Pattern7: src/mir/builder/control_flow/plan/normalizer.rs (SplitScan normalization) -/// - Pattern1-5: src/mir/builder/control_flow/joinir/patterns/pattern*.rs (direct lowering) +/// - Pattern1/2/4/8/9: src/mir/builder/control_flow/joinir/patterns/pattern*.rs (direct lowering) pub(crate) fn route_loop_pattern( builder: &mut MirBuilder, ctx: &LoopPatternContext, diff --git a/src/mir/builder/control_flow/plan/extractors/pattern1.rs b/src/mir/builder/control_flow/plan/extractors/pattern1.rs index b1851ae9..d84324d9 100644 --- a/src/mir/builder/control_flow/plan/extractors/pattern1.rs +++ b/src/mir/builder/control_flow/plan/extractors/pattern1.rs @@ -5,7 +5,6 @@ use crate::ast::{ASTNode, BinaryOperator}; // Phase 282 P9a: Use common_helpers use super::common_helpers::has_control_flow_statement as common_has_control_flow; -use crate::mir::builder::control_flow::plan::policies::pattern1_subset_policy::is_pattern1_step_only_body; #[derive(Debug, Clone)] pub(crate) struct Pattern1Parts { @@ -165,82 +164,6 @@ fn has_control_flow_statement(body: &[ASTNode]) -> bool { common_has_control_flow(body) } -// ============================================================================ -// Phase 286 P2.1: Pattern1 → Plan/Frag SSOT extractor -// ============================================================================ - -/// Phase 286 P2.1: Minimal subset extractor for Pattern1 Plan line -/// -/// Supported subset (PoC safety - Compare + Add only): -/// - Loop condition: ` < ` -/// - Loop increment: ` = + ` -/// -/// Returns Ok(None) for unsupported patterns → legacy fallback -pub(crate) fn extract_pattern1_plan( - condition: &ASTNode, - body: &[ASTNode], -) -> Result, String> { - use crate::mir::builder::control_flow::plan::{DomainPlan, Pattern1SimpleWhilePlan}; - - // Step 1: Validate via existing extractor - let parts = extract_simple_while_parts(condition, body)?; - if parts.is_none() { - return Ok(None); // Not Pattern1 → legacy fallback - } - let parts = parts.unwrap(); - - // Step 2: Validate loop condition is ` < ` - if !validate_loop_condition_plan(condition, &parts.loop_var) { - return Ok(None); // Unsupported condition format - } - - // Step 3: Extract loop increment ` = + ` - // Phase 286 P2.2: Use common helper from common_helpers - let loop_increment = match super::common_helpers::extract_loop_increment_plan(body, &parts.loop_var)? { - Some(inc) => inc, - None => return Ok(None), // No loop increment found - }; - - if !is_pattern1_step_only_body(body, &parts.loop_var) { - return Ok(None); - } - - Ok(Some(DomainPlan::Pattern1SimpleWhile(Pattern1SimpleWhilePlan { - loop_var: parts.loop_var, - condition: condition.clone(), - loop_increment, - }))) -} - -/// Validate loop condition: supports ` < ` only -fn validate_loop_condition_plan(cond: &ASTNode, loop_var: &str) -> bool { - use crate::ast::LiteralValue; - - if let ASTNode::BinaryOp { operator, left, right, .. } = cond { - if !matches!(operator, BinaryOperator::Less) { - return false; // Only < supported for PoC - } - - // Left must be the loop variable - if let ASTNode::Variable { name, .. } = left.as_ref() { - if name != loop_var { - return false; - } - } else { - return false; - } - - // Right must be integer literal - if !matches!(right.as_ref(), ASTNode::Literal { value: LiteralValue::Integer(_), .. }) { - return false; - } - - true - } else { - false - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/mir/builder/control_flow/plan/extractors/pattern3.rs b/src/mir/builder/control_flow/plan/extractors/pattern3.rs index 1af4b953..0c157675 100644 --- a/src/mir/builder/control_flow/plan/extractors/pattern3.rs +++ b/src/mir/builder/control_flow/plan/extractors/pattern3.rs @@ -468,97 +468,3 @@ mod tests { assert!(result.unwrap().is_none()); // Has break → Not Pattern3 } } - -// ============================================================================ -// Phase 286 P2.6: Pattern3 → Plan/Frag SSOT extractor -// ============================================================================ - -/// Phase 286 P2.6: Extract Pattern3 (Loop with If-Phi) Plan -/// -/// Leverages existing `extract_loop_with_if_phi_parts()` for validation, -/// then extracts detailed AST components for Plan normalization. -/// -/// # Returns -/// - Ok(Some(DomainPlan::Pattern3IfPhi)) if Pattern3 match confirmed -/// - Ok(None) if not Pattern3 (structural mismatch) -/// - Err if malformed AST (rare) -pub(crate) fn extract_pattern3_plan( - condition: &ASTNode, - body: &[ASTNode], -) -> Result, String> { - use crate::mir::builder::control_flow::plan::{DomainPlan, Pattern3IfPhiPlan}; - - // Step 1: Validate via existing extractor - let parts = extract_loop_with_if_phi_parts(condition, body)?; - if parts.is_none() { - return Ok(None); // Not Pattern3 → fallback - } - let parts = parts.unwrap(); - - // Step 2: Extract if-else statement (validated to exist) - let if_stmt = super::common_helpers::find_if_else_statement(body) - .ok_or_else(|| "Pattern3: if-else statement not found after validation".to_string())?; - - // Step 3: Extract if condition and branch updates - let (if_condition, then_update, else_update) = match if_stmt { - ASTNode::If { - condition: if_cond, - then_body, - else_body: Some(else_body), - .. - } => { - // Extract carrier update from then branch - let then_update = extract_single_update(then_body, &parts.merged_var)?; - - // Extract carrier update from else branch - let else_update = extract_single_update(else_body, &parts.merged_var)?; - - (if_cond.as_ref().clone(), then_update, else_update) - } - _ => { - return Err("Pattern3: if-else structure mismatch after validation".to_string()); - } - }; - - // Step 4: Extract loop increment - let loop_increment = match super::common_helpers::extract_loop_increment_plan(body, &parts.loop_var)? { - Some(inc) => inc, - None => { - return Err(format!( - "Pattern3: loop increment not found for variable '{}'", - parts.loop_var - )); - } - }; - - Ok(Some(DomainPlan::Pattern3IfPhi(Pattern3IfPhiPlan { - loop_var: parts.loop_var, - carrier_var: parts.merged_var, - condition: condition.clone(), - if_condition, - then_update, - else_update, - loop_increment, - }))) -} - -/// Extract update expression from a branch body -/// -/// Expects a single assignment: `carrier = ` -/// Returns the RHS expression AST -fn extract_single_update(body: &[ASTNode], carrier_var: &str) -> Result { - for stmt in body { - if let ASTNode::Assignment { target, value, .. } = stmt { - if let ASTNode::Variable { name, .. } = target.as_ref() { - if name == carrier_var { - return Ok(value.as_ref().clone()); - } - } - } - } - - Err(format!( - "Pattern3: carrier update not found for variable '{}' in branch", - carrier_var - )) -} diff --git a/src/mir/builder/control_flow/plan/single_planner/rules.rs b/src/mir/builder/control_flow/plan/single_planner/rules.rs index 11036840..c87f8947 100644 --- a/src/mir/builder/control_flow/plan/single_planner/rules.rs +++ b/src/mir/builder/control_flow/plan/single_planner/rules.rs @@ -96,11 +96,11 @@ fn fallback_extract( allow_pattern8: bool, ) -> Result, String> { match kind { - PlanRuleId::Pattern1 => extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body), + PlanRuleId::Pattern1 => Ok(None), PlanRuleId::Pattern2 => { extractors::pattern2_break::extract_pattern2_plan(ctx.condition, ctx.body) } - PlanRuleId::Pattern3 => extractors::pattern3::extract_pattern3_plan(ctx.condition, ctx.body), + PlanRuleId::Pattern3 => Ok(None), PlanRuleId::Pattern4 => extractors::pattern4::extract_pattern4_plan(ctx.condition, ctx.body), PlanRuleId::Pattern5 => extractors::pattern5::extract_pattern5_plan(ctx.condition, ctx.body), PlanRuleId::Pattern6 => {