refactor(joinir): Phase 170-A Step 1.5 - LoopFeatures-based detection API
Clarify design principle: CaseALoweringShape does NOT look at function names. Input must be LoopFeatures/LoopPatternKind only (structure-based detection). Changes: - Add detect_from_features(LoopFeatures, carrier_count, has_progress_carrier) - Deprecate detect(LoopScopeShape) with backward-compat wrapper - Case-A now rejects loops with `has_continue` (only break is allowed) - Document Phase 170-B future work (loop body AST analysis) Design Principle: > "CaseALoweringShape は 関数名を見ない。LoopFeatures/LoopPatternKind だけを入力にする" This ensures generic routing works for ANY structurally matching loop. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -82,32 +82,48 @@ pub enum CaseALoweringShape {
|
||||
}
|
||||
|
||||
impl CaseALoweringShape {
|
||||
/// Detect lowering shape from LoopScopeShape
|
||||
/// Detect lowering shape from LoopFeatures
|
||||
///
|
||||
/// Phase 170-A: Heuristic-based shape detection
|
||||
/// # Phase 170-A Design Principle
|
||||
///
|
||||
/// Returns NotCaseA if structural requirements not met.
|
||||
/// Returns one of the above if structural analysis suggests a pattern.
|
||||
/// **CaseALoweringShape does NOT look at function names.**
|
||||
/// Input: LoopFeatures / LoopPatternKind only (structure-based detection).
|
||||
///
|
||||
/// This is the core architectural invariant that enables generic routing.
|
||||
///
|
||||
/// # Heuristics
|
||||
/// - Single carrier (1) → likely StringExamination or ArrayAccumulation
|
||||
/// - Multiple carriers (2+) → likely IterationWithAccumulation
|
||||
/// - Pinned count → disambiguation hint
|
||||
/// - has_break/has_continue → affects Case-A eligibility
|
||||
///
|
||||
/// Note: More sophisticated pattern matching (analyzing loop body structure)
|
||||
/// is deferred to Phase 170-B.
|
||||
pub fn detect(scope: &super::shape::LoopScopeShape) -> Self {
|
||||
use super::shape::LoopScopeShape;
|
||||
/// # Phase 170-B Future Work
|
||||
/// - Analyze loop body AST for more precise classification
|
||||
/// - Distinguish StringExamination vs ArrayAccumulation
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `features` - LoopFeatures (structure-based, name-agnostic)
|
||||
/// * `carrier_count` - Number of carrier variables from LoopScopeShape
|
||||
/// * `has_progress_carrier` - Whether progress carrier exists
|
||||
pub fn detect_from_features(
|
||||
features: &crate::mir::loop_pattern_detection::LoopFeatures,
|
||||
carrier_count: usize,
|
||||
has_progress_carrier: bool,
|
||||
) -> Self {
|
||||
// Case-A requirement: must have a progress carrier
|
||||
if !has_progress_carrier {
|
||||
return CaseALoweringShape::NotCaseA;
|
||||
}
|
||||
|
||||
// Check if structurally Case-A
|
||||
if scope.progress_carrier.is_none() {
|
||||
// Case-A requirement: no complex control flow (continue)
|
||||
// Note: break is allowed (StringExamination patterns use break)
|
||||
if features.has_continue {
|
||||
return CaseALoweringShape::NotCaseA;
|
||||
}
|
||||
|
||||
// Phase 170-A: Simple heuristic based on carrier count
|
||||
match scope.carriers.len() {
|
||||
match carrier_count {
|
||||
0 => {
|
||||
// This shouldn't happen if progress_carrier is Some, but be safe
|
||||
// This shouldn't happen if has_progress_carrier is true, but be safe
|
||||
CaseALoweringShape::NotCaseA
|
||||
}
|
||||
1 => {
|
||||
@ -124,6 +140,33 @@ impl CaseALoweringShape {
|
||||
}
|
||||
}
|
||||
|
||||
/// Legacy wrapper: Detect from LoopScopeShape (deprecated, use detect_from_features)
|
||||
///
|
||||
/// Phase 170-A: Kept for backward compatibility during transition.
|
||||
#[deprecated(
|
||||
since = "Phase 170-A",
|
||||
note = "Use detect_from_features() with LoopFeatures instead"
|
||||
)]
|
||||
pub fn detect(scope: &super::shape::LoopScopeShape) -> Self {
|
||||
// Construct minimal LoopFeatures from LoopScopeShape
|
||||
// Note: This loses some information (has_break, has_continue not available)
|
||||
let has_progress_carrier = scope.progress_carrier.is_some();
|
||||
let carrier_count = scope.carriers.len();
|
||||
|
||||
// Create stub features (Phase 170-B will use real LoopFeatures)
|
||||
let stub_features = crate::mir::loop_pattern_detection::LoopFeatures {
|
||||
has_break: false, // Unknown from LoopScopeShape alone
|
||||
has_continue: false, // Unknown from LoopScopeShape alone
|
||||
has_if: false,
|
||||
has_if_else_phi: false,
|
||||
carrier_count,
|
||||
break_count: 0,
|
||||
continue_count: 0,
|
||||
};
|
||||
|
||||
Self::detect_from_features(&stub_features, carrier_count, has_progress_carrier)
|
||||
}
|
||||
|
||||
/// Is this a recognized lowering shape?
|
||||
pub fn is_recognized(&self) -> bool {
|
||||
!matches!(self, CaseALoweringShape::NotCaseA | CaseALoweringShape::Generic)
|
||||
|
||||
Reference in New Issue
Block a user