feat(joinir): Phase 188.3-P3.1,3.2 - AST extraction & validation helpers

Phase 3-1 完了: extract_inner_loop_ast() 実装
- 外側 loop body から内側 loop を抽出
- 正確に 1 つの inner loop を検証
- 0 個 or 2+ 個の場合は明示エラー (Fail-Fast)

Phase 3-2 完了: validate_strict_mode() プレースホルダー
- 現在は大半の検証を is_pattern6_lowerable() で実施
- 将来の strict mode チェック用の足場

ドキュメント追加:
- P1-INSTRUCTIONS.md: Phase 3-3 実装指示書 (4関数モデル詳細)
- README.md: max_loop_depth 定義の明確化
- 10-Now.md: Phase 188.3 方針の整合性維持

次タスク: Phase 3-3 (Continuation 生成) - P1-INSTRUCTIONS.md 参照

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-27 06:22:59 +09:00
parent a2c5fd90fe
commit c6ffc06660
4 changed files with 280 additions and 9 deletions

View File

@ -22,11 +22,74 @@
//! - Generate k_inner_exit (bridges to outer continuation)
//! - Wire continuations
use crate::ast::ASTNode;
use crate::mir::builder::control_flow::joinir::patterns::LoopPatternContext;
use crate::mir::builder::MirBuilder;
use crate::mir::loop_pattern_detection::LoopPatternKind;
use crate::mir::ValueId;
/// Phase 188.3: Validate strict mode constraints
///
/// Requirements (most already checked in is_pattern6_lowerable):
/// - Inner loop has no break (checked in routing.rs)
/// - Inner loop has no continue (checked in routing.rs)
/// - Outer loop has no break (checked in routing.rs)
/// - Outer loop has no continue (checked in routing.rs)
///
/// Additional checks (Phase 188.4+):
/// - Outer variable write-back detection (TODO: add to is_pattern6_lowerable)
///
/// This function serves as final safety check before lowering.
/// If validation fails → Fail-Fast (not silent fallback).
fn validate_strict_mode(_inner_ast: &ASTNode, _ctx: &LoopPatternContext) -> Result<(), String> {
// Phase 188.3: Most validation already done in is_pattern6_lowerable()
// This is a placeholder for future strict mode checks
// Future Phase 188.4+ checks:
// - Detect outer variable write-back in inner loop body
// - Validate carrier compatibility
// - Check for unsupported AST patterns
Ok(())
}
/// Phase 188.3: Extract inner loop AST from outer loop body
///
/// Requirements:
/// - Outer body must contain exactly 1 Loop node
/// - 0 loops → Error (shouldn't happen after Pattern6 selection)
/// - 2+ loops → Error (multiple inner loops not supported)
///
/// Returns reference to inner loop ASTNode
fn extract_inner_loop_ast<'a>(ctx: &'a LoopPatternContext) -> Result<&'a ASTNode, String> {
// Find all Loop nodes in outer body
let mut inner_loop: Option<&ASTNode> = None;
let mut loop_count = 0;
for stmt in ctx.body.iter() {
if matches!(stmt, ASTNode::Loop { .. }) {
loop_count += 1;
if inner_loop.is_none() {
inner_loop = Some(stmt);
}
}
}
// Validate exactly 1 inner loop
match loop_count {
0 => Err(
"[Pattern6/extract] No inner loop found (should not happen after Pattern6 selection)"
.to_string(),
),
1 => Ok(inner_loop.unwrap()), // Safe: loop_count == 1 guarantees Some
_ => Err(format!(
"[Pattern6/extract] Multiple inner loops ({}) not supported. \
Phase 188.3 supports exactly 1 inner loop only.",
loop_count
)),
}
}
/// Detect if this context can be lowered as Pattern6 (NestedLoopMinimal)
///
/// Pattern selection happens in choose_pattern_kind() (SSOT).
@ -40,9 +103,15 @@ pub(crate) fn can_lower(_builder: &MirBuilder, ctx: &LoopPatternContext) -> bool
/// Phase 188.3: Full implementation with continuation generation
pub(crate) fn lower(
_builder: &mut MirBuilder,
_ctx: &LoopPatternContext,
ctx: &LoopPatternContext,
) -> Result<Option<ValueId>, String> {
// Phase 188.3 stub - full implementation in Phase 3-3
// Phase 3-1: Extract inner loop AST (validate exactly 1 inner loop)
let inner_ast = extract_inner_loop_ast(ctx)?;
// Phase 3-2: Validate strict mode constraints (Fail-Fast)
validate_strict_mode(inner_ast, ctx)?;
// Phase 3-3 stub - full implementation next
// TODO: Implement continuation generation (outer_step, inner_step, k_inner_exit)
Err("[Pattern6] Nested loop lowering not yet implemented (Phase 188.3 stub)".to_string())
Err("[Pattern6] Nested loop lowering not yet implemented (Phase 3-3 pending)".to_string())
}