Files
hakorune/lang/src/vm/boxes/flow_debugger.hako

99 lines
3.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// flow_debugger.hako — MiniVM JSON v0 デバッグ用の軽量箱
// 責務:
// - JSON v0 の関数/ブロック/命令を静的に走査し、
// - ブロックID集合の抽出
// - branch/jump の then/else/target が妥当なIDか検証
// - op シーケンスの要約出力(最初の N 件)
// 非責務:
// - 実行・評価(それは MirVmMin に委譲)
using selfhost.shared.common.string_helpers as StringHelpers
static box FlowDebugBox {
// ユーティリティ — 文字列検索
_index_of_from(hay, needle, pos) { if pos < 0 { pos = 0 } local n = hay.length() if pos > n { return -1 } local i = pos local m = needle.length() if m <= 0 { return pos } local limit = n - m loop(i <= limit) { if hay.substring(i, i+m) == needle { return i } i = i + 1 } return -1 }
_read_digits(text, pos) { return StringHelpers.read_digits(text, pos) }
_int_to_str(n) { return StringHelpers.int_to_str(n) }
// ブロックID集合を抽出
collect_block_ids(mjson) {
local ids = new ArrayBox()
local pos = 0
loop(true) {
local p = me._index_of_from(mjson, "\"id\":", pos)
if p < 0 { break }
local d = me._read_digits(mjson, p + 5)
if d != "" { ids.push(d) }
pos = p + 5
}
return ids
}
// op シーケンスを先頭から limit 件だけ抽出
collect_ops(mjson, limit) {
if limit == null { limit = 50 }
local ops = new ArrayBox()
local pos = 0
loop(ops.length() < limit) {
local p = me._index_of_from(mjson, "\"op\":\"", pos)
if p < 0 { break }
local q = me._index_of_from(mjson, "\"", p + 6)
if q < 0 { break }
local op = mjson.substring(p + 6, q)
ops.push(op)
pos = q + 1
}
return ops
}
// branch/jump の then/else/target を抽出し、集合 membership を検査
validate_cf_targets(mjson) {
local ids = me.collect_block_ids(mjson)
// Set 風マップ化
local idset = {}
local i = 0
loop(i < ids.length()) { idset.set(ids.get(i), 1) i = i + 1 }
local errs = new ArrayBox()
local pos = 0
loop(true) {
local p = me._index_of_from(mjson, "\"op\":\"branch\"", pos)
if p < 0 { break }
// then
local pt = me._index_of_from(mjson, "\"then\":", p)
local pe = me._index_of_from(mjson, "\"else\":", p)
if pt >= 0 { local t = me._read_digits(mjson, pt + 7) if t != "" && idset.get(t) == null { errs.push("branch.then invalid:" + t) } }
if pe >= 0 { local e = me._read_digits(mjson, pe + 7) if e != "" && idset.get(e) == null { errs.push("branch.else invalid:" + e) } }
pos = p + 14
}
// jump
pos = 0
loop(true) {
local p = me._index_of_from(mjson, "\"op\":\"jump\"", pos)
if p < 0 { break }
local pt = me._index_of_from(mjson, "\"target\":", p)
if pt >= 0 { local t = me._read_digits(mjson, pt + 9) if t != "" && idset.get(t) == null { errs.push("jump.target invalid:" + t) } }
pos = p + 12
}
// レポート
if errs.length() == 0 { print("{\"kind\":\"flow_debug\",\"ok\":true,\"blocks\":" + (""+ids.length()) + "}") }
else {
local k = 0
loop(k < errs.length()) { print("{\"kind\":\"flow_debug\",\"ok\":false,\"msg\":\"" + errs.get(k) + "\"}") k = k + 1 }
}
return errs.length()
}
// 要約: 先頭の op を列挙
summarize_ops(mjson, limit) {
local ops = me.collect_ops(mjson, limit)
local i = 0
loop(i < ops.length()) { print("{\"kind\":\"flow_ops\",\"op\":\"" + ops.get(i) + "\"}") i = i + 1 }
return ops.length()
}
main(args) { return 0 }
}