2025-09-23 01:23:16 +09:00
|
|
|
|
using selfhost.common.mini_vm_scan as MiniVmScan
|
|
|
|
|
|
using selfhost.common.mini_vm_binop as MiniVmBinOp
|
|
|
|
|
|
using selfhost.common.mini_vm_compare as MiniVmCompare
|
2025-09-22 07:54:25 +09:00
|
|
|
|
// Use the JSON adapter facade for cursor ops (next_non_ws, digits)
|
2025-09-23 01:23:16 +09:00
|
|
|
|
using selfhost.vm.boxes.json_cur as MiniJsonLoader
|
2025-09-22 07:54:25 +09:00
|
|
|
|
|
|
|
|
|
|
static box MiniVmPrints {
|
|
|
|
|
|
// dev trace flag (0=OFF)
|
|
|
|
|
|
_trace_enabled() { return 0 }
|
|
|
|
|
|
// fallback toggle for legacy heuristics (0=OFF, 1=ON)
|
|
|
|
|
|
_fallback_enabled() { return 0 }
|
|
|
|
|
|
// literal string within Print
|
|
|
|
|
|
try_print_string_value_at(json, end, print_pos) {
|
|
|
|
|
|
local scan = new MiniVmScan()
|
|
|
|
|
|
local k_val = "\"value\":\""
|
|
|
|
|
|
local s = scan.index_of_from(json, k_val, print_pos)
|
|
|
|
|
|
if s < 0 || s >= end { return -1 }
|
|
|
|
|
|
local i = s + k_val.length()
|
|
|
|
|
|
local j = scan.index_of_from(json, "\"", i)
|
|
|
|
|
|
if j <= 0 || j > end { return -1 }
|
|
|
|
|
|
print(json.substring(i, j))
|
|
|
|
|
|
return j + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// literal int within Print (typed)
|
|
|
|
|
|
try_print_int_value_at(json, end, print_pos) {
|
|
|
|
|
|
local scan = new MiniVmScan()
|
|
|
|
|
|
local k_expr = "\"expression\":{"
|
|
|
|
|
|
local epos = scan.index_of_from(json, k_expr, print_pos)
|
|
|
|
|
|
if epos <= 0 || epos >= end { return -1 }
|
|
|
|
|
|
local obj_start = scan.index_of_from(json, "{", epos)
|
|
|
|
|
|
if obj_start <= 0 || obj_start >= end { return -1 }
|
|
|
|
|
|
local obj_end = scan.find_balanced_object_end(json, obj_start)
|
|
|
|
|
|
if obj_end <= 0 || obj_end > end { return -1 }
|
|
|
|
|
|
// robust: look for explicit int type within expression object
|
|
|
|
|
|
local k_tint = "\"type\":\"int\""
|
|
|
|
|
|
local tpos = scan.index_of_from(json, k_tint, obj_start)
|
|
|
|
|
|
if tpos <= 0 || tpos >= obj_end { return -1 }
|
|
|
|
|
|
local k_val2 = "\"value\":"
|
|
|
|
|
|
local v2 = scan.index_of_from(json, k_val2, tpos)
|
|
|
|
|
|
if v2 <= 0 || v2 >= obj_end { return -1 }
|
|
|
|
|
|
local digits = scan.read_digits(json, v2 + k_val2.length())
|
|
|
|
|
|
if digits == "" { return -1 }
|
|
|
|
|
|
print(digits)
|
|
|
|
|
|
return obj_end + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// minimal FunctionCall printer for echo/itoa
|
|
|
|
|
|
try_print_functioncall_at(json, end, print_pos) {
|
|
|
|
|
|
local scan = new MiniVmScan()
|
|
|
|
|
|
local k_fc = "\"kind\":\"FunctionCall\""
|
|
|
|
|
|
local fcp = scan.index_of_from(json, k_fc, print_pos)
|
|
|
|
|
|
if fcp <= 0 || fcp >= end { return -1 }
|
|
|
|
|
|
local k_name = "\"name\":\""
|
|
|
|
|
|
local npos = scan.index_of_from(json, k_name, fcp)
|
|
|
|
|
|
if npos <= 0 || npos >= end { return -1 }
|
|
|
|
|
|
local ni = npos + k_name.length()
|
|
|
|
|
|
local nj = scan.index_of_from(json, "\"", ni)
|
|
|
|
|
|
if nj <= 0 || nj > end { return -1 }
|
|
|
|
|
|
local fname = json.substring(ni, nj)
|
|
|
|
|
|
local k_args = "\"arguments\":["
|
|
|
|
|
|
local apos = scan.index_of_from(json, k_args, nj)
|
|
|
|
|
|
if apos <= 0 || apos >= end { return -1 }
|
|
|
|
|
|
local arr_start = scan.index_of_from(json, "[", apos)
|
|
|
|
|
|
local arr_end = scan.find_balanced_array_end(json, arr_start)
|
|
|
|
|
|
if arr_start <= 0 || arr_end <= 0 || arr_end > end { return -1 }
|
|
|
|
|
|
// handle empty args []
|
|
|
|
|
|
local nn = new MiniJsonLoader().next_non_ws(json, arr_start+1)
|
|
|
|
|
|
if nn > 0 && nn <= arr_end {
|
|
|
|
|
|
if json.substring(nn, nn+1) == "]" {
|
|
|
|
|
|
if fname == "echo" { print("") return arr_end + 1 }
|
|
|
|
|
|
if fname == "itoa" { print("0") return arr_end + 1 }
|
|
|
|
|
|
return -1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// first arg type
|
|
|
|
|
|
local k_t = "\"type\":\""
|
|
|
|
|
|
local atpos = scan.index_of_from(json, k_t, arr_start)
|
|
|
|
|
|
if atpos <= 0 || atpos >= arr_end {
|
|
|
|
|
|
if fname == "echo" { print("") return arr_end + 1 }
|
|
|
|
|
|
if fname == "itoa" { print("0") return arr_end + 1 }
|
|
|
|
|
|
return -1
|
|
|
|
|
|
}
|
|
|
|
|
|
atpos = atpos + k_t.length()
|
|
|
|
|
|
local at_end = scan.index_of_from(json, "\"", atpos)
|
|
|
|
|
|
if at_end <= 0 || at_end > arr_end { return -1 }
|
|
|
|
|
|
local aty = json.substring(atpos, at_end)
|
|
|
|
|
|
if aty == "string" {
|
|
|
|
|
|
local k_sval = "\"value\":\""
|
|
|
|
|
|
local svalp = scan.index_of_from(json, k_sval, at_end)
|
|
|
|
|
|
if svalp <= 0 || svalp >= arr_end { return -1 }
|
|
|
|
|
|
local si = svalp + k_sval.length()
|
|
|
|
|
|
local sj = scan.index_of_from(json, "\"", si)
|
|
|
|
|
|
if sj <= 0 || sj > arr_end { return -1 }
|
|
|
|
|
|
local sval = json.substring(si, sj)
|
|
|
|
|
|
if fname == "echo" { print(sval) return sj + 1 }
|
|
|
|
|
|
return -1
|
|
|
|
|
|
}
|
|
|
|
|
|
if aty == "int" || aty == "i64" || aty == "integer" {
|
|
|
|
|
|
local k_ival = "\"value\":"
|
|
|
|
|
|
local ivalp = scan.index_of_from(json, k_ival, at_end)
|
|
|
|
|
|
if ivalp <= 0 || ivalp >= arr_end { return -1 }
|
|
|
|
|
|
local digits = scan.read_digits(json, ivalp + k_ival.length())
|
|
|
|
|
|
if fname == "itoa" || fname == "echo" { print(digits) return ivalp + k_ival.length() }
|
|
|
|
|
|
return -1
|
|
|
|
|
|
}
|
|
|
|
|
|
return -1
|
|
|
|
|
|
}
|
|
|
|
|
|
// Print all Print-Literal values within [start,end]
|
|
|
|
|
|
print_prints_in_slice(json, start, end) {
|
|
|
|
|
|
// Preferred route: JSON Box (plugin) – robust and structure-aware
|
|
|
|
|
|
// If plugin is available, parse and traverse Program.statements and print.
|
|
|
|
|
|
// Fall back to text scanner when plugin is unavailable or parse fails.
|
|
|
|
|
|
{
|
|
|
|
|
|
// Attempt plugin route in a guarded block
|
|
|
|
|
|
@printed = 0
|
|
|
|
|
|
@ok = 0
|
2025-09-22 09:32:54 +09:00
|
|
|
|
@dbg = _trace_enabled()
|
2025-09-22 07:54:25 +09:00
|
|
|
|
// new JsonDocBox()/JsonNodeBox are provided by the JSON plugin
|
|
|
|
|
|
@doc = new JsonDocBox()
|
|
|
|
|
|
doc.parse(json)
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 {
|
|
|
|
|
|
@perr = doc.error()
|
|
|
|
|
|
if perr == "" { print("[json] parse ok") } else { print("[json] parse err=" + perr) }
|
|
|
|
|
|
}
|
2025-09-22 07:54:25 +09:00
|
|
|
|
@root = doc.root()
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 {
|
|
|
|
|
|
@rkind = root.kind()
|
|
|
|
|
|
print("[json] root.kind=" + rkind)
|
|
|
|
|
|
}
|
2025-09-22 07:54:25 +09:00
|
|
|
|
if root {
|
|
|
|
|
|
@stmts = root.get("statements")
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 {
|
|
|
|
|
|
@skind = stmts.kind()
|
|
|
|
|
|
@ssize = stmts.size()
|
|
|
|
|
|
print("[json] stmts.kind=" + skind + " size=" + new MiniVmScan()._int_to_str(ssize))
|
|
|
|
|
|
}
|
2025-09-22 07:54:25 +09:00
|
|
|
|
if stmts {
|
|
|
|
|
|
@n = stmts.size()
|
|
|
|
|
|
@i = 0
|
|
|
|
|
|
loop (i < n) {
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 {
|
|
|
|
|
|
print("[json] loop i=" + new MiniVmScan()._int_to_str(i) + "/" + new MiniVmScan()._int_to_str(n))
|
|
|
|
|
|
if i > 1000 { print("[json] debug guard: break loop at i>1000") break }
|
|
|
|
|
|
}
|
2025-09-22 07:54:25 +09:00
|
|
|
|
@node = stmts.at(i)
|
|
|
|
|
|
if !node { i = i + 1 continue }
|
|
|
|
|
|
@expr = node.get("expression")
|
|
|
|
|
|
if !expr { i = i + 1 continue }
|
|
|
|
|
|
@k = expr.get("kind").str()
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 { print("[json] expr.kind=" + k) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
if k == "Literal" {
|
|
|
|
|
|
@val = expr.get("value")
|
|
|
|
|
|
if val {
|
|
|
|
|
|
@ty = val.get("type").str()
|
|
|
|
|
|
if ty == "string" { print(val.get("value").str()) } else { print(val.get("value").int()) }
|
|
|
|
|
|
}
|
2025-09-22 09:32:54 +09:00
|
|
|
|
printed = printed + 1
|
2025-09-22 07:54:25 +09:00
|
|
|
|
i = i + 1
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if k == "FunctionCall" {
|
|
|
|
|
|
@name = expr.get("name").str()
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 { print("[json] func name=" + name) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
@args = expr.get("arguments")
|
|
|
|
|
|
if !args { i = i + 1 continue }
|
|
|
|
|
|
@asz = args.size()
|
|
|
|
|
|
if asz <= 0 {
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if name == "echo" { print("") }
|
|
|
|
|
|
if name == "itoa" { print("0") }
|
|
|
|
|
|
printed = printed + 1
|
2025-09-22 07:54:25 +09:00
|
|
|
|
i = i + 1
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
@arg0v = args.at(0).get("value")
|
|
|
|
|
|
if name == "echo" {
|
|
|
|
|
|
if arg0v {
|
|
|
|
|
|
@t = arg0v.get("type").str()
|
|
|
|
|
|
if t == "string" { print(arg0v.get("value").str()) } else { print(arg0v.get("value").int()) }
|
|
|
|
|
|
}
|
2025-09-22 09:32:54 +09:00
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
if dbg == 1 { print("[json] before inc i=" + new MiniVmScan()._int_to_str(i)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
i = i + 1
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 { print("[json] after inc i=" + new MiniVmScan()._int_to_str(i)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if name == "itoa" {
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if arg0v { print(arg0v.get("value").int()) }
|
|
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
if dbg == 1 { print("[json] before inc i=" + new MiniVmScan()._int_to_str(i)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
i = i + 1
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 { print("[json] after inc i=" + new MiniVmScan()._int_to_str(i)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
2025-09-22 09:32:54 +09:00
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
if dbg == 1 { print("[json] before inc i=" + new MiniVmScan()._int_to_str(i)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
i = i + 1
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 { print("[json] after inc i=" + new MiniVmScan()._int_to_str(i)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if k == "Compare" {
|
|
|
|
|
|
@op = expr.get("operation").str()
|
|
|
|
|
|
@lhs = expr.get("lhs").get("value").get("value").int()
|
|
|
|
|
|
@rhs = expr.get("rhs").get("value").get("value").int()
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if op == "<" { if lhs < rhs { print(1) } else { print(0) } }
|
|
|
|
|
|
if op == "==" { if lhs == rhs { print(1) } else { print(0) } }
|
|
|
|
|
|
if op == "<=" { if lhs <= rhs { print(1) } else { print(0) } }
|
|
|
|
|
|
if op == ">" { if lhs > rhs { print(1) } else { print(0) } }
|
|
|
|
|
|
if op == ">=" { if lhs >= rhs { print(1) } else { print(0) } }
|
|
|
|
|
|
if op == "!=" { if lhs != rhs { print(1) } else { print(0) } }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
i = i + 1
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if k == "BinaryOp" {
|
|
|
|
|
|
@op = expr.get("operator").str()
|
|
|
|
|
|
if op == "+" {
|
|
|
|
|
|
@left = expr.get("left").get("value").get("value").int()
|
|
|
|
|
|
@right = expr.get("right").get("value").get("value").int()
|
|
|
|
|
|
print(left + right)
|
|
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
i = i + 1
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-22 09:32:54 +09:00
|
|
|
|
// Unknown expression kind: treat as a no-op; do not count
|
2025-09-22 07:54:25 +09:00
|
|
|
|
i = i + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
ok = 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Prefer plugin result whenever JSON route ran (ok==1). Even if printed==0,
|
|
|
|
|
|
// return early to avoid falling back to the heuristic scanner which can loop
|
|
|
|
|
|
// on malformed inputs or seam-edge cases.
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if dbg == 1 { print("[json] plugin_ok=" + new MiniVmScan()._int_to_str(ok) + " printed=" + new MiniVmScan()._int_to_str(printed)) }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
if ok == 1 { return printed }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Fallback: text scanner(開発用)
|
2025-09-22 09:32:54 +09:00
|
|
|
|
if _trace_enabled() == 1 { print("[json] fallback engaged") }
|
2025-09-22 07:54:25 +09:00
|
|
|
|
local scan = new MiniVmScan()
|
|
|
|
|
|
local bin = new MiniVmBinOp()
|
|
|
|
|
|
local cmp = new MiniVmCompare()
|
|
|
|
|
|
local pos = start
|
|
|
|
|
|
local printed = 0
|
|
|
|
|
|
local guard = 0
|
|
|
|
|
|
loop (true) {
|
|
|
|
|
|
guard = guard + 1
|
|
|
|
|
|
if guard > 200 { break }
|
|
|
|
|
|
local k_print = "\"kind\":\"Print\""
|
|
|
|
|
|
local p = scan.index_of_from(json, k_print, pos)
|
|
|
|
|
|
if p < 0 || p > end { break }
|
|
|
|
|
|
// bound current Print object (coarse): use next Print marker as slice end to avoid deep brace scan
|
|
|
|
|
|
local p_obj_start = scan.index_of_from(json, "{", p)
|
|
|
|
|
|
// coarse slice end by next Print marker
|
|
|
|
|
|
local next_p = scan.index_of_from(json, k_print, p + k_print.length())
|
|
|
|
|
|
local p_slice_end = end
|
|
|
|
|
|
if next_p > 0 { p_slice_end = next_p }
|
|
|
|
|
|
// avoid heavy find_balanced_object_end; use coarse p_slice_end-1 as object end
|
|
|
|
|
|
local p_obj_end = p_slice_end - 1
|
|
|
|
|
|
if p_obj_start <= 0 { p_obj_end = p + k_print.length() }
|
|
|
|
|
|
// Fast path: handle within [p, p_slice_end) without deep brace scans
|
|
|
|
|
|
{
|
|
|
|
|
|
local did = 0
|
|
|
|
|
|
// FunctionCall echo/itoa
|
|
|
|
|
|
local k_fc = "\"kind\":\"FunctionCall\""
|
|
|
|
|
|
local fcp = scan.index_of_from(json, k_fc, p)
|
|
|
|
|
|
if fcp > 0 { if fcp < p_slice_end {
|
|
|
|
|
|
local k_name = "\"name\":\""
|
|
|
|
|
|
local npos = scan.index_of_from(json, k_name, fcp)
|
|
|
|
|
|
if npos > 0 { if npos < p_slice_end {
|
|
|
|
|
|
local ni = npos + k_name.length()
|
|
|
|
|
|
local nj = scan.index_of_from(json, "\"", ni)
|
|
|
|
|
|
if nj > 0 { if nj <= p_slice_end {
|
|
|
|
|
|
local fname = json.substring(ni, nj)
|
|
|
|
|
|
local k_args = "\"arguments\":["
|
|
|
|
|
|
local apos = scan.index_of_from(json, k_args, nj)
|
|
|
|
|
|
if apos > 0 { if apos < p_slice_end {
|
|
|
|
|
|
// quick value-based parse first (avoid type walk)
|
|
|
|
|
|
{
|
|
|
|
|
|
local k_sval = "\"value\":\""
|
|
|
|
|
|
local vs = scan.index_of_from(json, k_sval, apos)
|
|
|
|
|
|
if vs > 0 { if vs < p_slice_end {
|
|
|
|
|
|
local si = vs + k_sval.length()
|
|
|
|
|
|
local sj = scan.index_of_from(json, "\"", si)
|
|
|
|
|
|
if sj > 0 { if sj <= p_slice_end {
|
|
|
|
|
|
local sval = json.substring(si, sj)
|
|
|
|
|
|
if fname == "echo" { print(sval) printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
local k_ival = "\"value\":"
|
|
|
|
|
|
local vi = scan.index_of_from(json, k_ival, apos)
|
|
|
|
|
|
if vi > 0 { if vi < p_slice_end {
|
|
|
|
|
|
local digits = scan.read_digits(json, vi + k_ival.length())
|
|
|
|
|
|
if digits != "" { if fname == "itoa" || fname == "echo" { print(digits) printed = printed + 1 did = 1 pos = p_slice_end continue } }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
// empty args
|
|
|
|
|
|
local nwn = new MiniJsonLoader().next_non_ws(json, apos + k_args.length())
|
|
|
|
|
|
if nwn == apos + k_args.length() {
|
|
|
|
|
|
if fname == "echo" { print("") printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
if fname == "itoa" { print("0") printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
}
|
|
|
|
|
|
local k_t = "\"type\":\""
|
|
|
|
|
|
local atpos = scan.index_of_from(json, k_t, apos)
|
|
|
|
|
|
if atpos > 0 { if atpos < p_slice_end {
|
|
|
|
|
|
local ati = atpos + k_t.length()
|
|
|
|
|
|
local atj = scan.index_of_from(json, "\"", ati)
|
|
|
|
|
|
if atj > 0 { if atj <= p_slice_end {
|
|
|
|
|
|
local aty = json.substring(ati, atj)
|
|
|
|
|
|
if aty == "string" {
|
|
|
|
|
|
local k_sval = "\"value\":\""
|
|
|
|
|
|
local svalp = scan.index_of_from(json, k_sval, atj)
|
|
|
|
|
|
if svalp > 0 { if svalp < p_slice_end {
|
|
|
|
|
|
local si = svalp + k_sval.length()
|
|
|
|
|
|
local sj = scan.index_of_from(json, "\"", si)
|
|
|
|
|
|
if sj > 0 { if sj <= p_slice_end {
|
|
|
|
|
|
local sval = json.substring(si, sj)
|
|
|
|
|
|
if fname == "echo" { print(sval) printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
if aty == "int" || aty == "i64" || aty == "integer" {
|
|
|
|
|
|
local k_ival = "\"value\":"
|
|
|
|
|
|
local ivalp = scan.index_of_from(json, k_ival, atj)
|
|
|
|
|
|
if ivalp > 0 { if ivalp < p_slice_end {
|
|
|
|
|
|
local digits = scan.read_digits(json, ivalp + k_ival.length())
|
|
|
|
|
|
if fname == "itoa" || fname == "echo" { print(digits) printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
// Compare within slice
|
|
|
|
|
|
local k_cp = "\"kind\":\"Compare\""
|
|
|
|
|
|
local cpos = scan.index_of_from(json, k_cp, p)
|
|
|
|
|
|
if cpos > 0 { if cpos < p_slice_end {
|
|
|
|
|
|
local k_op = "\"operation\":\""
|
|
|
|
|
|
local opos = scan.index_of_from(json, k_op, cpos)
|
|
|
|
|
|
if opos > 0 { if opos < p_slice_end {
|
|
|
|
|
|
local oi = opos + k_op.length()
|
|
|
|
|
|
local oj = scan.index_of_from(json, "\"", oi)
|
|
|
|
|
|
if oj > 0 { if oj <= p_slice_end {
|
|
|
|
|
|
local op = json.substring(oi, oj)
|
|
|
|
|
|
local k_lhs = "\"lhs\":{\"kind\":\"Literal\""
|
|
|
|
|
|
local hl = scan.index_of_from(json, k_lhs, oj)
|
|
|
|
|
|
if hl > 0 { if hl < p_slice_end {
|
|
|
|
|
|
local k_v = "\"value\":"
|
|
|
|
|
|
local hv = scan.index_of_from(json, k_v, hl)
|
|
|
|
|
|
if hv > 0 { if hv < p_slice_end {
|
|
|
|
|
|
local a = scan.read_digits(json, hv + k_v.length())
|
|
|
|
|
|
local k_rhs = "\"rhs\":{\"kind\":\"Literal\""
|
|
|
|
|
|
local hr = scan.index_of_from(json, k_rhs, hl)
|
|
|
|
|
|
if hr > 0 { if hr < p_slice_end {
|
|
|
|
|
|
local rv = scan.index_of_from(json, k_v, hr)
|
|
|
|
|
|
if rv > 0 { if rv < p_slice_end {
|
|
|
|
|
|
local b = scan.read_digits(json, rv + k_v.length())
|
|
|
|
|
|
if a && b {
|
|
|
|
|
|
local ai = scan._str_to_int(a)
|
|
|
|
|
|
local bi = scan._str_to_int(b)
|
|
|
|
|
|
local res = 0
|
|
|
|
|
|
if op == "<" { if ai < bi { res = 1 } }
|
|
|
|
|
|
if op == "==" { if ai == bi { res = 1 } }
|
|
|
|
|
|
if op == "<=" { if ai <= bi { res = 1 } }
|
|
|
|
|
|
if op == ">" { if ai > bi { res = 1 } }
|
|
|
|
|
|
if op == ">=" { if ai >= bi { res = 1 } }
|
|
|
|
|
|
if op == "!=" { if ai != bi { res = 1 } }
|
|
|
|
|
|
print(res)
|
|
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
did = 1
|
|
|
|
|
|
pos = p_slice_end
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
// BinaryOp '+' (typed ints) within slice
|
|
|
|
|
|
if scan.index_of_from(json, "\"kind\":\"BinaryOp\"", p) > 0 { if scan.index_of_from(json, "\"operator\":\"+\"", p) > 0 {
|
|
|
|
|
|
local k_lint = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
|
|
|
|
|
|
local k_rint = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
|
|
|
|
|
|
local lp = scan.index_of_from(json, k_lint, p)
|
|
|
|
|
|
if lp > 0 { if lp < p_slice_end {
|
|
|
|
|
|
local ld = scan.read_digits(json, lp + k_lint.length())
|
|
|
|
|
|
if ld != "" {
|
|
|
|
|
|
local rp = scan.index_of_from(json, k_rint, lp + k_lint.length())
|
|
|
|
|
|
if rp > 0 { if rp < p_slice_end {
|
|
|
|
|
|
local rd = scan.read_digits(json, rp + k_rint.length())
|
|
|
|
|
|
if rd != "" { print(new MiniVmScan()._int_to_str(new MiniVmScan()._str_to_int(ld) + new MiniVmScan()._str_to_int(rd))) printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
// Literal string within slice
|
|
|
|
|
|
{
|
|
|
|
|
|
local k_val = "\"value\":\""
|
|
|
|
|
|
local s = scan.index_of_from(json, k_val, p)
|
|
|
|
|
|
if s > 0 { if s < p_slice_end {
|
|
|
|
|
|
local i = s + k_val.length()
|
|
|
|
|
|
local j = scan.index_of_from(json, "\"", i)
|
|
|
|
|
|
if j > 0 { if j <= p_slice_end {
|
|
|
|
|
|
print(json.substring(i, j))
|
|
|
|
|
|
printed = printed + 1
|
|
|
|
|
|
did = 1
|
|
|
|
|
|
pos = p_slice_end
|
|
|
|
|
|
continue
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Literal int within slice
|
|
|
|
|
|
{
|
|
|
|
|
|
local k_tint = "\"type\":\"int\""
|
|
|
|
|
|
local tpos = scan.index_of_from(json, k_tint, p)
|
|
|
|
|
|
if tpos > 0 { if tpos < p_slice_end {
|
|
|
|
|
|
local k_val2 = "\"value\":"
|
|
|
|
|
|
local v2 = scan.index_of_from(json, k_val2, tpos)
|
|
|
|
|
|
if v2 > 0 { if v2 < p_slice_end {
|
|
|
|
|
|
local digits = scan.read_digits(json, v2 + k_val2.length())
|
|
|
|
|
|
if digits != "" { print(digits) printed = printed + 1 did = 1 pos = p_slice_end continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
if did == 1 { pos = p_slice_end + 1 continue }
|
|
|
|
|
|
}
|
|
|
|
|
|
// 0) BinaryOp typed/expr(重スキャン回避のため無効化。必要なら下の軽量パスを使用)
|
|
|
|
|
|
// 1) BinaryOp fallbacks(開発用トグル。既定OFF)
|
|
|
|
|
|
if (new MiniVmPrints()._fallback_enabled() == 1) {
|
|
|
|
|
|
local nextp = bin.try_print_binop_sum_any(json, end, p)
|
|
|
|
|
|
if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
nextp = bin.try_print_binop_at(json, end, p)
|
|
|
|
|
|
if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
nextp = bin.try_print_binop_int_greedy(json, end, p)
|
|
|
|
|
|
if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
nextp = bin.try_print_binop_sum_any(json, end, p)
|
|
|
|
|
|
if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
// Inline typed sum within this Print BinaryOp('+')
|
|
|
|
|
|
{
|
|
|
|
|
|
local k_expr = "\"expression\":{"
|
|
|
|
|
|
local epos = scan.index_of_from(json, k_expr, p)
|
|
|
|
|
|
if epos > 0 { if epos < p_obj_end {
|
|
|
|
|
|
if scan.index_of_from(json, "\"kind\":\"BinaryOp\"", epos) > 0 {
|
|
|
|
|
|
if scan.index_of_from(json, "\"operator\":\"+\"", epos) > 0 {
|
|
|
|
|
|
local k_l = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
|
|
|
|
|
|
local k_r = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
|
|
|
|
|
|
local lp = scan.index_of_from(json, k_l, epos)
|
|
|
|
|
|
if lp > 0 { if lp < p_obj_end {
|
|
|
|
|
|
local ld = scan.read_digits(json, lp + k_l.length())
|
|
|
|
|
|
if ld != "" {
|
|
|
|
|
|
local rp = scan.index_of_from(json, k_r, lp + k_l.length())
|
|
|
|
|
|
if rp > 0 { if rp < p_obj_end {
|
|
|
|
|
|
local rd = scan.read_digits(json, rp + k_r.length())
|
|
|
|
|
|
if rd != "" { print(new MiniVmScan()._int_to_str(new MiniVmScan()._str_to_int(ld) + new MiniVmScan()._str_to_int(rd))) printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 2) Compare
|
|
|
|
|
|
nextp = cmp.try_print_compare_at(json, end, p)
|
|
|
|
|
|
if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
// 3) FunctionCall(既定: 軽量スライス限定パスで処理済み。重い版は呼ばない)
|
|
|
|
|
|
// nextp = new MiniVmPrints().try_print_functioncall_at(json, end, p)
|
|
|
|
|
|
// if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
// 4) literal string
|
|
|
|
|
|
nextp = new MiniVmPrints().try_print_string_value_at(json, end, p)
|
|
|
|
|
|
if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
// 5) literal int via type(重走査を避けるため無効化。スライス限定の軽量パスで処理済み)
|
|
|
|
|
|
// nextp = new MiniVmPrints().try_print_int_value_at(json, end, p)
|
|
|
|
|
|
// if nextp > 0 { printed = printed + 1 pos = p_obj_end + 1 continue }
|
|
|
|
|
|
// 5b) literal int(簡易フォールバック;既定OFF)
|
|
|
|
|
|
if (new MiniVmPrints()._fallback_enabled() == 1) {
|
|
|
|
|
|
local ki = "\"type\":\"int\",\"value\":"
|
|
|
|
|
|
local pi = scan.index_of_from(json, ki, p)
|
|
|
|
|
|
if pi > 0 { if pi < p_slice_end {
|
|
|
|
|
|
local digits = scan.read_digits(json, pi + ki.length())
|
|
|
|
|
|
if digits != "" { print(digits) printed = printed + 1 pos = p_slice_end continue }
|
|
|
|
|
|
}}
|
|
|
|
|
|
// Unknown shape: skip this Print object entirely to avoid stalls
|
|
|
|
|
|
pos = p_obj_end + 1
|
|
|
|
|
|
if pos <= p { pos = p + k_print.length() }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 既定は最小前進(次の探索へ)
|
|
|
|
|
|
pos = p + k_print.length()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return printed
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Process top-level If with literal condition; print branch prints. Returns printed count.
|
|
|
|
|
|
process_if_once(json) {
|
|
|
|
|
|
local scan = new MiniVmScan()
|
|
|
|
|
|
local k_if = "\"kind\":\"If\""
|
|
|
|
|
|
local p = scan.index_of_from(json, k_if, 0)
|
|
|
|
|
|
if p < 0 { return 0 }
|
|
|
|
|
|
local k_cond = "\"condition\""
|
|
|
|
|
|
local cpos = scan.index_of_from(json, k_cond, p)
|
|
|
|
|
|
if cpos < 0 { return 0 }
|
|
|
|
|
|
local k_val = "\"value\":"
|
|
|
|
|
|
local vpos = scan.index_of_from(json, k_val, cpos)
|
|
|
|
|
|
if vpos < 0 { return 0 }
|
|
|
|
|
|
local val_digits = scan.read_digits(json, vpos + k_val.length())
|
|
|
|
|
|
local truthy = 0
|
|
|
|
|
|
if val_digits { if val_digits != "0" { truthy = 1 } }
|
|
|
|
|
|
local k_then = "\"then_body\""
|
|
|
|
|
|
local k_else = "\"else_body\""
|
|
|
|
|
|
local bkey = k_then
|
|
|
|
|
|
if truthy == 0 { bkey = k_else }
|
|
|
|
|
|
local bpos = scan.index_of_from(json, bkey, cpos)
|
|
|
|
|
|
if bpos < 0 { return 0 }
|
|
|
|
|
|
local arr_start = scan.index_of_from(json, "[", bpos)
|
|
|
|
|
|
if arr_start < 0 { return 0 }
|
|
|
|
|
|
local arr_end = new MiniVmScan().find_balanced_array_end(json, arr_start)
|
|
|
|
|
|
if arr_end < 0 { return 0 }
|
|
|
|
|
|
return new MiniVmPrints().print_prints_in_slice(json, arr_start, arr_end)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Print all Print-Literal values in Program.statements (string/int only; MVP)
|
|
|
|
|
|
print_all_print_literals(json) {
|
|
|
|
|
|
return new MiniVmPrints().print_prints_in_slice(json, 0, json.length())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|