// Phase 27-shortterm S-4.4: JoinIR → Rust VM Bridge A/B Test // // 目的: // - JoinIR を VM ブリッジ経由で実行し、直接 VM 実行の結果と一致することを確認する // - Route A (AST→MIR→VM) と Route C (AST→MIR→JoinIR→MIR'→VM) の比較 // // Test Pattern: // - skip_ws(" abc") → 3 (leading spaces count) // // Implementation Status: // - S-4.3: Basic bridge structure ✅ // - S-4.4-A: Call/Jump instructions for skip_ws pattern ✅ // - S-4.4-B: A/B test (this file) ✅ use crate::ast::ASTNode; use crate::backend::VM; use crate::mir::join_ir::{lower_skip_ws_to_joinir, JoinFuncId}; use crate::mir::join_ir_ops::JoinValue; use crate::mir::join_ir_vm_bridge::run_joinir_via_vm; use crate::mir::MirCompiler; use crate::parser::NyashParser; fn require_experiment_toggle() -> bool { if std::env::var("NYASH_JOINIR_VM_BRIDGE") .ok() .as_deref() != Some("1") { eprintln!( "[joinir/vm_bridge] NYASH_JOINIR_VM_BRIDGE=1 not set, skipping VM bridge test" ); return false; } true } #[test] #[ignore] fn joinir_vm_bridge_skip_ws_matches_direct_vm() { if !require_experiment_toggle() { return; } std::env::set_var("NYASH_PARSER_STAGE3", "1"); std::env::set_var("HAKO_PARSER_STAGE3", "1"); std::env::set_var("NYASH_DISABLE_PLUGINS", "1"); std::env::set_var("NYASH_VM_MAX_STEPS", "100000"); let src = std::fs::read_to_string("apps/tests/minimal_ssa_skip_ws.hako") .expect("failed to read minimal_ssa_skip_ws.hako"); let runner = r#" static box Runner { main(args) { return Main.skip(" abc") } } "#; let full_src = format!("{src}\n{runner}"); let ast: ASTNode = NyashParser::parse_from_string(&full_src).expect("skip_ws: parse failed"); let mut mc = MirCompiler::with_options(false); let compiled = mc.compile(ast).expect("skip_ws: MIR compile failed"); // Route A: AST → MIR → VM (direct) eprintln!("[joinir_vm_bridge_test] Route A: Direct VM execution"); std::env::set_var("NYASH_ENTRY", "Runner.main"); let mut vm = VM::new(); let vm_out = vm .execute_module(&compiled.module) .expect("skip_ws: VM execution failed"); let vm_result = vm_out.to_string_box().value; std::env::remove_var("NYASH_ENTRY"); eprintln!("[joinir_vm_bridge_test] Route A result: {}", vm_result); // Route C: AST → MIR → JoinIR → MIR' → VM (via bridge) eprintln!("[joinir_vm_bridge_test] Route C: JoinIR → VM bridge execution"); let join_module = lower_skip_ws_to_joinir(&compiled.module).expect("lower_skip_ws_to_joinir failed"); let bridge_result = run_joinir_via_vm( &join_module, JoinFuncId::new(0), &[JoinValue::Str(" abc".to_string())], ) .expect("JoinIR VM bridge failed for skip_ws"); eprintln!("[joinir_vm_bridge_test] Route C result: {:?}", bridge_result); // Assertions: Both routes should produce the same result assert_eq!(vm_result, "3", "Route A (VM) expected to skip 3 leading spaces"); match bridge_result { JoinValue::Int(v) => { assert_eq!(v, 3, "Route C (JoinIR→VM bridge) skip_ws result mismatch"); eprintln!("[joinir_vm_bridge_test] ✅ A/B test passed: both routes returned 3"); } other => panic!("JoinIR VM bridge returned non-int value: {:?}", other), } std::env::remove_var("NYASH_PARSER_STAGE3"); std::env::remove_var("HAKO_PARSER_STAGE3"); std::env::remove_var("NYASH_DISABLE_PLUGINS"); std::env::remove_var("NYASH_VM_MAX_STEPS"); }