Phase 20.12b: quick green + structural cleanup

- Deprecations: add warn-once for nyash.toml (runtime::deprecations); apply in plugin loader v2 (singletons/method_resolver)
- Child env + runner hygiene: unify Stage‑3/quiet/disable-fallback env in test/runner; expand LLVM noise filters
- Docs/branding: prefer  and hako.toml in README.md/README.ja.md and smokes README
- VM: implement Map.clear in MIR interpreter (boxes_map)
- Stage‑B: gate bundle/alias/require smokes behind SMOKES_ENABLE_STAGEB; fix include cwd and resolve() call even for require-only cases
- Core‑Direct: gate rc boundary canary behind SMOKES_ENABLE_CORE_DIRECT
- Smokes: inject Stage‑3 and disable selfhost fallback for LLVM runs; filter using/* logs
- Quick profile: 168/168 PASS locally

This commit accelerates Phase 20.33 (80/20) by stabilizing quick suite, reducing noise, and gating heavy/experimental paths for speed.
This commit is contained in:
nyash-codex
2025-11-02 17:50:06 +09:00
parent 0cd2342b05
commit dd6876e1c6
46 changed files with 323 additions and 209 deletions

View File

@ -21,38 +21,38 @@ pub(crate) fn run_json_v0(runner: &NyashRunner, json: &str) -> i32 {
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;
// Only attempt Hako Core dispatcher when payload already looks like MIR(JSON v0)
// i.e., has functions/blocks keys. StageB Program(JSON v0) must go through bridge first.
let looks_like_mir = json.contains("\"functions\"") && json.contains("\"blocks\"");
if looks_like_mir {
if let Some(rc) = try_run_core_direct(json) { return rc; }
eprintln!("[core-exec] direct Core failed; falling back to VM interpreter");
}
eprintln!("[core-exec] direct Core failed; falling back to VM interpreter");
// else: skip direct Core and continue to bridge/VM path
}
let mut payload = json.to_string();
let use_core_wrapper = crate::config::env::nyvm_core_wrapper();
let use_downconvert = crate::config::env::nyvm_v1_downconvert();
if use_core_wrapper || use_downconvert {
// Best-effort canonicalize
if let Ok(j) = crate::runner::modes::common_util::core_bridge::canonicalize_module_json(&payload) {
payload = j;
}
match crate::runner::json_v1_bridge::try_parse_v1_to_module(&payload) {
Ok(Some(module)) => {
super::json_v0_bridge::maybe_dump_mir(&module);
// OOB strict: reset observation flag
crate::runner::child_env::pre_run_reset_oob_if_strict();
let rc = runner.execute_mir_module_quiet_exit(&module);
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() {
eprintln!("[gate-c][oob-strict] Out-of-bounds observed → exit(1)");
return 1;
}
return rc;
}
Ok(None) => { /* fall through to v0 */ }
Err(e) => {
eprintln!("❌ JSON v1 bridge error: {}", e);
// Always try the v1 bridge first (StageB Program JSON → MIR module).
// This is noop when input is already MIR(JSON v0) with functions/blocks.
if let Ok(j) = crate::runner::modes::common_util::core_bridge::canonicalize_module_json(&payload) {
payload = j;
}
match crate::runner::json_v1_bridge::try_parse_v1_to_module(&payload) {
Ok(Some(module)) => {
super::json_v0_bridge::maybe_dump_mir(&module);
// OOB strict: reset observation flag
crate::runner::child_env::pre_run_reset_oob_if_strict();
let rc = runner.execute_mir_module_quiet_exit(&module);
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() {
eprintln!("[gate-c][oob-strict] Out-of-bounds observed → exit(1)");
return 1;
}
return rc;
}
Ok(None) => { /* fall through to v0 parse/execute */ }
Err(e) => {
eprintln!("❌ JSON v1 bridge error: {}", e);
return 1;
}
}
@ -90,7 +90,7 @@ fn try_run_core_direct(json: &str) -> Option<i32> {
}
}
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",
"include \"lang/src/vm/core/dispatcher.hako\"\nstatic box Main {{ method main(args) {{ local j=\"{}\"; local r=NyVmDispatcher.run(j); return r }} }}\n",
j
);
if let Ok(mut f) = std::fs::File::create(&script_path) {
@ -102,22 +102,13 @@ fn try_run_core_direct(json: &str) -> Option<i32> {
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;
}
if !out.stdout.is_empty() {
let _ = std::io::stdout().write_all(&out.stdout);
}
if let Some(code) = rc { Some(code) } else { Some(1) }
let rc = out.status.code().unwrap_or(1);
Some(rc)
}