2025-09-18 13:35:38 +09:00
|
|
|
|
// no extra imports needed
|
2025-09-17 20:33:19 +09:00
|
|
|
|
|
|
|
|
|
|
/// Run PyVM harness over a MIR module, returning the exit code
|
2025-09-18 13:35:38 +09:00
|
|
|
|
#[allow(dead_code)]
|
2025-09-17 20:33:19 +09:00
|
|
|
|
pub fn run_pyvm_harness(module: &crate::mir::MirModule, tag: &str) -> Result<i32, String> {
|
|
|
|
|
|
let py3 = which::which("python3").map_err(|e| format!("python3 not found: {}", e))?;
|
2025-09-24 21:45:27 +09:00
|
|
|
|
// Resolve runner path relative to CWD or NYASH_ROOT fallback
|
|
|
|
|
|
let mut runner_buf = std::path::PathBuf::from("tools/pyvm_runner.py");
|
|
|
|
|
|
if !runner_buf.exists() {
|
|
|
|
|
|
if let Ok(root) = std::env::var("NYASH_ROOT") {
|
|
|
|
|
|
let alt = std::path::Path::new(&root).join("tools/pyvm_runner.py");
|
|
|
|
|
|
if alt.exists() { runner_buf = alt; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if !runner_buf.exists() {
|
|
|
|
|
|
return Err(format!("PyVM runner not found: tools/pyvm_runner.py (cwd) or $NYASH_ROOT/tools/pyvm_runner.py"));
|
2025-09-17 20:33:19 +09:00
|
|
|
|
}
|
|
|
|
|
|
let tmp_dir = std::path::Path::new("tmp");
|
|
|
|
|
|
let _ = std::fs::create_dir_all(tmp_dir);
|
|
|
|
|
|
let mir_json_path = tmp_dir.join("nyash_pyvm_mir.json");
|
|
|
|
|
|
crate::runner::mir_json_emit::emit_mir_json_for_harness_bin(module, &mir_json_path)
|
|
|
|
|
|
.map_err(|e| format!("PyVM MIR JSON emit error: {}", e))?;
|
|
|
|
|
|
crate::cli_v!("[ny-compiler] using PyVM ({} ) → {}", tag, mir_json_path.display());
|
2025-09-21 08:53:00 +09:00
|
|
|
|
// Determine entry function (prefer Main.main; top-level main only if allowed)
|
|
|
|
|
|
let allow_top = crate::config::env::entry_allow_toplevel_main();
|
2025-09-17 20:33:19 +09:00
|
|
|
|
let entry = if module.functions.contains_key("Main.main") {
|
|
|
|
|
|
"Main.main"
|
2025-09-21 08:53:00 +09:00
|
|
|
|
} else if allow_top && module.functions.contains_key("main") {
|
|
|
|
|
|
"main"
|
2025-09-17 20:33:19 +09:00
|
|
|
|
} else if module.functions.contains_key("main") {
|
2025-09-21 08:53:00 +09:00
|
|
|
|
eprintln!("[entry] Warning: using top-level 'main' without explicit allow; set NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 to silence.");
|
2025-09-17 20:33:19 +09:00
|
|
|
|
"main"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
"Main.main"
|
|
|
|
|
|
};
|
2025-09-21 08:53:00 +09:00
|
|
|
|
// Optional: Mini‑VM stdin loader — when enabled, read entire stdin and pass as argv[0]
|
|
|
|
|
|
let mut cmd = std::process::Command::new(py3);
|
2025-11-02 15:43:43 +09:00
|
|
|
|
crate::runner::child_env::apply_core_wrapper_env(&mut cmd);
|
2025-09-21 08:53:00 +09:00
|
|
|
|
if std::env::var("NYASH_MINIVM_READ_STDIN").ok().as_deref() == Some("1") {
|
|
|
|
|
|
use std::io::Read;
|
|
|
|
|
|
let mut buf = String::new();
|
|
|
|
|
|
let _ = std::io::stdin().read_to_string(&mut buf);
|
|
|
|
|
|
// Wrap as argv JSON array [string]
|
|
|
|
|
|
let arg_json = serde_json::json!([buf]).to_string();
|
|
|
|
|
|
cmd.env("NYASH_SCRIPT_ARGS_JSON", arg_json);
|
|
|
|
|
|
}
|
|
|
|
|
|
let status = cmd
|
2025-09-17 20:33:19 +09:00
|
|
|
|
.args([
|
2025-09-24 21:45:27 +09:00
|
|
|
|
runner_buf.to_string_lossy().as_ref(),
|
2025-09-17 20:33:19 +09:00
|
|
|
|
"--in",
|
|
|
|
|
|
&mir_json_path.display().to_string(),
|
|
|
|
|
|
"--entry",
|
|
|
|
|
|
entry,
|
2025-09-21 08:53:00 +09:00
|
|
|
|
"--args-env",
|
|
|
|
|
|
"NYASH_SCRIPT_ARGS_JSON",
|
2025-09-17 20:33:19 +09:00
|
|
|
|
])
|
|
|
|
|
|
.status()
|
|
|
|
|
|
.map_err(|e| format!("spawn pyvm: {}", e))?;
|
|
|
|
|
|
let code = status.code().unwrap_or(1);
|
|
|
|
|
|
if !status.success() {
|
|
|
|
|
|
crate::cli_v!("❌ PyVM ({}) failed (status={})", tag, code);
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(code)
|
|
|
|
|
|
}
|
2025-09-19 02:07:38 +09:00
|
|
|
|
|
|
|
|
|
|
/// Run PyVM harness over a nyash_rust (lib) MIR module, returning the exit code
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
|
pub fn run_pyvm_harness_lib(module: &nyash_rust::mir::MirModule, tag: &str) -> Result<i32, String> {
|
|
|
|
|
|
let py3 = which::which("python3").map_err(|e| format!("python3 not found: {}", e))?;
|
2025-09-24 21:45:27 +09:00
|
|
|
|
let mut runner_buf = std::path::PathBuf::from("tools/pyvm_runner.py");
|
|
|
|
|
|
if !runner_buf.exists() {
|
|
|
|
|
|
if let Ok(root) = std::env::var("NYASH_ROOT") {
|
|
|
|
|
|
let alt = std::path::Path::new(&root).join("tools/pyvm_runner.py");
|
|
|
|
|
|
if alt.exists() { runner_buf = alt; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if !runner_buf.exists() {
|
|
|
|
|
|
return Err(format!("PyVM runner not found: tools/pyvm_runner.py (cwd) or $NYASH_ROOT/tools/pyvm_runner.py"));
|
2025-09-19 02:07:38 +09:00
|
|
|
|
}
|
|
|
|
|
|
let tmp_dir = std::path::Path::new("tmp");
|
|
|
|
|
|
let _ = std::fs::create_dir_all(tmp_dir);
|
|
|
|
|
|
let mir_json_path = tmp_dir.join("nyash_pyvm_mir.json");
|
|
|
|
|
|
crate::runner::mir_json_emit::emit_mir_json_for_harness(module, &mir_json_path)
|
|
|
|
|
|
.map_err(|e| format!("PyVM MIR JSON emit error: {}", e))?;
|
|
|
|
|
|
crate::cli_v!("[Runner] using PyVM ({} ) → {}", tag, mir_json_path.display());
|
2025-09-21 08:53:00 +09:00
|
|
|
|
// Determine entry function (prefer Main.main; top-level main only if allowed)
|
|
|
|
|
|
let allow_top = crate::config::env::entry_allow_toplevel_main();
|
2025-09-19 02:07:38 +09:00
|
|
|
|
let entry = if module.functions.contains_key("Main.main") {
|
|
|
|
|
|
"Main.main"
|
2025-09-21 08:53:00 +09:00
|
|
|
|
} else if allow_top && module.functions.contains_key("main") {
|
|
|
|
|
|
"main"
|
2025-09-19 02:07:38 +09:00
|
|
|
|
} else if module.functions.contains_key("main") {
|
2025-09-21 08:53:00 +09:00
|
|
|
|
eprintln!("[entry] Warning: using top-level 'main' without explicit allow; set NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 to silence.");
|
2025-09-19 02:07:38 +09:00
|
|
|
|
"main"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
"Main.main"
|
|
|
|
|
|
};
|
2025-09-21 08:53:00 +09:00
|
|
|
|
let mut cmd = std::process::Command::new(py3);
|
2025-11-02 15:43:43 +09:00
|
|
|
|
crate::runner::child_env::apply_core_wrapper_env(&mut cmd);
|
2025-09-21 08:53:00 +09:00
|
|
|
|
if std::env::var("NYASH_MINIVM_READ_STDIN").ok().as_deref() == Some("1") {
|
|
|
|
|
|
use std::io::Read;
|
|
|
|
|
|
let mut buf = String::new();
|
|
|
|
|
|
let _ = std::io::stdin().read_to_string(&mut buf);
|
|
|
|
|
|
let arg_json = serde_json::json!([buf]).to_string();
|
|
|
|
|
|
cmd.env("NYASH_SCRIPT_ARGS_JSON", arg_json);
|
|
|
|
|
|
}
|
|
|
|
|
|
let status = cmd
|
2025-09-19 02:07:38 +09:00
|
|
|
|
.args([
|
2025-09-24 21:45:27 +09:00
|
|
|
|
runner_buf.to_string_lossy().as_ref(),
|
2025-09-19 02:07:38 +09:00
|
|
|
|
"--in",
|
|
|
|
|
|
&mir_json_path.display().to_string(),
|
|
|
|
|
|
"--entry",
|
|
|
|
|
|
entry,
|
2025-09-21 08:53:00 +09:00
|
|
|
|
"--args-env",
|
|
|
|
|
|
"NYASH_SCRIPT_ARGS_JSON",
|
2025-09-19 02:07:38 +09:00
|
|
|
|
])
|
|
|
|
|
|
.status()
|
|
|
|
|
|
.map_err(|e| format!("spawn pyvm: {}", e))?;
|
|
|
|
|
|
let code = status.code().unwrap_or(1);
|
|
|
|
|
|
if !status.success() {
|
|
|
|
|
|
crate::cli_v!("❌ PyVM ({}) failed (status={})", tag, code);
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(code)
|
|
|
|
|
|
}
|