feat(phi): Phase 26-F-2 - 箱理論による責務分離(IfBodyLocalMergeBox新設)

**箱理論による問題解決**:
-  問題: LoopVarClassBox(ループスコープ分析)とif-merge処理が混在
-  解決: if-merge専用箱を新設して責務分離

**新箱: IfBodyLocalMergeBox**:
- 責務: if-merge専用のbody-local φ候補決定
- ロジック:
  - 両腕に存在する変数を検出
  - pre_ifと比較して値が変わった変数のみ
  - empty elseは空リスト返す
- 特徴: LocalScopeInspector不要、LoopVarClassBox不使用

**変更ファイル**:
- src/mir/phi_core/if_body_local_merge.rs: 新規作成(IfBodyLocalMergeBox)
- src/mir/phi_core/phi_builder_box.rs: IfBodyLocalMergeBox使用に切り替え
- src/mir/phi_core/body_local_phi_builder.rs: filter_if_merge_candidates()削除
- src/mir/loop_builder.rs: BodyLocalPhiBuilder setup削除
- src/mir/phi_core/mod.rs: if_body_local_merge追加

**テスト結果**:
- Passed: 353→354 (+1) 
- Failed: 14→14 (退行なし)

**既知の問題**:
- domination error依然残存(%48 in bb48 from bb52)
- 次フェーズで調査・修正予定

技術詳細:
- ChatGPT箱理論分析による設計
- A案ベースのシンプル実装
- 責務明確化: ループスコープ分析 vs if-merge専用処理
This commit is contained in:
nyash-codex
2025-11-22 11:03:21 +09:00
parent cbe6bf0140
commit 948f22a03a
15 changed files with 634 additions and 353 deletions

View File

@ -0,0 +1,89 @@
// mir_funcscanner_parse_params_trim_min.rs
// Rust-level test for FuncScannerBox.parse_params + trim minimal SSA/PHI repro
//
// Goal:
// - Compile lang/src/compiler/entry/func_scanner.hako + minimal test .hako
// - Run MirVerifier to see if the undefined-value / dominator errors already
// appear in this smaller case。
// - Optionally execute via VM to surface runtime InvalidValue errors。
use crate::ast::ASTNode;
use crate::mir::{MirCompiler, MirVerifier};
use crate::parser::NyashParser;
#[test]
fn mir_funcscanner_parse_params_trim_min_verify_and_vm() {
// Minimal .hako that calls FuncScannerBox.parse_params + trim。
let test_file = "lang/src/compiler/tests/funcscanner_parse_params_trim_min.hako";
// Align parser env to Stage3 + using 経路(既存の skip_ws 系と揃えておく)。
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
std::env::set_var("NYASH_ENABLE_USING", "1");
std::env::set_var("HAKO_ENABLE_USING", "1");
std::env::set_var("NYASH_PARSER_ALLOW_SEMICOLON", "1");
std::env::set_var("NYASH_DISABLE_PLUGINS", "1");
// Optional: enable MIR debug / SSA debug when running this test manually。
// std::env::set_var("NYASH_MIR_DEBUG_LOG", "1");
// std::env::set_var("NYASH_VM_VERIFY_MIR", "1");
// std::env::set_var("NYASH_IF_HOLE_TRACE", "1");
// Bundle FuncScanner 本体と最小テスト。
let func_scanner_src =
include_str!("../../lang/src/compiler/entry/func_scanner.hako");
let test_src =
std::fs::read_to_string(test_file).expect("Failed to read minimal test .hako");
let src = format!("{func_scanner_src}\n\n{test_src}");
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("parse_params_trim_min: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc
.compile(ast)
.expect("parse_params_trim_min: MIR compile failed");
eprintln!(
"[parse-params-trim/min] module functions = {}",
compiled.module.functions.len()
);
// MIR verify: ここで Undefined / dominator エラーが出るかを見る。
let mut verifier = MirVerifier::new();
if let Err(errors) = verifier.verify_module(&compiled.module) {
eprintln!("[parse-params-trim/min] MIR verification errors:");
for e in &errors {
eprintln!("[rust-mir-verify] {}", e);
}
// いまは「バグ検出」が目的なので、失敗しても panic しておく。
panic!("parse_params_trim_min: MIR verification failed");
}
// VM 実行も一度試しておく(将来の回 regressions 用)。
use crate::backend::VM;
let mut vm = VM::new();
let vm_out = vm
.execute_module(&compiled.module)
.expect("parse_params_trim_min: VM execution failed");
let result_str = vm_out.to_string_box().value;
eprintln!("[parse-params-trim/min] VM result='{}'", result_str);
// Main.main は成功時 0 を返す想定。
assert_eq!(
result_str, "0",
"parse_params_trim_min: expected exit code 0"
);
// Cleanup env vars
std::env::remove_var("NYASH_PARSER_STAGE3");
std::env::remove_var("HAKO_PARSER_STAGE3");
std::env::remove_var("NYASH_ENABLE_USING");
std::env::remove_var("HAKO_ENABLE_USING");
std::env::remove_var("NYASH_PARSER_ALLOW_SEMICOLON");
std::env::remove_var("NYASH_DISABLE_PLUGINS");
std::env::remove_var("NYASH_MIR_DEBUG_LOG");
std::env::remove_var("NYASH_VM_VERIFY_MIR");
std::env::remove_var("NYASH_IF_HOLE_TRACE");
}

View File

@ -0,0 +1,41 @@
// Smallest repro for skip_whitespace SSA/PHI issues
// Inputs: lang/src/compiler/tests/funcscanner_skip_ws_min.hako
// Goal: verify + VM execute without undefined ValueId
use crate::ast::ASTNode;
use crate::mir::{MirCompiler, MirVerifier};
use crate::parser::NyashParser;
#[test]
fn mir_funcscanner_skip_ws_min_verify_and_vm() {
let test_file = "lang/src/compiler/tests/funcscanner_skip_ws_min.hako";
// Stage-3 + using
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
std::env::set_var("NYASH_ENABLE_USING", "1");
std::env::set_var("HAKO_ENABLE_USING", "1");
std::env::set_var("NYASH_DISABLE_PLUGINS", "1");
let src = std::fs::read_to_string(test_file).expect("Failed to read test file");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("compile failed");
let mut verifier = MirVerifier::new();
if let Err(errors) = verifier.verify_module(&compiled.module) {
panic!("MIR verify failed: {:?}", errors);
}
use crate::backend::VM;
let mut vm = VM::new();
vm.execute_module(&compiled.module).expect("VM exec failed");
std::env::remove_var("NYASH_PARSER_STAGE3");
std::env::remove_var("HAKO_PARSER_STAGE3");
std::env::remove_var("NYASH_ENABLE_USING");
std::env::remove_var("HAKO_ENABLE_USING");
std::env::remove_var("NYASH_DISABLE_PLUGINS");
}

View File

@ -8,6 +8,7 @@ pub mod identical_exec_instance;
pub mod identical_exec_string;
pub mod mir_breakfinder_ssa;
pub mod mir_funcscanner_skip_ws;
pub mod mir_funcscanner_parse_params_trim_min;
pub mod mir_funcscanner_ssa;
pub mod mir_locals_ssa;
pub mod mir_loopform_conditional_reassign;