feat(joinir): Structural pattern detection + Pattern 4 scaffold

- Add LoopFeatures struct for structure-based detection (no name deps)
- Add LoopPatternKind enum and classify() function
- Pattern 3: has_if_else_phi && !has_break && !has_continue
- Pattern 4: has_continue == true (detection only, lowering TODO)
- Unify router to use extract_features()/classify() instead of legacy
- Remove AST dependency, use LoopForm/LoopScope only
- Add Pattern 4 test file (loop_continue_pattern4.hako)
- Pattern 3 test passes (sum=9)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-06 00:10:27 +09:00
parent 255517ed58
commit a21501286e
7 changed files with 657 additions and 32 deletions

View File

@ -419,44 +419,51 @@ pub fn try_lower_loop_pattern_to_joinir(
loop_form: &LoopForm,
lowerer: &mut LoopToJoinLowerer,
) -> Option<JoinInst> {
// Phase 188: Pattern-based loop lowering router
// Tries patterns in order: Pattern 1 → Pattern 2 → Pattern 3
// Phase 194: Structure-based pattern classification
// Tries patterns based on CFG structure, not function names
use crate::mir::loop_pattern_detection::{
is_loop_with_break_pattern, is_loop_with_conditional_phi_pattern, is_simple_while_pattern,
};
use crate::mir::loop_pattern_detection::{classify, extract_features, LoopPatternKind};
// Pattern 1: Simple While Loop (easiest, most common)
// ====================================================
if is_simple_while_pattern(loop_form) {
if let Some(inst) = loop_patterns::lower_simple_while_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 1 (Simple While) matched");
return Some(inst);
// Step 1: Extract features from LoopForm (no LoopScope needed for now)
let features = extract_features(loop_form, None);
// Step 2: Classify pattern based on structure
let pattern = classify(&features);
// Step 3: Route to appropriate lowerer based on pattern
match pattern {
LoopPatternKind::Pattern4Continue => {
if let Some(inst) = loop_patterns::lower_loop_with_continue_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 4 (Continue) matched");
return Some(inst);
}
}
}
// Pattern 2: Loop with Conditional Break (medium complexity)
// ===========================================================
if is_loop_with_break_pattern(loop_form) {
if let Some(inst) = loop_patterns::lower_loop_with_break_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 2 (Loop with Break) matched");
return Some(inst);
LoopPatternKind::Pattern3IfPhi => {
if let Some(inst) = loop_patterns::lower_loop_with_conditional_phi_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 3 (If-Else PHI) matched");
return Some(inst);
}
}
}
// Pattern 3: Loop with If-Else PHI (leverages existing If lowering)
// ==================================================================
// Phase 188-Impl-3: Pattern 3 implementation
if is_loop_with_conditional_phi_pattern(loop_form) {
if let Some(inst) = loop_patterns::lower_loop_with_conditional_phi_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 3 (Loop with If-Else PHI) matched");
return Some(inst);
LoopPatternKind::Pattern2Break => {
if let Some(inst) = loop_patterns::lower_loop_with_break_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 2 (Break) matched");
return Some(inst);
}
}
LoopPatternKind::Pattern1SimpleWhile => {
if let Some(inst) = loop_patterns::lower_simple_while_to_joinir(loop_form, lowerer) {
eprintln!("[try_lower_loop_pattern] ✅ Pattern 1 (Simple While) matched");
return Some(inst);
}
}
LoopPatternKind::Unknown => {
eprintln!("[try_lower_loop_pattern] ❌ Unknown pattern, fallback to existing lowering");
}
}
// No Pattern Matched (fallback to existing lowering)
// ===================================================
eprintln!("[try_lower_loop_pattern] ❌ No pattern matched, fallback to existing lowering");
eprintln!("[try_lower_loop_pattern] ❌ Pattern lowering failed, fallback to existing lowering");
None
}