test(mir): Phase 25.1 StaticCompiler receiver回帰防止テスト追加

## テスト内容
1. MIR compile & verify(SSA検証)
2. VM実行でRC=0(receiver捏造バグ検出)
3. StringBox正規化確認(ParserBox→StringBox)

## 検証項目
-  StringHelpers.skip_ws/2 呼び出し成功
-  receiver型推論正常動作
-  文字列メソッド正規化動作確認

Co-Authored-By: ChatGPT5 <chatgpt@openai.com>
This commit is contained in:
nyash-codex
2025-11-21 14:00:09 +09:00
parent eb10fc7159
commit 74271f3c5b
2 changed files with 137 additions and 0 deletions

View File

@ -0,0 +1,136 @@
/*!
* Phase 25.1 StaticCompiler receiver型推論バグ回帰防止テスト
*
* ## 問題再現
* - StringHelpers.skip_ws/2 呼び出しで receiver 型情報なし
* - ParserBox.length が Global("ParserBox.length") に変換されてVM落ち
*
* ## 修正内容
* - Phase 1: guard.rs でreceiver型なし→Global変換
* - Phase 2: unified_emitter.rs で guard→materialization 順序反転
* - Phase 3-A: emit_string型注釈追加
* - Phase 3-B: BinOp(Add)型注釈強化
* - Phase 3-C: StaticCompiler文字列メソッド→StringBox正規化
*
* ## 検証項目
* 1. MIR compile + verify が通る
* 2. VM実行でRC=0エラー落ちしない
* 3. StringBox.length に正規化されている
*/
use crate::ast::ASTNode;
use crate::backend::VM;
use crate::mir::{instruction::MirInstruction, MirCompiler, MirVerifier};
use crate::parser::NyashParser;
fn ensure_stage3_env() {
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");
}
/// Stage1Cli + StringHelpers.skip_ws テスト用フィクスチャ
fn stage1_staticcompiler_fixture_src() -> String {
let stage1_cli_src = include_str!("../../lang/src/runner/stage1_cli.hako");
let test_main_src = r#"
using lang.src.runner.stage1_cli as Stage1Cli
static box Main {
main(args) {
env.set("STAGE1_SOURCE_TEXT", "static box Main { main() { return StringHelpers.skip_ws(\" a\", 0) } }")
local prog = Stage1Cli.emit_program_json_from_text()
print("[stage1_staticcompiler_receiver] prog=" + ("" + prog))
return 0
}
}
"#;
format!("{stage1_cli_src}\n\n{test_main_src}")
}
/// Test 1: MIR compile & verify が通ることを確認
#[test]
fn mir_stage1_staticcompiler_receiver_compiles_and_verifies() {
ensure_stage3_env();
let src = stage1_staticcompiler_fixture_src();
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("parse ok");
let mut mc = MirCompiler::with_options(false);
let cr = mc.compile(ast).expect("compile");
let mut verifier = MirVerifier::new();
if let Err(errors) = verifier.verify_module(&cr.module) {
for e in &errors {
eprintln!("[rust-mir-verify] {}", e);
}
panic!("MIR verification failed for stage1_staticcompiler_receiver");
}
}
/// Test 2: VM実行でRC=0receiver捏造バグがないことを確認
#[test]
fn mir_stage1_staticcompiler_receiver_exec_succeeds() {
ensure_stage3_env();
std::env::set_var("NYASH_DISABLE_PLUGINS", "1"); // Plugin依存を排除
let src = stage1_staticcompiler_fixture_src();
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("parse ok");
let mut mc = MirCompiler::with_options(false);
let cr = mc.compile(ast).expect("compile");
let mut verifier = MirVerifier::new();
verifier.verify_module(&cr.module).expect("verify");
// VM実行
let mut vm = VM::new();
let result = vm.execute_module(&cr.module);
// RC=0 を期待receiver捏造バグがあると "Unknown: ParserBox.length" で落ちる)
assert!(
result.is_ok(),
"VM should execute successfully without receiver fabrication error"
);
}
/// Test 3: StringBox正規化が行われていることを確認MIR検証
#[test]
fn mir_stage1_staticcompiler_receiver_normalizes_to_stringbox() {
ensure_stage3_env();
let src = stage1_staticcompiler_fixture_src();
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("parse ok");
let mut mc = MirCompiler::with_options(false);
let cr = mc.compile(ast).expect("compile");
// StringHelpers.skip_ws 内の .length() 呼び出しを探す
let mut found_stringbox_length = false;
for (fname, func) in cr.module.functions.iter() {
if fname.contains("StringHelpers") {
for (bb_id, block) in &func.blocks {
for inst in &block.instructions {
if let MirInstruction::Call { callee, .. } = inst {
if let Some(crate::mir::Callee::Method {
box_name, method, ..
}) = callee
{
if box_name == "StringBox" && method == "length" {
found_stringbox_length = true;
eprintln!(
"[test] Found StringBox.length in {} bb={:?}",
fname, bb_id
);
}
}
}
}
}
}
}
assert!(
found_stringbox_length,
"Expected StaticCompiler string methods to be normalized to StringBox"
);
}

View File

@ -15,6 +15,7 @@ pub mod mir_loopform_exit_phi;
pub mod mir_loopform_complex;
pub mod mir_static_box_naming;
pub mod mir_stage1_cli_emit_program_min;
pub mod mir_stage1_staticcompiler_receiver; // Phase 25.1: StaticCompiler receiver型推論バグ回帰防止
pub mod mir_stage1_using_resolver_verify;
pub mod stage1_cli_entry_ssa_smoke;
pub mod mir_stageb_like_args_length;