From 0364207dffbc101a9c71afcafff42b3d9bce052c Mon Sep 17 00:00:00 2001 From: gamer147 Date: Mon, 6 Jul 2026 13:03:33 -0400 Subject: [PATCH] feat(opcodes): emit drop-in age_opcodes_himegari.py shim; wire --build/--lint Co-Authored-By: Claude Opus 4.8 (1M context) --- tools/opcodes_build.py | 35 +++++++++++++++++++++++++++++++++++ tools/test_opcodes.py | 11 +++++++++++ 2 files changed, 46 insertions(+) diff --git a/tools/opcodes_build.py b/tools/opcodes_build.py index e6b7c1d..51dff1c 100644 --- a/tools/opcodes_build.py +++ b/tools/opcodes_build.py @@ -107,6 +107,21 @@ def bootstrap(toml_path: Path) -> None: f.write("\n".join(blocks)) print(f"bootstrap: {len(used)} used opcodes; appended {len(blocks)} new skeletons -> {toml_path}") +GEN_HEADER = "# DO NOT EDIT -- generated from vm-map/opcodes.toml by tools/opcodes_build.py --build\n" + +def emit_inferred_py(model: M.Model) -> str: + lines = [GEN_HEADER, + '"""Inferred Himegari opcode semantics (generated). sys4load reads INFERRED[op][\'name\']."""', + "from __future__ import annotations", "", "INFERRED: dict[int, dict] = {"] + for op, oc in sorted(model.opcodes.items()): + s = oc.semantics + if not s or s.name == oc.label: # only ops we've given a distinct mnemonic + continue + lines.append(" 0x%x: dict(name=%r, category=%r, noop=%r, confidence=%r, source=%r, summary=%r)," + % (op, s.name, s.category, s.noop_headless, s.confidence, s.source, s.summary)) + lines.append("}") + return "\n".join(lines) + "\n" + def main(argv=None): ap = argparse.ArgumentParser() ap.add_argument("--bootstrap", action="store_true") @@ -118,6 +133,26 @@ def main(argv=None): if args.bootstrap: bootstrap(tp) return 0 + if args.build: + model = M.load(tp) + errors, warnings = M.lint(model) + for m in warnings: + print("warn:", m) + if errors: + for m in errors: + print("error:", m) + return 1 + (paths.REPO / "tools" / "age_opcodes_himegari.py").write_text(emit_inferred_py(model), encoding="utf-8") + print("build: wrote tools/age_opcodes_himegari.py") + return 0 + if args.lint: + errors, warnings = M.lint(M.load(tp)) + for m in warnings: + print("warn:", m) + for m in errors: + print("error:", m) + print(f"lint: {len(errors)} errors, {len(warnings)} warnings") + return 1 if errors else 0 ap.error("no action (expected --bootstrap/--build/--lint)") if __name__ == "__main__": diff --git a/tools/test_opcodes.py b/tools/test_opcodes.py index 5edc2e5..c98d9f3 100644 --- a/tools/test_opcodes.py +++ b/tools/test_opcodes.py @@ -131,10 +131,21 @@ def test_bootstrap(): e, w = M.lint(m) check(e == [], f"bootstrapped file lints clean (errors: {e[:3]})") +def test_emit_inferred(): + import opcodes_build as B + src = B.emit_inferred_py(M.load(write_tmp(FIXTURE))) + check("INFERRED" in src and "hotspot-branch" in src, "shim contains INFERRED + our mnemonic") + ns = {} + exec(compile(src, "", "exec"), ns) + inf = ns["INFERRED"] + check(0x90 in inf and inf[0x90]["name"] == "hotspot-branch", "generated INFERRED[0x90]['name'] correct") + check(0x1f4 in inf, "named marker 0x1f4 (name != label) included") + def main(): test_load() test_lint() test_bootstrap() + test_emit_inferred() print("FAILURES:", len(FAILS)) return 1 if FAILS else 0