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:
136
src/tests/mir_stage1_staticcompiler_receiver.rs
Normal file
136
src/tests/mir_stage1_staticcompiler_receiver.rs
Normal 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=0(receiver捏造バグがないことを確認)
|
||||
#[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"
|
||||
);
|
||||
}
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user