feat(mir): Loop Canonicalizer Phase 2 - dev-only observation
## Summary ループ入口で LoopSkeleton/RoutingDecision を観測できるようにした。 既定挙動は完全不変(dev-only の並行観測のみ)。 ## Changes - src/mir/loop_canonicalizer/mod.rs: canonicalize_loop_expr() 追加 - Phase 2 最小実装: loop 構造検証のみ - パターン検出は未実装(全て Fail-Fast) - LoopSkeleton の基本構造(HeaderCond step)を生成 - 詳細な Fail-Fast 理由を返す - src/mir/builder/control_flow/joinir/routing.rs: dev-only 観測ポイント - joinir_dev_enabled() ON 時のみ観測ログ出力 - LoopSkeleton/RoutingDecision の内容を可視化 - 既存の routing/lowering は完全無変更 - 最小実装: skip_whitespace 相当の構造検証のみ対応 - 追加テスト: - test_canonicalize_rejects_non_loop - test_canonicalize_minimal_loop_structure - test_canonicalize_rejects_multi_statement_loop - test_canonicalize_rejects_if_without_else ## Tests - cargo test --release --lib: 1043 passed (退行なし) - HAKO_JOINIR_DEBUG=1: 観測ログ出力確認 - デフォルト: 完全無変更(ログも挙動も) ## Acceptance Criteria ✅ joinir_dev_enabled() ON 時のみ観測ログが出る ✅ joinir_dev_enabled() OFF 時は完全に無変更(ログも挙動も) ✅ 既存の smoke / cargo test --release --lib が退行しない ✅ 最小パターン(if-else with break)で LoopSkeleton が生成できる ✅ 未対応パターンは Fail-Fast で詳細理由を返す Phase 137-2 complete
This commit is contained in:
@ -122,6 +122,38 @@ impl MirBuilder {
|
||||
func_name: &str,
|
||||
debug: bool,
|
||||
) -> Result<Option<ValueId>, String> {
|
||||
// Phase 137-2: Dev-only observation via Loop Canonicalizer
|
||||
if crate::config::env::joinir_dev_enabled() {
|
||||
use crate::ast::Span;
|
||||
use crate::mir::loop_canonicalizer::canonicalize_loop_expr;
|
||||
|
||||
// Reconstruct loop AST for canonicalizer
|
||||
let loop_ast = ASTNode::Loop {
|
||||
condition: Box::new(condition.clone()),
|
||||
body: body.to_vec(),
|
||||
span: Span::unknown(),
|
||||
};
|
||||
|
||||
match canonicalize_loop_expr(&loop_ast) {
|
||||
Ok((skeleton, decision)) => {
|
||||
eprintln!("[loop_canonicalizer] Function: {}", func_name);
|
||||
eprintln!("[loop_canonicalizer] Skeleton steps: {}", skeleton.steps.len());
|
||||
eprintln!("[loop_canonicalizer] Carriers: {}", skeleton.carriers.len());
|
||||
eprintln!("[loop_canonicalizer] Has exits: {}", skeleton.exits.has_any_exit());
|
||||
eprintln!("[loop_canonicalizer] Decision: {}",
|
||||
if decision.is_success() { "SUCCESS" } else { "FAIL_FAST" });
|
||||
if decision.is_fail_fast() {
|
||||
eprintln!("[loop_canonicalizer] Reason: {}", decision.notes.join("; "));
|
||||
eprintln!("[loop_canonicalizer] Missing caps: {:?}", decision.missing_caps);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[loop_canonicalizer] Function: {}", func_name);
|
||||
eprintln!("[loop_canonicalizer] Error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 194: Use table-driven router instead of if/else chain
|
||||
use super::patterns::{route_loop_pattern, LoopPatternContext};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user