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:
nyash-codex
2025-12-16 15:22:29 +09:00
parent 6169ae03d6
commit 51017a0f9a
5 changed files with 266 additions and 9 deletions

View File

@ -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