diff --git a/lang/src/vm/hakorune-vm/dispatcher_v1.hako b/lang/src/vm/hakorune-vm/dispatcher_v1.hako index 5643d649..78250d1b 100644 --- a/lang/src/vm/hakorune-vm/dispatcher_v1.hako +++ b/lang/src/vm/hakorune-vm/dispatcher_v1.hako @@ -38,8 +38,71 @@ static box NyVmDispatcherV1Box { } return 0 } + // Internal scanner with simple flow: const/compare/mir_call/branch/jump/ret (phi→fallback) + run_scan_flow(json) { + json = "" + json + local regs = new MiniMap() + local last_cmp_dst = -1 + local last_cmp_val = 0 + local bb = 0 + local steps = 0 + local max_steps = 200000 + loop(true) { + steps = steps + 1 + if steps > max_steps { return 0 } + local start = JsonV1ReaderBox.block_insts_start(json, bb) + if start < 0 { return 0 } + local endp = JsonCursorBox.seek_array_end(json, start) + if endp <= start { return 0 } + local seg = (""+json).substring(start + 1, endp) + local scan = 0 + loop(true) { + if scan >= seg.length() { break } + local tup = InstructionScannerBox.next_tuple(seg, scan) + if tup == "" { break } + local c1 = StringOps.index_of_from(tup, ",", 0) + local c2 = StringOps.index_of_from(tup, ",", c1+1) + if c1 < 0 || c2 < 0 { break } + local s = JsonFragBox._str_to_int(tup.substring(0, c1)) + local e = JsonFragBox._str_to_int(tup.substring(c1+1, c2)) + local op = tup.substring(c2+1, tup.length()) + local item = seg.substring(s, e) + if op == "const" { OpHandlersBox.handle_const(item, regs) } + else if op == "compare" { + OpHandlersBox.handle_compare(item, regs) + local dst = JsonFragBox.get_int(item, "dst") + if dst != null { + last_cmp_dst = dst + local sv = regs.getField(""+dst); if sv != null { last_cmp_val = JsonFragBox._str_to_int(""+sv) } else { last_cmp_val = 0 } + } + } + else if op == "mir_call" { MirCallV1HandlerBox.handle(item, regs) } + else if op == "branch" { + local c = JsonFragBox.get_int(item, "cond") + local t = JsonFragBox.get_int(item, "then") + local f = JsonFragBox.get_int(item, "else") + if c != null && t != null && f != null { + local cv = 0 + if c == last_cmp_dst { cv = last_cmp_val } else { local sv = regs.getField(""+c); if sv != null { cv = JsonFragBox._str_to_int(""+sv) } } + bb = (cv != 0) ? t : f + break + } else { return MirVmMin.run_min(json) } + } + else if op == "jump" { + local tgt = JsonFragBox.get_int(item, "target"); if tgt == null { return MirVmMin.run_min(json) } + bb = tgt; break + } + else if op == "phi" { + return MirVmMin.run_min(json) + } + else if op == "ret" { return MirVmMin._handle_ret_op(item, regs, last_cmp_dst, last_cmp_val, 0) } + scan = e + } + } + } // Main entry: Choose internal scanner when enabled; otherwise delegate to Mini‑VM run(json) { + if env.get("HAKO_V1_DISPATCHER_FLOW") == "1" { return me.run_scan_flow(json) } if env.get("HAKO_V1_DISPATCHER_INTERNAL") == "1" { return me.run_scan(json) } return MirVmMin.run_min(json) } diff --git a/lang/src/vm/hakorune-vm/extern_provider.hako b/lang/src/vm/hakorune-vm/extern_provider.hako index c6be9ac7..50414c9b 100644 --- a/lang/src/vm/hakorune-vm/extern_provider.hako +++ b/lang/src/vm/hakorune-vm/extern_provider.hako @@ -17,6 +17,14 @@ static box HakoruneExternProviderBox { print("" + args) return 0 } + if name == "env.mirbuilder.emit" { + // Stub only (20.38でC‑ABI接続): return empty string + return "" + } + if name == "env.codegen.emit_object" { + // Stub only: return empty string (path placeholder) + return "" + } // Unknown: return null for now (caller decides Fail‑Fast) return null } diff --git a/tools/smokes/v2/profiles/quick/core/phase2037/v1_mircall_parity_hakovm_minivm_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2037/v1_mircall_parity_hakovm_minivm_vm.sh new file mode 100644 index 00000000..e5dd4405 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2037/v1_mircall_parity_hakovm_minivm_vm.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Parity: MirCallV1Handler used by Mini‑VM and Hakovm dispatcher produce same rc +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2 + +tmp_json="/tmp/mir_v1_parity_mircall_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[{"id":0,"instructions":[ + {"op":"mir_call","dst":0, "callee":{"type":"Constructor","box_type":"ArrayBox"}, "args":[], "effects":[]}, + {"op":"const","dst":1, "value": {"type": "i64", "value": 10}}, + {"op":"const","dst":2, "value": {"type": "i64", "value": 20}}, + {"op":"mir_call", "callee":{"type":"Method","box_name":"ArrayBox","method":"push","receiver":0}, "args":[1], "effects":[]}, + {"op":"mir_call", "callee":{"type":"Method","box_name":"ArrayBox","method":"push","receiver":0}, "args":[2], "effects":[]}, + {"op":"mir_call","dst":3, "callee":{"type":"Method","box_name":"ArrayBox","method":"size","receiver":0}, "args":[], "effects":[]}, + {"op":"ret","value":3} + ]}]} + ] +} +JSON + +set +e +# Mini‑VM path +rc_min=0; HAKO_VERIFY_PRIMARY=hakovm HAKO_V1_DISPATCHER_INTERNAL=0 HAKO_V1_DISPATCHER_FLOW=0 verify_mir_rc "$tmp_json" >/dev/null 2>&1; rc_min=$? +# Hakovm internal flow path +rc_hv1=0; HAKO_VERIFY_PRIMARY=hakovm HAKO_V1_DISPATCHER_FLOW=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1; rc_hv1=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc_min" -eq "$rc_hv1" ]; then + echo "[PASS] v1_mircall_parity_hakovm_minivm_vm (rc=$rc_hv1)" + exit 0 +fi +echo "[FAIL] v1_mircall_parity_hakovm_minivm_vm (mini=$rc_min, hv1=$rc_hv1)" >&2; exit 1 +