Files
hakorune/apps/selfhost-vm/boxes/mini_vm_prints.hako

231 lines
9.9 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.

using selfhost.vm.scan as MiniVmScan
using selfhost.vm.binop as MiniVmBinOp
using selfhost.vm.compare as MiniVmCompare
// Use the JSON adapter facade for cursor ops (next_non_ws, digits)
using selfhost.vm.json as MiniJsonLoader
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) {
local scan = new MiniVmScan()
local bin = new MiniVmBinOp()
local cmp = new MiniVmCompare()
local pos = start
local printed = 0
local guard = 0
local trace = _trace_enabled()
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
local p_obj_start = scan.index_of_from(json, "{", p)
local p_obj_end = scan.find_balanced_object_end(json, p_obj_start)
if p_obj_start <= 0 || p_obj_end <= 0 { p_obj_end = p + k_print.length() }
// also compute coarse slice end by next Print marker to guard when object balance is not reliable
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 }
// 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 minimal
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())
}
}