// step_runner.hako — Mini‑VM JSON v0 ステップ観測用の軽量箱(実行はしない) using selfhost.vm.boxes.compare_ops as CompareOpsBox using selfhost.shared.json.core.json_cursor as JsonCursorBox static box StepRunnerBox { // 文字列ヘルパ // 文字列ヘルパ(JsonCursorBox に委譲) _index_of_from(hay, needle, pos) { return JsonCursorBox.index_of_from(hay, needle, pos) } // Delegate digit scanning to JsonCursorBox for consistency _read_digits(text, pos) { return JsonCursorBox.digits_from(text, pos) } _int(s) { local t = "" + s if t == "" { return 0 } local i = 0 local neg = 0 if t.substring(0,1) == "-" { neg = 1 i = 1 } local acc = 0 loop(i < t.length()) { local ch = t.substring(i, i+1) if ch < "0" || ch > "9" { break } acc = acc * 10 + (ch == "0" ? 0 : ch == "1" ? 1 : ch == "2" ? 2 : ch == "3" ? 3 : ch == "4" ? 4 : ch == "5" ? 5 : ch == "6" ? 6 : ch == "7" ? 7 : ch == "8" ? 8 : 9) i = i + 1 } if neg == 1 { acc = 0 - acc } return acc } // block 0 の instructions セグメント抽出 _block0_segment(mjson) { local key = "\"instructions\":[" local k = me._index_of_from(mjson, key, 0) if k < 0 { return "" } local lb = k + key.length() - 1 // Delegate to JsonScanBox for robust end detection (escape-aware) local rb = JsonCursorBox.seek_array_end(mjson, lb) if rb < 0 { return "" } return mjson.substring(lb + 1, rb) } // compare の (lhs,rhs,kind,dst) を抽出 parse_compare(seg) { local p = JsonCursorBox.index_of_from(seg, "\"op\":\"compare\"", 0) if p < 0 { return {} } local lhs = me._int(me._read_digits(seg, JsonCursorBox.index_of_from(seg, "\"lhs\":", p) + 6)) local rhs = me._int(me._read_digits(seg, JsonCursorBox.index_of_from(seg, "\"rhs\":", p) + 6)) local dst = me._int(me._read_digits(seg, JsonCursorBox.index_of_from(seg, "\"dst\":", p) + 6)) // kind local kpos = JsonCursorBox.index_of_from(seg, "\"cmp\":\"", p) local kend = me._index_of_from(seg, "\"", kpos + 6) local kind = seg.substring(kpos + 6, kend) return { lhs: lhs, rhs: rhs, dst: dst, kind: kind } } // branch の cond/then/else を抽出 parse_branch(seg) { local p = JsonCursorBox.index_of_from(seg, "\"op\":\"branch\"", 0) if p < 0 { return {} } local cond = me._int(me._read_digits(seg, JsonCursorBox.index_of_from(seg, "\"cond\":", p) + 7)) local then_id = me._int(me._read_digits(seg, JsonCursorBox.index_of_from(seg, "\"then\":", p) + 7)) local else_id = me._int(me._read_digits(seg, JsonCursorBox.index_of_from(seg, "\"else\":", p) + 7)) return { cond: cond, then: then_id, else: else_id } } // compare を評価し cond==dst のときに bool を返す eval_branch_bool(mjson) { local seg = me._block0_segment(mjson) if seg == "" { return 0 } local cmp = me.parse_compare(seg) local br = me.parse_branch(seg) if cmp.get == null || br.get == null { return 0 } local kind = "" + cmp.get("kind") local lhs = cmp.get("lhs") local rhs = cmp.get("rhs") local dst = cmp.get("dst") local cond = br.get("cond") if cond != dst { return 0 } // 最小仕様: cond は直前 compare の dst local r = CompareOpsBox.eval(kind, lhs, rhs) return r } main(args) { return 0 } }