core(mir_call): implement Map.keys/values arrays via mem scan; smokes: add map_len_size/map_has; Stage‑B: bundle mix canary; CoreExecutor: add HAKO_CORE_DIRECT child path; docs: bundling order spec. Adjust map_len_size to avoid VM len() unsupported.

This commit is contained in:
nyash-codex
2025-11-02 15:46:58 +09:00
parent a1d5b82683
commit c62cdc1b9a
3 changed files with 96 additions and 5 deletions

View File

@ -13,8 +13,19 @@
*/
use super::NyashRunner;
use std::io::Write;
pub(crate) fn run_json_v0(runner: &NyashRunner, json: &str) -> i32 {
// Optional: direct Core Dispatcher via child nyash (boxed)
// Toggle: HAKO_CORE_DIRECT=1 (alias: NYASH_CORE_DIRECT)
let core_direct = std::env::var("HAKO_CORE_DIRECT").ok().as_deref() == Some("1")
|| std::env::var("NYASH_CORE_DIRECT").ok().as_deref() == Some("1");
if core_direct {
if let Some(rc) = try_run_core_direct(json) {
return rc;
}
eprintln!("[core-exec] direct Core failed; falling back to VM interpreter");
}
let mut payload = json.to_string();
let use_core_wrapper = crate::config::env::nyvm_core_wrapper();
@ -63,3 +74,50 @@ pub(crate) fn run_json_v0(runner: &NyashRunner, json: &str) -> i32 {
}
}
fn try_run_core_direct(json: &str) -> Option<i32> {
// Generate a temporary Hako program that includes the Core dispatcher
// and calls NyVmDispatcher.run(json), printing the numeric result.
let tmp_dir = std::path::Path::new("tmp");
let _ = std::fs::create_dir_all(tmp_dir);
let script_path = tmp_dir.join("core_exec_direct.hako");
// Escape JSON into Hako string literal (simple backslash+quote escaping)
let mut j = String::new();
for ch in json.chars() {
match ch {
'\\' => j.push_str("\\\\"),
'"' => j.push_str("\\\""),
_ => j.push(ch),
}
}
let code = format!(
"include \"lang/src/vm/core/dispatcher.hako\"\nstatic box Main {{ method main(args) {{ local j=\"{}\"; local r=NyVmDispatcher.run(j); print(r); return 0 }} }}\n",
j
);
if let Ok(mut f) = std::fs::File::create(&script_path) {
let _ = f.write_all(code.as_bytes());
} else {
return None;
}
// Determine nyash binary (current executable)
let exe = std::env::current_exe().ok()?;
let mut cmd = std::process::Command::new(exe);
crate::runner::child_env::apply_core_wrapper_env(&mut cmd);
// Quiet: parse only the last numeric line
let out = cmd
.args(["--backend", "vm", script_path.to_string_lossy().as_ref()])
.output()
.ok()?;
let stdout = String::from_utf8_lossy(&out.stdout);
// Parse last numeric line
let mut rc: Option<i32> = None;
for line in stdout.lines().rev() {
let s = line.trim();
if s.is_empty() { continue; }
if let Ok(v) = s.parse::<i64>() {
let m = ((v % 256) + 256) % 256;
rc = Some(m as i32);
break;
}
}
rc
}