feat(joinir): FuncScannerBox.trim/1 JoinIR VM Bridge A/B test
Phase 30.x: JoinIR VM Bridge でPHI問題を設計で解決できることを実証 変更内容: - src/runner/modes/vm.rs: FuncScannerBox.trim/1 検出時にJoinIR経由実行 - src/mir/join_ir_vm_bridge.rs: Non-tail call サポート追加 - dst=Some(id) の場合、結果を格納して次の命令へ継続 - src/tests/joinir_vm_bridge_trim.rs: A/Bテスト新規作成 - メインテスト: Route A (VM) → "void" (PHI bug), Route C (JoinIR) → "abc" ✅ - エッジケース: 5パターン全てPASS - src/config/env.rs: joinir_vm_bridge_debug() 追加 - docs: Phase 30 TASKS.md に L-0.4 追加 テスト結果: Route A (MIR→VM直接): "void" ← PHI バグ Route C (MIR→JoinIR→VM): "abc" ← 正解 ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -2,6 +2,13 @@ use super::super::NyashRunner;
|
||||
use nyash_rust::{ast::ASTNode, mir::MirCompiler, parser::NyashParser};
|
||||
use std::{fs, process};
|
||||
|
||||
// Phase 30.x: JoinIR VM Bridge integration (experimental)
|
||||
// Used only when NYASH_JOINIR_EXPERIMENT=1 AND NYASH_JOINIR_VM_BRIDGE=1
|
||||
use crate::config::env::{joinir_experiment_enabled, joinir_vm_bridge_enabled};
|
||||
use crate::mir::join_ir::{lower_funcscanner_trim_to_joinir, lower_skip_ws_to_joinir, JoinFuncId};
|
||||
use crate::mir::join_ir_ops::JoinValue;
|
||||
use crate::mir::join_ir_vm_bridge::run_joinir_via_vm;
|
||||
|
||||
impl NyashRunner {
|
||||
/// Execute VM mode with full plugin initialization and AST prelude merge
|
||||
pub(crate) fn execute_vm_mode(&self, filename: &str) {
|
||||
@ -495,6 +502,106 @@ impl NyashRunner {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 30.x: JoinIR VM Bridge experimental path
|
||||
// Activated when NYASH_JOINIR_EXPERIMENT=1 AND NYASH_JOINIR_VM_BRIDGE=1
|
||||
// Currently only supports minimal_ssa_skip_ws.hako (Main.skip function)
|
||||
let joinir_path_attempted = if joinir_experiment_enabled() && joinir_vm_bridge_enabled() {
|
||||
// Check if this module contains Main.skip/1 (minimal_ssa_skip_ws target)
|
||||
// Note: function names include arity suffix like "Main.skip/1"
|
||||
let has_main_skip = module_vm.functions.contains_key("Main.skip/1");
|
||||
let has_trim = module_vm.functions.contains_key("FuncScannerBox.trim/1");
|
||||
|
||||
if has_main_skip {
|
||||
eprintln!("[joinir/vm_bridge] Attempting JoinIR path for Main.skip");
|
||||
match lower_skip_ws_to_joinir(&module_vm) {
|
||||
Some(join_module) => {
|
||||
// Get input argument from NYASH_JOINIR_INPUT or use default
|
||||
let input = std::env::var("NYASH_JOINIR_INPUT")
|
||||
.unwrap_or_else(|_| " abc".to_string());
|
||||
eprintln!("[joinir/vm_bridge] Input: {:?}", input);
|
||||
|
||||
match run_joinir_via_vm(
|
||||
&join_module,
|
||||
JoinFuncId::new(0),
|
||||
&[JoinValue::Str(input)],
|
||||
) {
|
||||
Ok(result) => {
|
||||
let exit_code = match &result {
|
||||
JoinValue::Int(v) => *v as i32,
|
||||
JoinValue::Bool(b) => if *b { 1 } else { 0 },
|
||||
_ => 0,
|
||||
};
|
||||
eprintln!("[joinir/vm_bridge] ✅ JoinIR result: {:?}", result);
|
||||
if !quiet_pipe {
|
||||
println!("RC: {}", exit_code);
|
||||
}
|
||||
process::exit(exit_code);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[joinir/vm_bridge] ❌ JoinIR execution failed: {:?}", e);
|
||||
eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
|
||||
false // Continue to normal VM execution
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
eprintln!("[joinir/vm_bridge] lower_skip_ws_to_joinir returned None");
|
||||
eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
|
||||
false
|
||||
}
|
||||
}
|
||||
} else if has_trim {
|
||||
// Phase 30.x: FuncScannerBox.trim/1 JoinIR path
|
||||
eprintln!("[joinir/vm_bridge] Attempting JoinIR path for FuncScannerBox.trim");
|
||||
match lower_funcscanner_trim_to_joinir(&module_vm) {
|
||||
Some(join_module) => {
|
||||
// Get input argument from NYASH_JOINIR_INPUT or use default
|
||||
let input = std::env::var("NYASH_JOINIR_INPUT")
|
||||
.unwrap_or_else(|_| " abc ".to_string());
|
||||
eprintln!("[joinir/vm_bridge] Input: {:?}", input);
|
||||
|
||||
match run_joinir_via_vm(
|
||||
&join_module,
|
||||
JoinFuncId::new(0),
|
||||
&[JoinValue::Str(input)],
|
||||
) {
|
||||
Ok(result) => {
|
||||
// trim returns a string, print it and exit with 0
|
||||
eprintln!("[joinir/vm_bridge] ✅ JoinIR trim result: {:?}", result);
|
||||
if !quiet_pipe {
|
||||
match &result {
|
||||
JoinValue::Str(s) => println!("{}", s),
|
||||
_ => println!("{:?}", result),
|
||||
}
|
||||
}
|
||||
process::exit(0);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[joinir/vm_bridge] ❌ JoinIR trim failed: {:?}", e);
|
||||
eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
eprintln!("[joinir/vm_bridge] lower_funcscanner_trim_to_joinir returned None");
|
||||
eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false // No supported JoinIR target function
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Normal VM execution path (fallback or default)
|
||||
if joinir_path_attempted {
|
||||
// This branch is never reached because successful JoinIR path calls process::exit()
|
||||
unreachable!("JoinIR path should have exited");
|
||||
}
|
||||
|
||||
match vm.execute_module(&module_vm) {
|
||||
Ok(ret) => {
|
||||
use crate::box_trait::{BoolBox, IntegerBox};
|
||||
|
||||
Reference in New Issue
Block a user