**Quick Win 1: PromotedBindingRecorder Box Introduction** - **New file**: `promoted_binding_recorder.rs` (167 lines) - Type-safe BindingId recording for promoted variables - Centralizes scattered binding_map wiring logic - Result-based error handling (BindingRecordError enum) - 4 unit tests (1 always-on + 3 feature-gated) - Dual impl blocks for feature gate handling - **Updated DigitPosPromoter**: `loop_body_digitpos_promoter.rs` - Replaced 30-line binding_map wiring with 2-line recorder call - Added log_promotion_error() helper function - Removed scattered eprintln! warnings - **Updated TrimLoopHelper**: `loop_body_carrier_promoter.rs` - Replaced 30-line binding_map wiring with 2-line recorder call - Added log_trim_promotion_error() helper function - Updated 4 tests to include binding_map field **Quick Win 2: Error Handling Improvement** - Replaced eprintln! with Result-based errors - Added clear error messages via helper functions - Both promoters now use same error logging pattern - Testable error paths (3 error tests added) **Impact**: - **Code reduction**: ~30 lines deleted (duplicated wiring logic) - **Maintainability**: Single reusable Box for future promoters - **Testability**: Error cases now covered by unit tests - **Consistency**: Unified error message format **Test Results**: - Without feature: 959/959 PASS (1 new test added) - With normalized_dev: 1010/1013 PASS (4 new tests total) - 3 failing tests are pre-existing phase49 issues - All PromotedBindingRecorder tests: 4/4 PASS - All DigitPosPromoter tests: 6/6 PASS - All CarrierPromoter tests: 10/10 PASS **Build Status**: ✅ Clean (0 errors, 0 warnings) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
704 lines
23 KiB
Rust
704 lines
23 KiB
Rust
//! Loop Pattern Detection Module
|
|
//!
|
|
//! Phase 188 Task 188-4: Pattern detection helpers for JoinIR loop lowering.
|
|
//!
|
|
//! This module provides detection functions for 4 loop patterns:
|
|
//! - Pattern 1: Simple While Loop (foundational)
|
|
//! - Pattern 2: Loop with Conditional Break (early exit)
|
|
//! - Pattern 3: Loop with If-Else PHI (variable mutation)
|
|
//! - Pattern 4: Loop with Continue (skip iteration)
|
|
//!
|
|
//! Phase 194+: Structure-based detection using LoopFeatures.
|
|
//! Patterns are classified based on CFG structure, not function names.
|
|
//!
|
|
//! # Architecture
|
|
//!
|
|
//! ```
|
|
//! LoopForm → extract_features() → LoopFeatures → classify() → LoopPatternKind
|
|
//! ```
|
|
//!
|
|
//! Reference: docs/private/roadmap2/phases/phase-188-joinir-loop-pattern-expansion/design.md
|
|
|
|
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
|
use crate::mir::loop_form::LoopForm;
|
|
|
|
// ============================================================================
|
|
// Pattern Classification System (Phase 194+)
|
|
// ============================================================================
|
|
|
|
/// Loop pattern classification based on structure.
|
|
///
|
|
/// This enum represents the 4 main loop patterns we support.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum LoopPatternKind {
|
|
/// Pattern 1: Simple While Loop
|
|
/// - No break, no continue
|
|
/// - Single backedge
|
|
Pattern1SimpleWhile,
|
|
|
|
/// Pattern 2: Loop with Conditional Break
|
|
/// - Has break statement(s)
|
|
/// - No continue statements
|
|
Pattern2Break,
|
|
|
|
/// Pattern 3: Loop with If-Else PHI
|
|
/// - Has if-else statement with PHI
|
|
/// - No break, no continue
|
|
/// - Multiple carrier variables
|
|
Pattern3IfPhi,
|
|
|
|
/// Pattern 4: Loop with Continue
|
|
/// - Has continue statement(s)
|
|
/// - No break statements (for simplicity)
|
|
Pattern4Continue,
|
|
|
|
/// Pattern not recognized
|
|
Unknown,
|
|
}
|
|
|
|
impl LoopPatternKind {
|
|
/// Phase 193-3: Get human-readable pattern name
|
|
///
|
|
/// Returns the friendly name for this pattern (e.g., "Pattern 1: Simple While")
|
|
pub fn name(&self) -> &'static str {
|
|
match self {
|
|
LoopPatternKind::Pattern1SimpleWhile => "Pattern 1: Simple While Loop",
|
|
LoopPatternKind::Pattern2Break => "Pattern 2: Loop with Conditional Break",
|
|
LoopPatternKind::Pattern3IfPhi => "Pattern 3: Loop with If-Else PHI",
|
|
LoopPatternKind::Pattern4Continue => "Pattern 4: Loop with Continue",
|
|
LoopPatternKind::Unknown => "Unknown Pattern",
|
|
}
|
|
}
|
|
|
|
/// Phase 193-3: Get numeric pattern ID
|
|
///
|
|
/// Returns the pattern number (1-4) or 0 for unknown.
|
|
/// Useful for priority sorting.
|
|
pub fn pattern_id(&self) -> u8 {
|
|
match self {
|
|
LoopPatternKind::Pattern1SimpleWhile => 1,
|
|
LoopPatternKind::Pattern2Break => 2,
|
|
LoopPatternKind::Pattern3IfPhi => 3,
|
|
LoopPatternKind::Pattern4Continue => 4,
|
|
LoopPatternKind::Unknown => 0,
|
|
}
|
|
}
|
|
|
|
/// Phase 193-3: Check if this is a recognized pattern
|
|
///
|
|
/// Returns false only for Unknown.
|
|
pub fn is_recognized(&self) -> bool {
|
|
!matches!(self, LoopPatternKind::Unknown)
|
|
}
|
|
|
|
/// Phase 193-3: Check if pattern has special control flow
|
|
///
|
|
/// Returns true if pattern involves break or continue.
|
|
pub fn has_special_control_flow(&self) -> bool {
|
|
matches!(
|
|
self,
|
|
LoopPatternKind::Pattern2Break | LoopPatternKind::Pattern4Continue
|
|
)
|
|
}
|
|
|
|
/// Phase 193-3: Check if pattern involves PHI merging
|
|
///
|
|
/// Returns true if pattern has if-else PHI merge.
|
|
pub fn has_phi_merge(&self) -> bool {
|
|
matches!(self, LoopPatternKind::Pattern3IfPhi)
|
|
}
|
|
}
|
|
|
|
/// Feature vector extracted from loop structure.
|
|
///
|
|
/// This structure captures all relevant properties needed for pattern classification.
|
|
/// It is name-agnostic and purely structure-based.
|
|
#[derive(Debug, Clone)]
|
|
pub struct LoopFeatures {
|
|
/// Has break statement(s)?
|
|
pub has_break: bool,
|
|
|
|
/// Has continue statement(s)?
|
|
pub has_continue: bool,
|
|
|
|
/// Has if statement(s) in body?
|
|
pub has_if: bool,
|
|
|
|
/// Has if-else statement with PHI nodes?
|
|
/// (detected via multiple carriers or specific CFG patterns)
|
|
pub has_if_else_phi: bool,
|
|
|
|
/// Number of carrier variables (loop variables that are updated)
|
|
pub carrier_count: usize,
|
|
|
|
/// Number of break targets
|
|
pub break_count: usize,
|
|
|
|
/// Number of continue targets
|
|
pub continue_count: usize,
|
|
|
|
/// Phase 170-C-2b: Carrier update pattern summary
|
|
///
|
|
/// Contains UpdateKind (CounterLike/AccumulationLike/Other) for each carrier.
|
|
/// Used by CaseALoweringShape for more precise shape detection.
|
|
/// None if carrier names are not available.
|
|
pub update_summary:
|
|
Option<crate::mir::join_ir::lowering::loop_update_summary::LoopUpdateSummary>,
|
|
}
|
|
|
|
impl LoopFeatures {
|
|
/// Phase 193-3: Get debug statistics string
|
|
///
|
|
/// Returns a formatted string showing all feature values for debugging.
|
|
pub fn debug_stats(&self) -> String {
|
|
format!(
|
|
"LoopFeatures {{ break: {}, continue: {}, if: {}, if_else_phi: {}, carriers: {}, break_count: {}, continue_count: {} }}",
|
|
self.has_break,
|
|
self.has_continue,
|
|
self.has_if,
|
|
self.has_if_else_phi,
|
|
self.carrier_count,
|
|
self.break_count,
|
|
self.continue_count
|
|
)
|
|
}
|
|
|
|
/// Phase 193-3: Count total control flow divergences
|
|
///
|
|
/// Returns the total number of break + continue targets.
|
|
/// Useful for determining loop complexity.
|
|
pub fn total_divergences(&self) -> usize {
|
|
self.break_count + self.continue_count
|
|
}
|
|
|
|
/// Phase 193-3: Check if loop has complex control flow
|
|
///
|
|
/// Returns true if loop has multiple divergences or multiple carriers.
|
|
pub fn is_complex(&self) -> bool {
|
|
self.total_divergences() > 1 || self.carrier_count > 1
|
|
}
|
|
|
|
/// Phase 193-3: Check if loop is simple (no special features)
|
|
///
|
|
/// Returns true if loop is purely sequential.
|
|
pub fn is_simple(&self) -> bool {
|
|
!self.has_break && !self.has_continue && !self.has_if_else_phi && self.carrier_count <= 1
|
|
}
|
|
}
|
|
|
|
/// Extract features from LoopForm for pattern classification.
|
|
///
|
|
/// This function is the entry point for structure-based pattern detection.
|
|
/// It analyzes the CFG structure without relying on variable names.
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
/// * `scope` - Optional LoopScopeShape for carrier analysis
|
|
///
|
|
/// # Returns
|
|
/// * `LoopFeatures` - Feature vector for pattern classification
|
|
pub(crate) fn extract_features(
|
|
loop_form: &LoopForm,
|
|
scope: Option<&LoopScopeShape>,
|
|
) -> LoopFeatures {
|
|
// Phase 194: Basic feature extraction from LoopForm
|
|
let has_break = !loop_form.break_targets.is_empty();
|
|
let has_continue = !loop_form.continue_targets.is_empty();
|
|
let break_count = loop_form.break_targets.len();
|
|
let continue_count = loop_form.continue_targets.len();
|
|
|
|
// Phase 194+: Extract carrier_count from LoopScopeShape if available
|
|
let carrier_count = scope.map(|s| s.carriers.len()).unwrap_or(0);
|
|
|
|
// Pattern 3 heuristic: has_if_else_phi if carrier_count > 1
|
|
// This is a conservative heuristic - multiple carriers typically
|
|
// indicate if-else statements with PHI nodes.
|
|
let has_if_else_phi = carrier_count > 1;
|
|
|
|
// TODO: Implement has_if detection via CFG analysis
|
|
// For now, we infer it from carrier_count > 1 (Pattern 3 heuristic)
|
|
let has_if = has_if_else_phi;
|
|
|
|
// Phase 170-C-2b: Build update_summary from carrier names
|
|
// Note: carriers is BTreeSet<String>, so each item is already a String
|
|
let update_summary = scope.map(|s| {
|
|
let carrier_names: Vec<String> = s.carriers.iter().cloned().collect();
|
|
crate::mir::join_ir::lowering::loop_update_summary::analyze_loop_updates_by_name(
|
|
&carrier_names,
|
|
)
|
|
});
|
|
|
|
LoopFeatures {
|
|
has_break,
|
|
has_continue,
|
|
has_if,
|
|
has_if_else_phi,
|
|
carrier_count,
|
|
break_count,
|
|
continue_count,
|
|
update_summary,
|
|
}
|
|
}
|
|
|
|
/// Classify loop pattern based on feature vector.
|
|
///
|
|
/// This function implements the pattern classification logic using
|
|
/// structure-based rules. It does NOT depend on function names or
|
|
/// variable names like "sum".
|
|
///
|
|
/// # Pattern Classification Rules (Phase 212.5: Structural if detection)
|
|
///
|
|
/// 1. **Pattern 4 (Continue)**: `has_continue == true`
|
|
/// - Priority: Check first (most specific)
|
|
///
|
|
/// 2. **Pattern 3 (If-PHI)**: `has_if && carrier_count >= 1 && !has_break && !has_continue`
|
|
/// - Phase 212.5: Changed from carrier_count > 1 to structural if detection
|
|
/// - Includes single-carrier if-update patterns (e.g., if-sum with 1 carrier)
|
|
///
|
|
/// 3. **Pattern 2 (Break)**: `has_break && !has_continue`
|
|
/// - Has break but no continue
|
|
///
|
|
/// 4. **Pattern 1 (Simple While)**: `!has_break && !has_continue && !has_if`
|
|
/// - Phase 212.5: Exclude loops with if statements
|
|
/// - No control flow alterations
|
|
///
|
|
/// # Arguments
|
|
/// * `features` - Feature vector from extract_features()
|
|
///
|
|
/// # Returns
|
|
/// * `LoopPatternKind` - Classified pattern
|
|
///
|
|
/// # Phase 183: Unified Detection
|
|
///
|
|
/// This is the single source of truth for pattern classification.
|
|
/// Both routers (`router.rs` and `loop_pattern_router.rs`) use this
|
|
/// function to avoid duplicate detection logic.
|
|
pub fn classify(features: &LoopFeatures) -> LoopPatternKind {
|
|
// Pattern 4: Continue (highest priority)
|
|
if features.has_continue {
|
|
return LoopPatternKind::Pattern4Continue;
|
|
}
|
|
|
|
// Pattern 3: If-PHI (check before Pattern 1)
|
|
// Phase 212.5: Structural if detection - route to P3 if has_if && carrier_count >= 1
|
|
if features.has_if
|
|
&& features.carrier_count >= 1
|
|
&& !features.has_break
|
|
&& !features.has_continue
|
|
{
|
|
return LoopPatternKind::Pattern3IfPhi;
|
|
}
|
|
|
|
// Pattern 2: Break
|
|
if features.has_break && !features.has_continue {
|
|
return LoopPatternKind::Pattern2Break;
|
|
}
|
|
|
|
// Pattern 1: Simple While
|
|
// Phase 212.5: Exclude loops with if statements (they go to P3)
|
|
if !features.has_break && !features.has_continue && !features.has_if {
|
|
return LoopPatternKind::Pattern1SimpleWhile;
|
|
}
|
|
|
|
// Unknown pattern
|
|
LoopPatternKind::Unknown
|
|
}
|
|
|
|
/// Phase 193-3: Diagnose pattern classification with details
|
|
///
|
|
/// This function performs classification AND generates diagnostic information.
|
|
/// Useful for debugging and logging.
|
|
///
|
|
/// # Returns
|
|
/// * `(LoopPatternKind, String)` - The classified pattern and a diagnostic message
|
|
pub fn classify_with_diagnosis(features: &LoopFeatures) -> (LoopPatternKind, String) {
|
|
let pattern = classify(features);
|
|
let reason = match pattern {
|
|
LoopPatternKind::Pattern4Continue => {
|
|
format!(
|
|
"Has continue statement (continue_count={})",
|
|
features.continue_count
|
|
)
|
|
}
|
|
LoopPatternKind::Pattern3IfPhi => {
|
|
format!(
|
|
"Has if-else PHI with {} carriers, no break/continue",
|
|
features.carrier_count
|
|
)
|
|
}
|
|
LoopPatternKind::Pattern2Break => {
|
|
format!(
|
|
"Has break statement (break_count={}), no continue",
|
|
features.break_count
|
|
)
|
|
}
|
|
LoopPatternKind::Pattern1SimpleWhile => {
|
|
"Simple while loop with no special control flow".to_string()
|
|
}
|
|
LoopPatternKind::Unknown => {
|
|
format!("Unknown pattern: {}", features.debug_stats())
|
|
}
|
|
};
|
|
|
|
(pattern, reason)
|
|
}
|
|
|
|
// ============================================================================
|
|
// Legacy Detection Functions (Phase 188)
|
|
// ============================================================================
|
|
//
|
|
// NOTE (Phase 179): These functions are still actively used by pattern lowerers.
|
|
// The term "legacy" refers to Phase 188 implementation style (name-based detection),
|
|
// not deprecation status. Do NOT move to legacy/ subdirectory - still production code.
|
|
//
|
|
// Future work: Gradually migrate to Phase 194+ structure-based detection (extract_features/classify).
|
|
|
|
// ============================================================================
|
|
// Pattern 1: Simple While Loop
|
|
// ============================================================================
|
|
|
|
/// Detect Pattern 1: Simple While Loop
|
|
///
|
|
/// Returns true ONLY if:
|
|
/// - Loop condition is simple comparison (no &&, ||)
|
|
/// - Loop body contains only assignments + prints (no nested loops, no breaks)
|
|
/// - Loop has single increment/decrement
|
|
/// - NO break statements (break_targets is empty)
|
|
/// - NO continue statements (continue_targets is empty)
|
|
/// - Single backedge (latches.len() == 1)
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * `true` if the loop matches Pattern 1 (Simple While), `false` otherwise
|
|
///
|
|
/// # Reference
|
|
/// See design.md § Pattern 1 → LoopScopeShape Recognition
|
|
///
|
|
/// # Example
|
|
/// ```rust,ignore
|
|
/// let loop_form = /* ... */;
|
|
/// if is_simple_while_pattern(&loop_form) {
|
|
/// // Lower to simple while pattern
|
|
/// }
|
|
/// ```
|
|
pub fn is_simple_while_pattern(loop_form: &LoopForm) -> bool {
|
|
// Pattern 1 Recognition Criteria (from design.md § Pattern 1):
|
|
// 1. break_targets: EMPTY (no break statements)
|
|
// 2. continue_targets: EMPTY (no continue statements)
|
|
// 3. Single backedge (single latch - LoopShape has singular latch field)
|
|
//
|
|
// Note: LoopShape has a singular `latch` field, not `latches`, so we don't
|
|
// need to check length. The existence of a LoopShape implies a valid latch.
|
|
|
|
// Check 1: No break statements
|
|
if !loop_form.break_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Check 2: No continue statements
|
|
if !loop_form.continue_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Check 3: All other checks passed
|
|
// The LoopShape structure guarantees:
|
|
// - Single preheader, header, body, latch, exit
|
|
// - Valid loop structure
|
|
//
|
|
// Pattern 1 ONLY requires:
|
|
// - No breaks, no continues
|
|
// - Natural loop structure (which LoopShape guarantees)
|
|
//
|
|
// Advanced checks (nested loops, complex conditions) are deferred to
|
|
// lowering phase where we can fail gracefully if needed.
|
|
|
|
true
|
|
}
|
|
|
|
// ============================================================================
|
|
// Pattern 2: Loop with Conditional Break
|
|
// ============================================================================
|
|
|
|
/// Detect Pattern 2: Loop with Conditional Break
|
|
///
|
|
/// Returns true ONLY if:
|
|
/// - Loop condition exists
|
|
/// - Loop body contains exactly ONE if statement with break
|
|
/// - Break is in then-branch
|
|
/// - NO nested loops
|
|
/// - break_targets is NON-EMPTY (has at least one break)
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * `true` if the loop matches Pattern 2 (Break), `false` otherwise
|
|
///
|
|
/// # Reference
|
|
/// See design.md § Pattern 2 → LoopScopeShape Recognition
|
|
///
|
|
/// # Example
|
|
/// ```rust,ignore
|
|
/// let loop_form = /* ... */;
|
|
/// if is_loop_with_break_pattern(&loop_form) {
|
|
/// // Lower to loop with break pattern
|
|
/// }
|
|
/// ```
|
|
pub fn is_loop_with_break_pattern(loop_form: &LoopForm) -> bool {
|
|
// Pattern 2 Recognition Criteria (from design.md § Pattern 2):
|
|
// 1. break_targets: NON-EMPTY (at least 1 break)
|
|
// 2. continue_targets: EMPTY (for simplicity)
|
|
// 3. Exactly ONE break target
|
|
//
|
|
// Phase 188-Impl-2: Minimal implementation
|
|
// Advanced checks (nested loops, if-statement structure) are deferred to
|
|
// lowering phase where we can fail gracefully if needed.
|
|
|
|
// Check 1: break_targets is NON-EMPTY (has at least 1 break)
|
|
if loop_form.break_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Check 2: Exactly ONE break target (pattern assumes single break)
|
|
if loop_form.break_targets.len() != 1 {
|
|
return false;
|
|
}
|
|
|
|
// Check 3: No continue statements (for simplicity in Pattern 2)
|
|
if !loop_form.continue_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Pattern 2 matched
|
|
// The LoopForm structure guarantees:
|
|
// - Valid loop structure
|
|
// - Single break target
|
|
// - No continues
|
|
//
|
|
// Advanced checks (break is in if-statement, etc.) are deferred to
|
|
// lowering phase for graceful failure.
|
|
|
|
true
|
|
}
|
|
|
|
// ============================================================================
|
|
// Pattern 3: Loop with If-Else PHI
|
|
// ============================================================================
|
|
|
|
/// Detect Pattern 3: Loop with If-Else PHI
|
|
///
|
|
/// Returns true ONLY if:
|
|
/// - Loop has if-else statement assigning to variable(s)
|
|
/// - Both branches assign to same variable
|
|
/// - NO nested loops
|
|
/// - NO break or continue statements
|
|
/// - Loop has multiple carrier variables (e.g., i + sum)
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * `true` if the loop matches Pattern 3 (If-Else PHI), `false` otherwise
|
|
///
|
|
/// # Reference
|
|
/// See design.md § Pattern 3 → LoopScopeShape Recognition
|
|
///
|
|
/// # Example
|
|
/// ```rust,ignore
|
|
/// let loop_form = /* ... */;
|
|
/// if is_loop_with_conditional_phi_pattern(&loop_form) {
|
|
/// // Lower to loop with if-else phi pattern
|
|
/// }
|
|
/// ```
|
|
pub fn is_loop_with_conditional_phi_pattern(loop_form: &LoopForm) -> bool {
|
|
// Phase 188-Impl-3: Minimal implementation
|
|
// Pattern 3 Recognition Criteria (from design.md § Pattern 3):
|
|
// 1. break_targets: EMPTY (no break statements)
|
|
// 2. continue_targets: EMPTY (no continue statements)
|
|
// 3. All Pattern 3 loops are valid Pattern 1 loops with extra PHI nodes
|
|
//
|
|
// For now: return true as fallback for Pattern 1 loops
|
|
// Advanced checks (if-else detection, multiple carriers) are deferred to
|
|
// lowering phase where we can fail gracefully if needed.
|
|
|
|
// Check 1: No break statements
|
|
if !loop_form.break_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Check 2: No continue statements
|
|
if !loop_form.continue_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Pattern 3 matched (fallback for now)
|
|
// Since all Pattern 3 loops are also Pattern 1 loops, we can safely return true
|
|
// The lowering phase will determine if the specific pattern is supported
|
|
true
|
|
}
|
|
|
|
// ============================================================================
|
|
// Pattern 4: Loop with Continue
|
|
// ============================================================================
|
|
|
|
/// Detect Pattern 4: Loop with Continue
|
|
///
|
|
/// Returns true ONLY if:
|
|
/// - Loop has continue statement(s)
|
|
/// - Continue is typically in an if statement
|
|
/// - NO break statements (for simplicity)
|
|
/// - Loop has multiple carrier variables
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * `true` if the loop matches Pattern 4 (Continue), `false` otherwise
|
|
///
|
|
/// # Reference
|
|
/// See design.md § Pattern 4 → LoopScopeShape Recognition
|
|
///
|
|
/// # Example
|
|
/// ```rust,ignore
|
|
/// let loop_form = /* ... */;
|
|
/// if is_loop_with_continue_pattern(&loop_form) {
|
|
/// // Lower to loop with continue pattern
|
|
/// }
|
|
/// ```
|
|
pub fn is_loop_with_continue_pattern(loop_form: &LoopForm) -> bool {
|
|
// Pattern 4 Recognition Criteria:
|
|
// 1. continue_targets: NON-EMPTY (at least 1 continue)
|
|
// 2. break_targets: EMPTY (for simplicity in Pattern 4)
|
|
// 3. At least ONE continue target
|
|
//
|
|
// Phase 188-Impl-4: Minimal implementation
|
|
// Advanced checks (nested loops, if-statement structure) are deferred to
|
|
// lowering phase where we can fail gracefully if needed.
|
|
|
|
// Check 1: continue_targets is NON-EMPTY (has at least 1 continue)
|
|
if loop_form.continue_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Check 2: At least ONE continue target (pattern assumes single continue for now)
|
|
if loop_form.continue_targets.len() < 1 {
|
|
return false;
|
|
}
|
|
|
|
// Check 3: No break statements (for simplicity in Pattern 4)
|
|
if !loop_form.break_targets.is_empty() {
|
|
return false;
|
|
}
|
|
|
|
// Pattern 4 matched
|
|
// The LoopForm structure guarantees:
|
|
// - Valid loop structure
|
|
// - At least one continue target
|
|
// - No breaks
|
|
//
|
|
// Advanced checks (continue is in if-statement, etc.) are deferred to
|
|
// lowering phase for graceful failure.
|
|
|
|
true
|
|
}
|
|
|
|
// ============================================================================
|
|
// Helper Functions (Future Use)
|
|
// ============================================================================
|
|
|
|
/// Count the number of carrier variables in a loop
|
|
///
|
|
/// Carrier variables are loop variables that are updated in the loop body
|
|
/// and carried through PHI nodes in the header.
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * Number of carrier variables
|
|
///
|
|
/// # TODO
|
|
/// Implement by analyzing header PHI nodes
|
|
#[allow(dead_code)]
|
|
fn count_carrier_variables(_loop_form: &LoopForm) -> usize {
|
|
// TODO: Implement carrier variable counting
|
|
// Step 1: Access loop_form.header block
|
|
// Step 2: Count PHI instructions in header
|
|
// Step 3: Return count
|
|
0
|
|
}
|
|
|
|
/// Check if loop body contains nested loops
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * `true` if nested loops found, `false` otherwise
|
|
///
|
|
/// # TODO
|
|
/// Implement by checking for LoopForm within body blocks
|
|
#[allow(dead_code)]
|
|
fn has_nested_loops(_loop_form: &LoopForm) -> bool {
|
|
// TODO: Implement nested loop detection
|
|
// Step 1: Traverse body blocks
|
|
// Step 2: Check for loop headers in body
|
|
// Step 3: Return true if any found
|
|
false
|
|
}
|
|
|
|
/// Check if loop condition is simple (single comparison, no && or ||)
|
|
///
|
|
/// # Arguments
|
|
/// * `loop_form` - The loop structure to analyze
|
|
///
|
|
/// # Returns
|
|
/// * `true` if condition is simple, `false` otherwise
|
|
///
|
|
/// # TODO
|
|
/// Implement by checking header condition complexity
|
|
#[allow(dead_code)]
|
|
fn has_simple_condition(_loop_form: &LoopForm) -> bool {
|
|
// TODO: Implement condition complexity check
|
|
// Step 1: Access loop_form.header block
|
|
// Step 2: Find condition instruction
|
|
// Step 3: Check for && or || operators
|
|
// Step 4: Return true if no complex operators
|
|
true // Assume simple for now
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
// Phase 170-D: Loop Condition Scope Analysis Boxes
|
|
pub mod condition_var_analyzer;
|
|
pub mod loop_condition_scope;
|
|
|
|
// Phase 170-ultrathink: Error Message Utilities
|
|
pub mod error_messages;
|
|
|
|
// Phase 171-C: LoopBodyLocal Carrier Promotion
|
|
pub mod loop_body_carrier_promoter;
|
|
|
|
// Phase 223-3: LoopBodyLocal Condition Promotion (for Pattern4)
|
|
pub mod loop_body_cond_promoter;
|
|
|
|
// Phase 224: A-4 DigitPos Pattern Promotion
|
|
pub mod loop_body_digitpos_promoter;
|
|
|
|
// Phase 171-C-5: Trim Pattern Helper
|
|
pub mod trim_loop_helper;
|
|
pub use trim_loop_helper::TrimLoopHelper;
|
|
|
|
// Phase 33-23: Break Condition Analysis (Stage 2, Issue 6)
|
|
pub mod break_condition_analyzer;
|
|
|
|
// Phase 200-A: Function Scope Capture Infrastructure
|
|
pub mod function_scope_capture;
|
|
|
|
// Phase 78: PromotedBindingRecorder - Type-safe BindingId recording
|
|
pub mod promoted_binding_recorder;
|
|
pub use promoted_binding_recorder::{BindingRecordError, PromotedBindingRecorder};
|