diff --git a/src/mir/builder.rs b/src/mir/builder.rs index cc89417d..1dd3f237 100644 --- a/src/mir/builder.rs +++ b/src/mir/builder.rs @@ -28,8 +28,11 @@ mod exprs_call; mod metadata_context; // Phase 136 follow-up (Step 6/7): MetadataContext extraction mod method_call_handlers; mod variable_context; // Phase 136 follow-up (Step 5/7): VariableContext extraction // Method call handler separation (Phase 3) // call(expr) - // include lowering removed (using is handled in runner) + // include lowering removed (using is handled in runner) mod control_flow; // thin wrappers to centralize control-flow entrypoints + +// Phase 140-P4-A: Re-export for loop_canonicalizer SSOT (crate-wide visibility) +pub(crate) use control_flow::{detect_skip_whitespace_pattern, SkipWhitespaceInfo}; mod exprs_lambda; // lambda lowering mod exprs_peek; // peek expression mod exprs_qmark; // ?-propagate diff --git a/src/mir/builder/control_flow/joinir/mod.rs b/src/mir/builder/control_flow/joinir/mod.rs index d7d8dd29..cc3f68c0 100644 --- a/src/mir/builder/control_flow/joinir/mod.rs +++ b/src/mir/builder/control_flow/joinir/mod.rs @@ -13,3 +13,6 @@ pub(in crate::mir::builder) mod patterns; pub(in crate::mir::builder) mod routing; pub(in crate::mir::builder) mod routing_legacy_binding; pub(in crate::mir::builder) mod trace; + +// Phase 140-P4-A: Re-export for loop_canonicalizer SSOT (crate-wide visibility) +pub(crate) use patterns::{detect_skip_whitespace_pattern, SkipWhitespaceInfo}; diff --git a/src/mir/builder/control_flow/joinir/patterns/mod.rs b/src/mir/builder/control_flow/joinir/patterns/mod.rs index c00ba383..47b14ee2 100644 --- a/src/mir/builder/control_flow/joinir/patterns/mod.rs +++ b/src/mir/builder/control_flow/joinir/patterns/mod.rs @@ -64,3 +64,6 @@ pub(in crate::mir::builder) mod trim_pattern_validator; // Re-export router for convenience pub(in crate::mir::builder) use router::{route_loop_pattern, LoopPatternContext}; + +// Phase 140-P4-A: Re-export for loop_canonicalizer SSOT (crate-wide visibility) +pub(crate) use ast_feature_extractor::{detect_skip_whitespace_pattern, SkipWhitespaceInfo}; diff --git a/src/mir/builder/control_flow/mod.rs b/src/mir/builder/control_flow/mod.rs index ce6ca768..bbb01821 100644 --- a/src/mir/builder/control_flow/mod.rs +++ b/src/mir/builder/control_flow/mod.rs @@ -54,6 +54,9 @@ pub(in crate::mir::builder) mod exception; // Phase 6: Utility functions pub(in crate::mir::builder) mod utils; +// Phase 140-P4-A: Re-export for loop_canonicalizer SSOT (crate-wide visibility) +pub(crate) use joinir::{detect_skip_whitespace_pattern, SkipWhitespaceInfo}; + impl super::MirBuilder { /// Control-flow: block pub(super) fn cf_block(&mut self, statements: Vec) -> Result { diff --git a/src/mir/join_ir/lowering/mod.rs b/src/mir/join_ir/lowering/mod.rs index ff7123d4..9865292a 100644 --- a/src/mir/join_ir/lowering/mod.rs +++ b/src/mir/join_ir/lowering/mod.rs @@ -69,7 +69,7 @@ pub mod scope_manager; // Phase 231: Unified variable scope management // Phase #[cfg(feature = "normalized_dev")] pub mod scope_manager_bindingid_poc; pub(crate) mod step_schedule; // Phase 47-A: Generic step scheduler for P2/P3 (renamed from pattern2_step_schedule) // Phase 73: BindingId-based scope PoC (dev-only) - // Phase 242-EX-A: loop_with_if_phi_minimal removed - replaced by loop_with_if_phi_if_sum + // Phase 242-EX-A: loop_with_if_phi_minimal removed - replaced by loop_with_if_phi_if_sum pub mod loop_with_if_phi_if_sum; // Phase 213: Pattern 3 AST-based if-sum lowerer (Phase 242-EX-A: supports complex conditions) pub mod min_loop; pub mod simple_while_minimal; // Phase 188-Impl-1: Pattern 1 minimal lowerer diff --git a/src/mir/loop_canonicalizer/pattern_recognizer.rs b/src/mir/loop_canonicalizer/pattern_recognizer.rs index 83ef7cde..7daceba7 100644 --- a/src/mir/loop_canonicalizer/pattern_recognizer.rs +++ b/src/mir/loop_canonicalizer/pattern_recognizer.rs @@ -1,12 +1,13 @@ //! Pattern Recognition Helpers //! -//! This module contains pattern detection logic for specific loop structures. -//! Currently supports the skip_whitespace pattern, with room for future patterns. +//! Phase 140-P4-B: This module now delegates to SSOT implementations in ast_feature_extractor. +//! Provides backward-compatible wrappers for existing callsites. use crate::ast::ASTNode; +use crate::mir::{detect_skip_whitespace_pattern as ast_detect, SkipWhitespaceInfo}; // ============================================================================ -// Skip Whitespace Pattern +// Skip Whitespace Pattern (Phase 140-P4-B SSOT Wrapper) // ============================================================================ /// Try to extract skip_whitespace pattern from loop @@ -24,86 +25,15 @@ use crate::ast::ASTNode; /// ``` /// /// Returns (carrier_name, delta, body_stmts) if pattern matches. +/// +/// # Phase 140-P4-B: SSOT Migration +/// +/// This function now delegates to `ast_feature_extractor::detect_skip_whitespace_pattern` +/// for SSOT implementation. This wrapper maintains backward compatibility for existing callsites. pub fn try_extract_skip_whitespace_pattern( body: &[ASTNode], ) -> Option<(String, i64, Vec)> { - if body.is_empty() { - return None; - } - - // Last statement must be if-else with break - let last_stmt = &body[body.len() - 1]; - - let (then_body, else_body) = match last_stmt { - ASTNode::If { - then_body, - else_body: Some(else_body), - .. - } => (then_body, else_body), - _ => return None, - }; - - // Then branch must be single assignment: carrier = carrier + const - if then_body.len() != 1 { - return None; - } - - let (carrier_name, delta) = match &then_body[0] { - ASTNode::Assignment { target, value, .. } => { - // Extract target variable name - let target_name = match target.as_ref() { - ASTNode::Variable { name, .. } => name.clone(), - _ => return None, - }; - - // Value must be: target + const - match value.as_ref() { - ASTNode::BinaryOp { - operator: crate::ast::BinaryOperator::Add, - left, - right, - .. - } => { - // Left must be same variable - let left_name = match left.as_ref() { - ASTNode::Variable { name, .. } => name, - _ => return None, - }; - - if left_name != &target_name { - return None; - } - - // Right must be integer literal - let delta = match right.as_ref() { - ASTNode::Literal { - value: crate::ast::LiteralValue::Integer(n), - .. - } => *n, - _ => return None, - }; - - (target_name, delta) - } - _ => return None, - } - } - _ => return None, - }; - - // Else branch must be single break - if else_body.len() != 1 { - return None; - } - - match &else_body[0] { - ASTNode::Break { .. } => { - // Success! Extract body statements (all except last if) - let body_stmts = body[..body.len() - 1].to_vec(); - Some((carrier_name, delta, body_stmts)) - } - _ => None, - } + ast_detect(body).map(|info| (info.carrier_name, info.delta, info.body_stmts)) } #[cfg(test)] diff --git a/src/mir/mod.rs b/src/mir/mod.rs index 3ca35b2f..29d9f391 100644 --- a/src/mir/mod.rs +++ b/src/mir/mod.rs @@ -55,6 +55,9 @@ pub mod verification_types; // extracted error types // Optimization subpasses ( pub use basic_block::{BasicBlock, BasicBlockId, BasicBlockIdGenerator}; pub use binding_id::BindingId; // Phase 74: BindingId infrastructure pub use builder::MirBuilder; + +// Phase 140-P4-A: Re-export for loop_canonicalizer SSOT +pub(crate) use builder::{detect_skip_whitespace_pattern, SkipWhitespaceInfo}; pub use cfg_extractor::extract_cfg_info; // Phase 154: CFG extraction pub use definitions::{CallFlags, Callee, MirCall}; // Unified call definitions pub use effect::{Effect, EffectMask};