68 lines
3.2 KiB
Plaintext
68 lines
3.2 KiB
Plaintext
// 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 }
|
||
}
|