feat(joinir): Phase 92 P0-2 - Skeleton to LoopPatternContext (Option A)
SSOT principle: Pass canonicalizer-derived ConditionalStep info to Pattern2 lowerer without re-detecting from AST. Changes: - router.rs: Add skeleton: Option<&'a LoopSkeleton> to LoopPatternContext - parity_checker.rs: Return (Result, Option<LoopSkeleton>) to reuse skeleton - routing.rs: Pass skeleton to context when joinir_dev_enabled() - pattern2_with_break.rs: Detect ConditionalStep in can_lower() Next: P0-3 implements actual JoinIR generation for ConditionalStep. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -647,10 +647,12 @@ fn collect_body_local_variables(
|
||||
/// Phase 192: Updated to structure-based detection
|
||||
/// Phase 178: Added string carrier rejection (unsupported by Pattern 2)
|
||||
/// Phase 187-2: No legacy fallback - rejection means error
|
||||
/// Phase 92 P0-2: Added ConditionalStep detection from skeleton (Option A)
|
||||
///
|
||||
/// Pattern 2 matches:
|
||||
/// - Pattern kind is Pattern2Break (has break, no continue)
|
||||
/// - No string/complex carrier updates (JoinIR doesn't support string concat)
|
||||
/// - ConditionalStep updates are supported (if skeleton provides them)
|
||||
pub(crate) fn can_lower(builder: &MirBuilder, ctx: &super::router::LoopPatternContext) -> bool {
|
||||
use super::common_init::CommonPatternInitializer;
|
||||
use crate::mir::loop_pattern_detection::LoopPatternKind;
|
||||
@ -671,6 +673,32 @@ pub(crate) fn can_lower(builder: &MirBuilder, ctx: &super::router::LoopPatternCo
|
||||
);
|
||||
}
|
||||
|
||||
// Phase 92 P0-2: Check skeleton for ConditionalStep support
|
||||
if let Some(skeleton) = ctx.skeleton {
|
||||
use crate::mir::loop_canonicalizer::UpdateKind;
|
||||
|
||||
// Count ConditionalStep carriers
|
||||
let conditional_step_count = skeleton.carriers.iter()
|
||||
.filter(|c| matches!(c.update_kind, UpdateKind::ConditionalStep { .. }))
|
||||
.count();
|
||||
|
||||
if conditional_step_count > 0 {
|
||||
if ctx.debug {
|
||||
trace::trace().debug(
|
||||
"pattern2/can_lower",
|
||||
&format!(
|
||||
"Phase 92 P0-2: Found {} ConditionalStep carriers in skeleton",
|
||||
conditional_step_count
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Phase 92 P0-2: ConditionalStep support enabled
|
||||
// Pattern2 can handle these via if-else JoinIR generation
|
||||
// TODO: Implement actual lowering in cf_loop_pattern2_with_break_impl
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 188/Refactor: Use common carrier update validation
|
||||
// Extracts loop variable for dummy carrier creation (not used but required by API)
|
||||
let loop_var_name = match builder.extract_loop_variable_from_condition(ctx.condition) {
|
||||
|
||||
@ -29,6 +29,9 @@ use crate::mir::loop_pattern_detection::{LoopFeatures, LoopPatternKind};
|
||||
/// (declared in mod.rs as pub module, import from parent)
|
||||
use super::ast_feature_extractor as ast_features;
|
||||
|
||||
/// Phase 92 P0-2: Import LoopSkeleton for Option A
|
||||
use crate::mir::loop_canonicalizer::LoopSkeleton;
|
||||
|
||||
/// Context passed to pattern detect/lower functions
|
||||
pub(crate) struct LoopPatternContext<'a> {
|
||||
/// Loop condition AST node
|
||||
@ -61,6 +64,13 @@ pub(crate) struct LoopPatternContext<'a> {
|
||||
/// Phase 200-C: Optional function body AST for capture analysis
|
||||
/// None if not available, Some(&[ASTNode]) if function body is accessible
|
||||
pub fn_body: Option<&'a [ASTNode]>,
|
||||
|
||||
/// Phase 92 P0-2: Optional LoopSkeleton from canonicalizer
|
||||
/// This provides ConditionalStep information for Pattern2 lowering.
|
||||
/// None if canonicalizer hasn't run yet (backward compatibility).
|
||||
/// SSOT Principle: Avoid re-detecting ConditionalStep in lowering phase.
|
||||
#[allow(dead_code)]
|
||||
pub skeleton: Option<&'a LoopSkeleton>,
|
||||
}
|
||||
|
||||
impl<'a> LoopPatternContext<'a> {
|
||||
@ -71,6 +81,7 @@ impl<'a> LoopPatternContext<'a> {
|
||||
/// 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
|
||||
/// Phase 92 P0-2: Added skeleton parameter (None for backward compatibility)
|
||||
pub(crate) fn new(
|
||||
condition: &'a ASTNode,
|
||||
body: &'a [ASTNode],
|
||||
@ -99,6 +110,7 @@ impl<'a> LoopPatternContext<'a> {
|
||||
features,
|
||||
pattern_kind,
|
||||
fn_body: None, // Phase 200-C: Default to None
|
||||
skeleton: None, // Phase 92 P0-2: Default to None
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,6 +126,13 @@ impl<'a> LoopPatternContext<'a> {
|
||||
ctx.fn_body = Some(fn_body);
|
||||
ctx
|
||||
}
|
||||
|
||||
/// Phase 92 P0-2: Set skeleton (for canonicalizer integration)
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn with_skeleton(mut self, skeleton: &'a LoopSkeleton) -> Self {
|
||||
self.skeleton = Some(skeleton);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase 193: Feature extraction moved to ast_feature_extractor module
|
||||
|
||||
Reference in New Issue
Block a user