fix(mir): PHI検証panic修正 - update_cfg()を検証前に呼び出し
A案実装: debug_verify_phi_inputs呼び出し前にCFG predecessorを更新
修正箇所(7箇所):
- src/mir/builder/phi.rs:50, 73, 132, 143
- src/mir/builder/ops.rs:273, 328, 351
根本原因:
- Branch/Jump命令でsuccessorは即座に更新
- predecessorはupdate_cfg()で遅延再構築
- PHI検証が先に実行されてpredecessor未更新でpanic
解決策:
- 各debug_verify_phi_inputs呼び出し前に
if let Some(func) = self.current_function.as_mut() {
func.update_cfg();
}
を挿入してCFGを同期
影響: if/else文、論理演算子(&&/||)のPHI生成が正常動作
This commit is contained in:
@ -9,21 +9,21 @@ static box ArithmeticBox {
|
||||
_to_dec_str(x) {
|
||||
local s = "" + x
|
||||
local i = 0
|
||||
loop(i < s.size()) { local ch = s.substring(i,i+1) if ch=="+" || ch==" " { i=i+1 } else { break } }
|
||||
s = s.substring(i, s.size())
|
||||
loop(i < s.length()) { local ch = s.substring(i,i+1) if ch=="+" || ch==" " { i=i+1 } else { break } }
|
||||
s = s.substring(i, s.length())
|
||||
i = 0
|
||||
loop(i < s.size() && s.substring(i,i+1)=="0") { i = i + 1 }
|
||||
if i >= s.size() { return "0" }
|
||||
return s.substring(i, s.size())
|
||||
loop(i < s.length() && s.substring(i,i+1)=="0") { i = i + 1 }
|
||||
if i >= s.length() { return "0" }
|
||||
return s.substring(i, s.length())
|
||||
}
|
||||
|
||||
_cmp_dec(a, b) {
|
||||
local sa = me._to_dec_str(a)
|
||||
local sb = me._to_dec_str(b)
|
||||
if sa.size() < sb.size() { return -1 }
|
||||
if sa.size() > sb.size() { return 1 }
|
||||
if sa.length() < sb.length() { return -1 }
|
||||
if sa.length() > sb.length() { return 1 }
|
||||
local i = 0
|
||||
loop(i < sa.size()) {
|
||||
loop(i < sa.length()) {
|
||||
local ca = sa.substring(i,i+1)
|
||||
local cb = sb.substring(i,i+1)
|
||||
if ca != cb { if ca < cb { return -1 } else { return 1 } }
|
||||
@ -35,8 +35,8 @@ static box ArithmeticBox {
|
||||
_add_dec(a, b) {
|
||||
local sa = me._to_dec_str(a)
|
||||
local sb = me._to_dec_str(b)
|
||||
local i = sa.size() - 1
|
||||
local j = sb.size() - 1
|
||||
local i = sa.length() - 1
|
||||
local j = sb.length() - 1
|
||||
local carry = 0
|
||||
local out = new ArrayBox()
|
||||
loop(i >= 0 || j >= 0 || carry > 0) {
|
||||
@ -49,7 +49,7 @@ static box ArithmeticBox {
|
||||
local d = s % 10
|
||||
out.push(("0123456789").substring(d, d+1))
|
||||
}
|
||||
local k = out.size()
|
||||
local k = out.length()
|
||||
local res = ""
|
||||
loop(k > 0) { k = k - 1 res = res + (""+out.get(k)) }
|
||||
return res
|
||||
@ -62,8 +62,8 @@ static box ArithmeticBox {
|
||||
local c = me._cmp_dec(sa, sb)
|
||||
if c == 0 { return "0" }
|
||||
if c < 0 { return "-" + me._sub_dec(sb, sa) }
|
||||
local i = sa.size() - 1
|
||||
local j = sb.size() - 1
|
||||
local i = sa.length() - 1
|
||||
local j = sb.length() - 1
|
||||
local borrow = 0
|
||||
local out = new ArrayBox()
|
||||
loop(i >= 0) {
|
||||
@ -75,7 +75,7 @@ static box ArithmeticBox {
|
||||
out.push(("0123456789").substring(d, d+1))
|
||||
i = i - 1
|
||||
}
|
||||
local k = out.size() - 1
|
||||
local k = out.length() - 1
|
||||
loop(true) { if k > 0 && out.get(k) == "0" { k = k - 1 } else { break } }
|
||||
local res = ""
|
||||
loop(k >= 0) { res = res + (""+out.get(k)) k = k - 1 }
|
||||
@ -86,8 +86,8 @@ static box ArithmeticBox {
|
||||
local sa = me._to_dec_str(a)
|
||||
local sb = me._to_dec_str(b)
|
||||
if sa == "0" || sb == "0" { return "0" }
|
||||
local na = sa.size()
|
||||
local nb = sb.size()
|
||||
local na = sa.length()
|
||||
local nb = sb.length()
|
||||
local res = new ArrayBox()
|
||||
local t = 0
|
||||
loop(t < na+nb) { res.push(0) t = t + 1 }
|
||||
@ -108,9 +108,9 @@ static box ArithmeticBox {
|
||||
ia = ia - 1
|
||||
}
|
||||
local k = 0
|
||||
loop(k < res.size() && res.get(k) == 0) { k = k + 1 }
|
||||
loop(k < res.length() && res.get(k) == 0) { k = k + 1 }
|
||||
local out = ""
|
||||
loop(k < res.size()) { out = out + ("0123456789").substring(res.get(k), res.get(k)+1) k = k + 1 }
|
||||
loop(k < res.length()) { out = out + ("0123456789").substring(res.get(k), res.get(k)+1) k = k + 1 }
|
||||
if out == "" { return "0" } else { return out }
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ static box CompareScanBox {
|
||||
local sym = JsonFragBox.get_str(seg, "operation")
|
||||
if sym != "" { kind = CompareOpsBox.map_symbol(sym) } else { kind = "Eq" }
|
||||
}
|
||||
return map({ dst: dst, lhs: lhs, rhs: rhs, kind: kind })
|
||||
return { dst: dst, lhs: lhs, rhs: rhs, kind: kind }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
|
||||
static box FlowDebugBox {
|
||||
// ユーティリティ — 文字列検索
|
||||
_index_of_from(hay, needle, pos) { if pos < 0 { pos = 0 } local n = hay.size() if pos > n { return -1 } local i = pos local m = needle.size() 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 }
|
||||
_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) }
|
||||
|
||||
@ -34,7 +34,7 @@ static box FlowDebugBox {
|
||||
if limit == null { limit = 50 }
|
||||
local ops = new ArrayBox()
|
||||
local pos = 0
|
||||
loop(ops.size() < limit) {
|
||||
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)
|
||||
@ -50,9 +50,9 @@ static box FlowDebugBox {
|
||||
validate_cf_targets(mjson) {
|
||||
local ids = me.collect_block_ids(mjson)
|
||||
// Set 風マップ化
|
||||
local idset = map({})
|
||||
local idset = {}
|
||||
local i = 0
|
||||
loop(i < ids.size()) { idset.set(ids.get(i), 1) i = i + 1 }
|
||||
loop(i < ids.length()) { idset.set(ids.get(i), 1) i = i + 1 }
|
||||
|
||||
local errs = new ArrayBox()
|
||||
local pos = 0
|
||||
@ -78,20 +78,20 @@ static box FlowDebugBox {
|
||||
}
|
||||
|
||||
// レポート
|
||||
if errs.size() == 0 { print("{\"kind\":\"flow_debug\",\"ok\":true,\"blocks\":" + (""+ids.size()) + "}") }
|
||||
if errs.length() == 0 { print("{\"kind\":\"flow_debug\",\"ok\":true,\"blocks\":" + (""+ids.length()) + "}") }
|
||||
else {
|
||||
local k = 0
|
||||
loop(k < errs.size()) { print("{\"kind\":\"flow_debug\",\"ok\":false,\"msg\":\"" + errs.get(k) + "\"}") k = k + 1 }
|
||||
loop(k < errs.length()) { print("{\"kind\":\"flow_debug\",\"ok\":false,\"msg\":\"" + errs.get(k) + "\"}") k = k + 1 }
|
||||
}
|
||||
return errs.size()
|
||||
return errs.length()
|
||||
}
|
||||
|
||||
// 要約: 先頭の op を列挙
|
||||
summarize_ops(mjson, limit) {
|
||||
local ops = me.collect_ops(mjson, limit)
|
||||
local i = 0
|
||||
loop(i < ops.size()) { print("{\"kind\":\"flow_ops\",\"op\":\"" + ops.get(i) + "\"}") i = i + 1 }
|
||||
return ops.size()
|
||||
loop(i < ops.length()) { print("{\"kind\":\"flow_ops\",\"op\":\"" + ops.get(i) + "\"}") i = i + 1 }
|
||||
return ops.length()
|
||||
}
|
||||
|
||||
main(args) { return 0 }
|
||||
|
||||
@ -5,7 +5,7 @@ using "lang/src/shared/json/json_cursor.hako" as JsonCursorBox
|
||||
using "lang/src/vm/boxes/cfg_navigator.hako" as CfgNavigatorBox
|
||||
|
||||
static box InstructionScannerBox {
|
||||
_tprint(msg) { if call("String.indexOf/2", msg, "[ERROR]") >= 0 { print(msg) } }
|
||||
_tprint(msg) { if msg.indexOf("[ERROR]") >= 0 { print(msg) } }
|
||||
|
||||
index_of_from(hay, needle, pos) { return CfgNavigatorBox.index_of_from(hay, needle, pos) }
|
||||
|
||||
@ -16,7 +16,7 @@ static box InstructionScannerBox {
|
||||
if seg == null { return "" }
|
||||
local out = ""
|
||||
local i = 0
|
||||
local n = seg.size()
|
||||
local n = seg.length()
|
||||
loop (i < n) {
|
||||
local ch = seg.substring(i, i+1)
|
||||
if i+2 <= n {
|
||||
@ -36,7 +36,7 @@ static box InstructionScannerBox {
|
||||
local k1 = "\"op\":\""
|
||||
local p1 = obj.indexOf(k1)
|
||||
if p1 >= 0 {
|
||||
local i = p1 + k1.size() // start of value (right after opening quote)
|
||||
local i = p1 + k1.length() // start of value (right after opening quote)
|
||||
local j = JsonCursorBox.scan_string_end(obj, i - 1)
|
||||
if j > i { return obj.substring(i, j) }
|
||||
}
|
||||
@ -44,7 +44,7 @@ static box InstructionScannerBox {
|
||||
local kk = "\"kind\":\""
|
||||
local pk = obj.indexOf(kk)
|
||||
if pk >= 0 {
|
||||
local i2 = pk + kk.size()
|
||||
local i2 = pk + kk.length()
|
||||
local j2 = JsonCursorBox.scan_string_end(obj, i2 - 1)
|
||||
if j2 > i2 {
|
||||
local k = obj.substring(i2, j2)
|
||||
@ -97,7 +97,7 @@ static box InstructionScannerBox {
|
||||
endp = endp + 1
|
||||
local obj = seg.substring(start, endp)
|
||||
local op = me._extract_op(obj)
|
||||
return map({ start: start, end: endp, op: op })
|
||||
return { start: start, end: endp, op: op }
|
||||
}
|
||||
|
||||
// Mini‑VM friendly variant: return "start,end,op" to avoid MapBox dependency
|
||||
|
||||
@ -5,7 +5,7 @@ static box MiniJsonCur {
|
||||
// Skip whitespace from pos; return first non-ws index or -1
|
||||
next_non_ws(s, pos) {
|
||||
local i = pos
|
||||
local n = s.size()
|
||||
local n = s.length()
|
||||
loop (i < n) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch != " " && ch != "\n" && ch != "\r" && ch != "\t" { return i }
|
||||
@ -19,7 +19,7 @@ static box MiniJsonCur {
|
||||
if s.substring(i, i+1) != "\"" { return "" }
|
||||
i = i + 1
|
||||
local out = ""
|
||||
local n = s.size()
|
||||
local n = s.length()
|
||||
loop (i < n) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch == "\"" { break }
|
||||
|
||||
@ -30,7 +30,7 @@ box MiniArray {
|
||||
local idx = 0
|
||||
if si != "" {
|
||||
local i = 0
|
||||
loop(i < si.size()) { idx = idx * 10 + ("0123456789".indexOf(si.substring(i,i+1))) i = i + 1 }
|
||||
loop(i < si.length()) { idx = idx * 10 + ("0123456789".indexOf(si.substring(i,i+1))) i = i + 1 }
|
||||
}
|
||||
local n = me.length()
|
||||
if idx < 0 || idx >= n { print("[ERROR] MiniArray.at: index out of range: " + (""+idx) + "/" + (""+n)) return 0 }
|
||||
@ -45,7 +45,7 @@ box MiniArray {
|
||||
cur = cur + 1
|
||||
}
|
||||
local endp = s.indexOf(",", pos)
|
||||
if endp < 0 { endp = s.size() }
|
||||
if endp < 0 { endp = s.length() }
|
||||
return s.substring(pos, endp)
|
||||
}
|
||||
}
|
||||
@ -91,7 +91,7 @@ box MiniMap2 {
|
||||
local eq = line.indexOf("=")
|
||||
if eq >= 0 {
|
||||
local k = line.substring(0, eq)
|
||||
if k == key { return line.substring(eq + 1, line.size()) }
|
||||
if k == key { return line.substring(eq + 1, line.length()) }
|
||||
}
|
||||
pos = nl + 1
|
||||
}
|
||||
@ -110,7 +110,7 @@ box MiniMap2 {
|
||||
if s == "" { return 0 }
|
||||
// naive contains of 'key=' at line start or after \n
|
||||
local needle = key + "="
|
||||
if s.substring(0, needle.size()) == needle { return 1 }
|
||||
if s.substring(0, needle.length()) == needle { return 1 }
|
||||
local p = s.indexOf("\n" + needle)
|
||||
if p >= 0 { return 1 }
|
||||
return 0
|
||||
|
||||
@ -6,7 +6,7 @@ static box MiniVmEntryBox {
|
||||
|
||||
run_trace(j) {
|
||||
if j.substring(0,1) == "{" {
|
||||
local payload = j.substring(1, j.size())
|
||||
local payload = j.substring(1, j.length())
|
||||
local j2 = "{\"__trace__\":1," + payload
|
||||
return MirVmMin.run_min(j2)
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ static box MiniVmPrints {
|
||||
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.size()
|
||||
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))
|
||||
@ -35,7 +35,7 @@ static box MiniVmPrints {
|
||||
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.size())
|
||||
local digits = scan.read_digits(json, v2 + k_val2.length())
|
||||
if digits == "" { return -1 }
|
||||
print(digits)
|
||||
return obj_end + 1
|
||||
@ -49,7 +49,7 @@ static box MiniVmPrints {
|
||||
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.size()
|
||||
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)
|
||||
@ -76,7 +76,7 @@ static box MiniVmPrints {
|
||||
if fname == "itoa" { print("0") return arr_end + 1 }
|
||||
return -1
|
||||
}
|
||||
atpos = atpos + k_t.size()
|
||||
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)
|
||||
@ -84,7 +84,7 @@ static box MiniVmPrints {
|
||||
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.size()
|
||||
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)
|
||||
@ -95,8 +95,8 @@ static box MiniVmPrints {
|
||||
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.size())
|
||||
if fname == "itoa" || fname == "echo" { print(digits) return ivalp + k_ival.size() }
|
||||
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
|
||||
|
||||
@ -6,12 +6,12 @@ using "lang/src/vm/boxes/op_handlers.hako" as OpHandlersBox
|
||||
|
||||
static box MiniVmProbe {
|
||||
probe_compare(mjson) {
|
||||
local regs = map({})
|
||||
local regs = {}
|
||||
local seg = JsonFragBox.block0_segment(mjson)
|
||||
if seg.size() == 0 { return map({}) }
|
||||
if seg.length() == 0 { return {} }
|
||||
local pos = 0
|
||||
loop(true) {
|
||||
if pos >= seg.size() { break }
|
||||
if pos >= seg.length() { break }
|
||||
// Use escape-aware scanner to get next instruction object
|
||||
local mm = InstructionScannerBox.next(seg, pos)
|
||||
if mm == null { break }
|
||||
@ -39,13 +39,13 @@ static box MiniVmProbe {
|
||||
"Ge" => { if a >= b { 1 } else { 0 } }
|
||||
_ => 0
|
||||
}
|
||||
return map({ a: a, b: b, r: r })
|
||||
return { a: a, b: b, r: r }
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
pos = i
|
||||
}
|
||||
return map({ a: 0, b: 0, r: 0 })
|
||||
return { a: 0, b: 0, r: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ static box MirVmM2 {
|
||||
_find_int_in(seg, keypat) {
|
||||
local p = seg.indexOf(keypat)
|
||||
if p < 0 { return null }
|
||||
p = p + keypat.size()
|
||||
p = p + keypat.length()
|
||||
local i = p
|
||||
local out = ""
|
||||
loop(true) {
|
||||
@ -23,7 +23,7 @@ static box MirVmM2 {
|
||||
_find_str_in(seg, keypat) {
|
||||
local p = seg.indexOf(keypat)
|
||||
if p < 0 { return "" }
|
||||
p = p + keypat.size()
|
||||
p = p + keypat.length()
|
||||
local q = seg.indexOf(""", p)
|
||||
if q < 0 { return "" }
|
||||
return seg.substring(p, q)
|
||||
@ -53,7 +53,7 @@ static box MirVmM2 {
|
||||
if name_end < 0 { break }
|
||||
local opname = json.substring(name_start, name_end)
|
||||
local next_pos = StringOps.index_of_from(json, ""op":"", name_end)
|
||||
if next_pos < 0 { next_pos = json.size() }
|
||||
if next_pos < 0 { next_pos = json.length() }
|
||||
local seg = json.substring(op_pos, next_pos)
|
||||
if opname == "const" {
|
||||
local dst = me._find_int_in(seg, ""dst":")
|
||||
|
||||
@ -51,7 +51,7 @@ box MiniMap {
|
||||
local eq = line.indexOf("=")
|
||||
if eq >= 0 {
|
||||
local k = line.substring(0, eq)
|
||||
if k == key { last = line.substring(eq + 1, line.size()) }
|
||||
if k == key { last = line.substring(eq + 1, line.length()) }
|
||||
}
|
||||
pos = nl + 1
|
||||
}
|
||||
@ -72,8 +72,8 @@ static box MirVmMin {
|
||||
local key = '"callee":{"name":"'
|
||||
local p = seg.indexOf(key)
|
||||
if p < 0 { return "" }
|
||||
p = p + key.size()
|
||||
local rest = seg.substring(p, seg.size())
|
||||
p = p + key.length()
|
||||
local rest = seg.substring(p, seg.length())
|
||||
local q = rest.indexOf('"')
|
||||
if q < 0 { return "" }
|
||||
return rest.substring(0, q)
|
||||
@ -83,7 +83,7 @@ static box MirVmMin {
|
||||
local key = '"args":'
|
||||
local p = seg.indexOf(key)
|
||||
if p < 0 { return null }
|
||||
p = p + key.size()
|
||||
p = p + key.length()
|
||||
// find first digit or '-'
|
||||
local i = p
|
||||
loop(true) {
|
||||
@ -144,7 +144,7 @@ static box MirVmMin {
|
||||
run_thin(mjson) {
|
||||
// Inject a lightweight marker into JSON to toggle thin mode inside _run_min
|
||||
if mjson.substring(0,1) == "{" {
|
||||
local payload = mjson.substring(1, mjson.size())
|
||||
local payload = mjson.substring(1, mjson.length())
|
||||
local j2 = "{\"__thin__\":1," + payload
|
||||
local v = me._run_min(j2)
|
||||
print(me._int_to_str(v))
|
||||
@ -158,7 +158,7 @@ static box MirVmMin {
|
||||
|
||||
// helpers
|
||||
_int_to_str(n) { return StringHelpers.int_to_str(n) }
|
||||
_is_numeric_str(s){ if s==null {return 0} local n=s.size() if n==0 {return 0} local i=0 if s.substring(0,1)=="-" { if n==1 {return 0} i=1 } loop(i<n){ local ch=s.substring(i,i+1) if ch<"0"||ch>"9" {return 0} i=i+1 } return 1 }
|
||||
_is_numeric_str(s){ if s==null {return 0} local n=s.length() if n==0 {return 0} local i=0 if s.substring(0,1)=="-" { if n==1 {return 0} i=1 } loop(i<n){ local ch=s.substring(i,i+1) if ch<"0"||ch>"9" {return 0} i=i+1 } return 1 }
|
||||
_load_reg(regs,id){ local v=regs.getField(""+id) if v==null {return 0} local s=""+v if me._is_numeric_str(s)==1 { return JsonFragBox._str_to_int(s) } return 0 }
|
||||
|
||||
// block helpers
|
||||
@ -195,7 +195,7 @@ static box MirVmMin {
|
||||
local key = "\"value\":{\"type\":\"i64\",\"value\":"
|
||||
local p = StringOps.index_of_from(b0, key, 0)
|
||||
if p >= 0 {
|
||||
local ds = b0.substring(p + key.size(), b0.size())
|
||||
local ds = b0.substring(p + key.length(), b0.length())
|
||||
// read consecutive digits
|
||||
local i = 0
|
||||
local out = ""
|
||||
@ -234,13 +234,13 @@ static box MirVmMin {
|
||||
me._d("[DEBUG] endp="+me._int_to_str(endp), trace)
|
||||
if endp <= start { return 0 }
|
||||
local inst_seg = mjson.substring(start, endp)
|
||||
me._d("[DEBUG] seglen="+me._int_to_str(inst_seg.size()), trace)
|
||||
me._d("[DEBUG] seglen="+me._int_to_str(inst_seg.length()), trace)
|
||||
// scan objects in this block
|
||||
local scan_pos = 0
|
||||
local inst_count = 0
|
||||
local moved = 0
|
||||
loop(true){
|
||||
if scan_pos >= inst_seg.size() { break }
|
||||
if scan_pos >= inst_seg.length() { break }
|
||||
local tup = InstructionScannerBox.next_tuple(inst_seg, scan_pos)
|
||||
if tup == "" { break }
|
||||
// parse "start,end,op"
|
||||
@ -249,7 +249,7 @@ static box MirVmMin {
|
||||
if c1 < 0 || c2 < 0 { break }
|
||||
local obj_start = JsonFragBox._str_to_int(tup.substring(0, c1))
|
||||
local obj_end = JsonFragBox._str_to_int(tup.substring(c1+1, c2))
|
||||
local op = tup.substring(c2+1, tup.size())
|
||||
local op = tup.substring(c2+1, tup.length())
|
||||
local seg = inst_seg.substring(obj_start, obj_end)
|
||||
if op == null { op = "" } if op == "null" { op = "" } if op == 0 { op = "" }
|
||||
if op == "" {
|
||||
@ -283,7 +283,7 @@ static box MirVmMin {
|
||||
local krhs_fast = rec.get("rhs")
|
||||
local kcmp_fast = rec.get("kind")
|
||||
// Determine if a ret exists after this compare in the same block
|
||||
local tail = inst_seg.substring(obj_end, inst_seg.size())
|
||||
local tail = inst_seg.substring(obj_end, inst_seg.length())
|
||||
local ridt = JsonFragBox.get_int(tail, "value")
|
||||
if kdst_fast != null && klhs_fast != null && krhs_fast != null && ridt != null && ridt == kdst_fast {
|
||||
local a = me._load_reg(regs, klhs_fast)
|
||||
@ -378,7 +378,7 @@ else if op == "ret" {
|
||||
// Prefer recent compare result when a ret exists targeting it (no recompute)
|
||||
if inst_seg.indexOf("\"op\":\"ret\"") >= 0 {
|
||||
local rstartX = inst_seg.indexOf("\"op\":\"ret\"")
|
||||
local rsegX = inst_seg.substring(rstartX, inst_seg.size())
|
||||
local rsegX = inst_seg.substring(rstartX, inst_seg.length())
|
||||
local ridX = JsonFragBox.get_int(rsegX, "value")
|
||||
if ridX != null { if ridX == last_cmp_dst { return last_cmp_val } }
|
||||
}
|
||||
@ -387,7 +387,7 @@ else if op == "ret" {
|
||||
// Detect explicit ret in this block and resolve
|
||||
if inst_seg.indexOf("\"op\":\"ret\"") >= 0 {
|
||||
local rstart = inst_seg.indexOf("\"op\":\"ret\"")
|
||||
local rseg = inst_seg.substring(rstart, inst_seg.size())
|
||||
local rseg = inst_seg.substring(rstart, inst_seg.length())
|
||||
local rid = JsonFragBox.get_int(rseg, "value")
|
||||
if rid != null {
|
||||
if rid == last_cmp_dst {
|
||||
@ -410,7 +410,7 @@ else if op == "ret" {
|
||||
loop(true) {
|
||||
local k = StringOps.index_of_from(search, key, pos)
|
||||
if k < 0 { break }
|
||||
local ds = search.substring(k + key.size(), search.size())
|
||||
local ds = search.substring(k + key.length(), search.length())
|
||||
// read consecutive digits as number
|
||||
local i = 0
|
||||
local out = ""
|
||||
@ -421,29 +421,29 @@ else if op == "ret" {
|
||||
}
|
||||
if out != "" { if first == "" { first = out } else { second = out } }
|
||||
if second != "" { break }
|
||||
pos = k + key.size() + i
|
||||
pos = k + key.length() + i
|
||||
}
|
||||
if first != "" && second != "" {
|
||||
local lv = 0
|
||||
local rv = 0
|
||||
// simple to_i64
|
||||
local i0 = 0
|
||||
loop(i0 < first.size()) { lv = lv * 10 + ("0123456789".indexOf(first.substring(i0,i0+1))) i0 = i0 + 1 }
|
||||
loop(i0 < first.length()) { lv = lv * 10 + ("0123456789".indexOf(first.substring(i0,i0+1))) i0 = i0 + 1 }
|
||||
local i1 = 0
|
||||
loop(i1 < second.size()) { rv = rv * 10 + ("0123456789".indexOf(second.substring(i1,i1+1))) i1 = i1 + 1 }
|
||||
loop(i1 < second.length()) { rv = rv * 10 + ("0123456789".indexOf(second.substring(i1,i1+1))) i1 = i1 + 1 }
|
||||
// cmp: parse cmp op
|
||||
local cmp_key = "\"cmp\":\""
|
||||
local pk = inst_seg.indexOf(cmp_key)
|
||||
local cmp = "Eq"
|
||||
if pk >= 0 {
|
||||
local i = pk + cmp_key.size()
|
||||
local i = pk + cmp_key.length()
|
||||
local j = StringOps.index_of_from(inst_seg, "\"", i)
|
||||
if j > i { cmp = inst_seg.substring(i, j) }
|
||||
}
|
||||
local cv = CompareOpsBox.eval(cmp, lv, rv)
|
||||
// ret id
|
||||
local rstart4 = inst_seg.indexOf("\"op\":\"ret\"")
|
||||
local rseg4 = inst_seg.substring(rstart4, inst_seg.size())
|
||||
local rseg4 = inst_seg.substring(rstart4, inst_seg.length())
|
||||
local rid4 = JsonFragBox.get_int(rseg4, "value")
|
||||
if rid4 != null { return cv }
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ static box OpHandlersBox {
|
||||
_find_int_in(seg, keypat) {
|
||||
local p = seg.indexOf(keypat)
|
||||
if p < 0 { return null }
|
||||
p = p + keypat.size()
|
||||
p = p + keypat.length()
|
||||
local i = p
|
||||
local out = ""
|
||||
loop(true) {
|
||||
@ -37,9 +37,9 @@ static box OpHandlersBox {
|
||||
_find_str_in(seg, keypat) {
|
||||
local p = seg.indexOf(keypat)
|
||||
if p < 0 { return "" }
|
||||
p = p + keypat.size()
|
||||
p = p + keypat.length()
|
||||
// Use substring to work around indexOf not supporting start position
|
||||
local rest = seg.substring(p, seg.size())
|
||||
local rest = seg.substring(p, seg.length())
|
||||
local q = rest.indexOf("\"")
|
||||
if q < 0 { return "" }
|
||||
return rest.substring(0, q)
|
||||
@ -77,7 +77,7 @@ static box OpHandlersBox {
|
||||
local p = seg.indexOf(pat_i64)
|
||||
if p >= 0 {
|
||||
// Minimal digit read (inline)
|
||||
local i = p + pat_i64.size()
|
||||
local i = p + pat_i64.length()
|
||||
local out = ""
|
||||
loop(true) {
|
||||
local ch = seg.substring(i, i+1)
|
||||
@ -96,7 +96,7 @@ static box OpHandlersBox {
|
||||
local pat_str = "\"value\":{\"type\":\"string\",\"value\":\""
|
||||
local ps = seg.indexOf(pat_str)
|
||||
if ps >= 0 {
|
||||
local start = ps + pat_str.size()
|
||||
local start = ps + pat_str.length()
|
||||
// Use escape-aware scanner to find the string end at the matching quote
|
||||
local vend = JsonCursorBox.scan_string_end(seg, start - 1)
|
||||
if vend > start {
|
||||
@ -111,7 +111,7 @@ static box OpHandlersBox {
|
||||
local pat_v = "\"value\":\""
|
||||
local pv = seg.indexOf(pat_v)
|
||||
if pv >= 0 {
|
||||
local start = pv + pat_v.size()
|
||||
local start = pv + pat_v.length()
|
||||
local vend = JsonCursorBox.scan_string_end(seg, start - 1)
|
||||
if vend > start {
|
||||
local s2 = seg.substring(start, vend)
|
||||
|
||||
@ -36,10 +36,10 @@ static box PhiDecodeBox {
|
||||
local key = me._dq()+"values"+me._dq()+":"+me._lsq()
|
||||
local p = seg.indexOf(key)
|
||||
if p < 0 { return null }
|
||||
local arr_br = p + key.size() - 1 // points at '['
|
||||
local arr_br = p + key.length() - 1 // points at '['
|
||||
local i = arr_br + 1
|
||||
local endp = JsonCursorBox.seek_array_end(seg, arr_br)
|
||||
local n = seg.size()
|
||||
local n = seg.length()
|
||||
if endp >= 0 { n = endp }
|
||||
local best_dst = JsonFragBox.get_int(seg, "dst")
|
||||
if best_dst == null { return { type: "err", code: "phi:invalid-object:dst-missing" } }
|
||||
|
||||
@ -14,7 +14,7 @@ box ReleaseManagerBox {
|
||||
if arr == null { return 0 }
|
||||
// Defensive: tolerate both ArrayBox and array-like values
|
||||
local n = 0
|
||||
if arr.length != null { n = arr.size() } else { return 0 }
|
||||
if arr.length != null { n = arr.length() } else { return 0 }
|
||||
local i = 0
|
||||
loop(i < n) {
|
||||
local v = arr.get(i)
|
||||
|
||||
@ -20,7 +20,7 @@ static box RetResolveSimpleBox {
|
||||
_resolve_explicit(inst_seg, regs, last_cmp_dst, last_cmp_val) {
|
||||
local rpos = inst_seg.indexOf("\"op\":\"ret\"")
|
||||
if rpos < 0 { return null }
|
||||
local rseg = inst_seg.substring(rpos, inst_seg.size())
|
||||
local rseg = inst_seg.substring(rpos, inst_seg.length())
|
||||
local rid = JsonFragBox.get_int(rseg, "value")
|
||||
if rid == null { return null }
|
||||
if rid == last_cmp_dst { return last_cmp_val }
|
||||
@ -30,7 +30,7 @@ static box RetResolveSimpleBox {
|
||||
_resolve_kind(inst_seg, regs, last_cmp_dst, last_cmp_val) {
|
||||
local kpos = inst_seg.indexOf("\"kind\":\"Ret\"")
|
||||
if kpos < 0 { return null }
|
||||
local kseg = inst_seg.substring(kpos, inst_seg.size())
|
||||
local kseg = inst_seg.substring(kpos, inst_seg.length())
|
||||
local rid = JsonFragBox.get_int(kseg, "value")
|
||||
if rid == null { return null }
|
||||
if rid == last_cmp_dst { return last_cmp_val }
|
||||
|
||||
@ -26,12 +26,12 @@ static box RuneHostBox {
|
||||
// else try simple integer literal (only digits)
|
||||
local i = 0
|
||||
local ok = 1
|
||||
loop(i < code.size()) { local ch = code.substring(i,i+1) if !(ch == "0" or ch == "1" or ch == "2" or ch == "3" or ch == "4" or ch == "5" or ch == "6" or ch == "7" or ch == "8" or ch == "9") { ok = 0 } i = i + 1 }
|
||||
loop(i < code.length()) { local ch = code.substring(i,i+1) if !(ch == "0" or ch == "1" or ch == "2" or ch == "3" or ch == "4" or ch == "5" or ch == "6" or ch == "7" or ch == "8" or ch == "9") { ok = 0 } i = i + 1 }
|
||||
if ok == 1 {
|
||||
// very rough: build integer by repeated add (limited)
|
||||
local n = 0
|
||||
i = 0
|
||||
loop(i < code.size()) {
|
||||
loop(i < code.length()) {
|
||||
n = n * 10
|
||||
local ch2 = code.substring(i,i+1)
|
||||
if ch2 == "1" { n = n + 1 } else { if ch2 == "2" { n = n + 2 } else { if ch2 == "3" { n = n + 3 } else { if ch2 == "4" { n = n + 4 } else { if ch2 == "5" { n = n + 5 } else { if ch2 == "6" { n = n + 6 } else { if ch2 == "7" { n = n + 7 } else { if ch2 == "8" { n = n + 8 } else { if ch2 == "9" { n = n + 9 } } } } } } } }
|
||||
|
||||
@ -11,7 +11,7 @@ box ScannerBox {
|
||||
me._src = source
|
||||
me._pos = 0
|
||||
me._max = 0
|
||||
if source != null { me._max = source.size() }
|
||||
if source != null { me._max = source.length() }
|
||||
}
|
||||
|
||||
at_end() {
|
||||
|
||||
@ -13,7 +13,7 @@ static box SeamInspector {
|
||||
@n = end
|
||||
@delta = 0
|
||||
loop (i < n) {
|
||||
@ch = call("String.substring/2", text, i, i+1)
|
||||
@ch = text.substring(i, i+1)
|
||||
if ch == "\"" {
|
||||
i = i + 1
|
||||
loop (i < n) {
|
||||
@ -32,13 +32,13 @@ static box SeamInspector {
|
||||
}
|
||||
_scan_boxes(text) {
|
||||
@i = 0
|
||||
@n = text.size()
|
||||
@n = text.length()
|
||||
@res = new ArrayBox()
|
||||
@tok = "static box "
|
||||
loop (i < n) {
|
||||
@p = StringOps.index_of_from(text, tok, i)
|
||||
if p < 0 { break }
|
||||
@j = p + tok.size()
|
||||
@j = p + tok.length()
|
||||
@name = ""
|
||||
loop (j < n) {
|
||||
@c = text.substring(j, j+1)
|
||||
@ -50,7 +50,7 @@ static box SeamInspector {
|
||||
loop (j < n) { @c2 = text.substring(j, j+1) if c2 == "{" { break } j = j + 1 }
|
||||
@end = MiniVmScan.find_balanced_object_end(text, j)
|
||||
if end < 0 { end = j }
|
||||
@obj = map({})
|
||||
@obj = {}
|
||||
obj.set("name", name)
|
||||
obj.set("start", _int_to_str(p))
|
||||
obj.set("end", _int_to_str(end))
|
||||
@ -61,17 +61,17 @@ static box SeamInspector {
|
||||
}
|
||||
_report_duplicate_boxes(text) {
|
||||
@boxes = _scan_boxes(text)
|
||||
@cnt = map({})
|
||||
@cnt = {}
|
||||
@names = new ArrayBox()
|
||||
@i = 0
|
||||
loop (i < boxes.size()) {
|
||||
loop (i < boxes.length()) {
|
||||
@name = boxes.get(i).get("name")
|
||||
@cur = cnt.get(name)
|
||||
if cur == null { cnt.set(name, "1") names.push(name) } else { cnt.set(name, _int_to_str(_str_to_int(cur) + 1)) }
|
||||
i = i + 1
|
||||
}
|
||||
@j = 0
|
||||
loop (j < names.size()) {
|
||||
loop (j < names.length()) {
|
||||
@k = names.get(j)
|
||||
@v = cnt.get(k)
|
||||
if _str_to_int(v) > 1 { print("dup_box " + k + " x" + v) }
|
||||
@ -82,9 +82,9 @@ static box SeamInspector {
|
||||
_report_duplicate_functions_in_box(text, box_name) {
|
||||
@boxes = _scan_boxes(text)
|
||||
@i = 0
|
||||
@fnmap = map({})
|
||||
@fnmap = {}
|
||||
@fnames = new ArrayBox()
|
||||
loop (i < boxes.size()) {
|
||||
loop (i < boxes.length()) {
|
||||
@b = boxes.get(i)
|
||||
if b.get("name") == box_name {
|
||||
@s = _str_to_int(b.get("start"))
|
||||
@ -142,7 +142,7 @@ static box SeamInspector {
|
||||
i = i + 1
|
||||
}
|
||||
@x = 0
|
||||
loop (x < fnames.size()) {
|
||||
loop (x < fnames.length()) {
|
||||
@nm = fnames.get(x)
|
||||
@ct = fnmap.get(nm)
|
||||
if _str_to_int(ct) > 1 { print("dup_fn " + box_name + "." + nm + " x" + ct) }
|
||||
|
||||
@ -8,14 +8,14 @@ static box StepRunnerBox {
|
||||
_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.size()) { 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 }
|
||||
_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.size() - 1
|
||||
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 "" }
|
||||
@ -25,7 +25,7 @@ static box StepRunnerBox {
|
||||
// compare の (lhs,rhs,kind,dst) を抽出
|
||||
parse_compare(seg) {
|
||||
local p = JsonCursorBox.index_of_from(seg, "\"op\":\"compare\"", 0)
|
||||
if p < 0 { return map({}) }
|
||||
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))
|
||||
@ -33,17 +33,17 @@ static box StepRunnerBox {
|
||||
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 map({ lhs: lhs, rhs: rhs, dst: dst, kind: kind })
|
||||
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 map({}) }
|
||||
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 map({ cond: cond, then: then_id, else: else_id })
|
||||
return { cond: cond, then: then_id, else: else_id }
|
||||
}
|
||||
|
||||
// compare を評価し cond==dst のときに bool を返す
|
||||
|
||||
@ -5,8 +5,8 @@ static box MiniVm {
|
||||
// simple substring find from position
|
||||
index_of_from(hay, needle, pos) {
|
||||
if pos < 0 { pos = 0 }
|
||||
if pos >= hay.size() { return -1 }
|
||||
local tail = hay.substring(pos, hay.size())
|
||||
if pos >= hay.length() { return -1 }
|
||||
local tail = hay.substring(pos, hay.length())
|
||||
local rel = tail.indexOf(needle)
|
||||
if rel < 0 { return -1 } else { return pos + rel }
|
||||
}
|
||||
@ -26,7 +26,7 @@ static box MiniVm {
|
||||
local k_n = "\"name\":\""
|
||||
local np = index_of_from(json, k_n, p)
|
||||
if np < 0 { break }
|
||||
local ni = np + k_n.size()
|
||||
local ni = np + k_n.length()
|
||||
local nj = index_of_from(json, "\"", ni)
|
||||
if nj < 0 { break }
|
||||
local fname = json.substring(ni, nj)
|
||||
@ -37,7 +37,7 @@ static box MiniVm {
|
||||
local rb = index_of_from(json, "]", ap)
|
||||
if rb < 0 { break }
|
||||
// no content between '[' and ']'
|
||||
if rb == ap + k_a.size() {
|
||||
if rb == ap + k_a.length() {
|
||||
if fname == "echo" { out.push("") }
|
||||
if fname == "itoa" { out.push("0") }
|
||||
}
|
||||
@ -53,7 +53,7 @@ static box Main {
|
||||
|
||||
local arr = new MiniVm().collect_prints(json)
|
||||
local i = 0
|
||||
loop (i < arr.size()) { print(arr.get(i)) i = i + 1 }
|
||||
loop (i < arr.length()) { print(arr.get(i)) i = i + 1 }
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,9 +5,9 @@ static box Main {
|
||||
local json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"FunctionCall\",\"name\":\"echo\",\"arguments\":[]}},{\"kind\":\"Print\",\"expression\":{\"kind\":\"FunctionCall\",\"name\":\"itoa\",\"arguments\":[]}}]}"
|
||||
|
||||
local arr = new MiniVm().collect_prints(json)
|
||||
print("DEBUG: arr.size=" + arr.size())
|
||||
print("DEBUG: arr.size=" + arr.length())
|
||||
local i = 0
|
||||
loop (i < arr.size()) { print(arr.get(i)) i = i + 1 }
|
||||
loop (i < arr.length()) { print(arr.get(i)) i = i + 1 }
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ static box Main {
|
||||
local ki = "\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
|
||||
local p = json.indexOf(ki)
|
||||
if p >= 0 {
|
||||
local i = p + ki.size()
|
||||
local i = p + ki.length()
|
||||
local j = i
|
||||
loop (true) {
|
||||
local ch = json.substring(j, j+1)
|
||||
|
||||
@ -17,8 +17,8 @@ static box Main {
|
||||
if p < 0 { break }
|
||||
// bound current Print slice as [current_print, next_print)
|
||||
local obj_start = p
|
||||
local next_p = StringOps.index_of_from(json, k_print, p + k_print.size())
|
||||
local obj_end = json.size()
|
||||
local next_p = StringOps.index_of_from(json, k_print, p + k_print.length())
|
||||
local obj_end = json.length()
|
||||
if next_p > 0 { obj_end = next_p }
|
||||
|
||||
// 1) BinaryOp(int '+' int)
|
||||
@ -36,12 +36,12 @@ static box Main {
|
||||
local k_r = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
|
||||
local lp = StringOps.index_of_from(json, k_l, bpos)
|
||||
if lp > 0 { if lp < obj_end {
|
||||
local ld = me.read_digits(json, lp + k_l.size())
|
||||
local ld = me.read_digits(json, lp + k_l.length())
|
||||
if ld != "" {
|
||||
local rp = StringOps.index_of_from(json, k_r, lp + k_l.size())
|
||||
local rp = StringOps.index_of_from(json, k_r, lp + k_l.length())
|
||||
if rp > 0 { if rp < obj_end {
|
||||
local rd = me.read_digits(json, rp + k_r.size())
|
||||
if rd != "" { out.push(_int_to_str(_str_to_int(ld) + _str_to_int(rd))) pos = p + k_print.size() continue }
|
||||
local rd = me.read_digits(json, rp + k_r.length())
|
||||
if rd != "" { out.push(_int_to_str(_str_to_int(ld) + _str_to_int(rd))) pos = p + k_print.length() continue }
|
||||
}}
|
||||
}
|
||||
}}
|
||||
@ -49,12 +49,12 @@ static box Main {
|
||||
local k_v = "\"value\":"
|
||||
local v1 = StringOps.index_of_from(json, k_v, epos)
|
||||
if v1 > 0 { if v1 < obj_end {
|
||||
local d1 = me.read_digits(json, v1 + k_v.size())
|
||||
local d1 = me.read_digits(json, v1 + k_v.length())
|
||||
if d1 != "" {
|
||||
local v2 = StringOps.index_of_from(json, k_v, v1 + k_v.size())
|
||||
local v2 = StringOps.index_of_from(json, k_v, v1 + k_v.length())
|
||||
if v2 > 0 { if v2 < obj_end {
|
||||
local d2 = me.read_digits(json, v2 + k_v.size())
|
||||
if d2 != "" { out.push(_int_to_str(_str_to_int(d1) + _str_to_int(d2))) pos = p + k_print.size() continue }
|
||||
local d2 = me.read_digits(json, v2 + k_v.length())
|
||||
if d2 != "" { out.push(_int_to_str(_str_to_int(d1) + _str_to_int(d2))) pos = p + k_print.length() continue }
|
||||
}}
|
||||
}
|
||||
}}
|
||||
@ -71,18 +71,18 @@ static box Main {
|
||||
local k_op = "\"operation\":\""
|
||||
local opos = StringOps.index_of_from(json, k_op, cpos)
|
||||
if opos > 0 { if opos < obj_end {
|
||||
local oi = opos + k_op.size()
|
||||
local oi = opos + k_op.length()
|
||||
local oj = StringOps.index_of_from(json, "\"", oi)
|
||||
if oj > 0 { if oj <= obj_end {
|
||||
local op = json.substring(oi, oj)
|
||||
local k_v = "\"value\":"
|
||||
local lhs_v = StringOps.index_of_from(json, k_v, oj)
|
||||
if lhs_v > 0 { if lhs_v < obj_end {
|
||||
local la = me.read_digits(json, lhs_v + k_v.size())
|
||||
local la = me.read_digits(json, lhs_v + k_v.length())
|
||||
if la != "" {
|
||||
local rhs_v = StringOps.index_of_from(json, k_v, lhs_v + k_v.size())
|
||||
local rhs_v = StringOps.index_of_from(json, k_v, lhs_v + k_v.length())
|
||||
if rhs_v > 0 { if rhs_v < obj_end {
|
||||
local rb = me.read_digits(json, rhs_v + k_v.size())
|
||||
local rb = me.read_digits(json, rhs_v + k_v.length())
|
||||
if rb != "" {
|
||||
local ai = _str_to_int(la)
|
||||
local bi = _str_to_int(rb)
|
||||
@ -94,7 +94,7 @@ static box Main {
|
||||
if op == ">=" { if ai >= bi { res = 1 } }
|
||||
if op == "!=" { if ai != bi { res = 1 } }
|
||||
out.push(_int_to_str(res))
|
||||
pos = p + k_print.size()
|
||||
pos = p + k_print.length()
|
||||
continue
|
||||
}
|
||||
}}
|
||||
@ -113,7 +113,7 @@ static box Main {
|
||||
local kn = "\"name\":\""
|
||||
local np = StringOps.index_of_from(json, kn, fcp)
|
||||
if np > 0 { if np < obj_end {
|
||||
local ni = np + kn.size()
|
||||
local ni = np + kn.length()
|
||||
local nj = StringOps.index_of_from(json, "\"", ni)
|
||||
if nj > 0 { if nj <= obj_end {
|
||||
local fname = json.substring(ni, nj)
|
||||
@ -124,19 +124,19 @@ static box Main {
|
||||
local ks = "\"type\":\"string\",\"value\":\""
|
||||
local ps = StringOps.index_of_from(json, ks, ap)
|
||||
if ps > 0 { if ps < obj_end {
|
||||
local si = ps + ks.size()
|
||||
local si = ps + ks.length()
|
||||
local sj = StringOps.index_of_from(json, "\"", si)
|
||||
if sj > 0 { if sj <= obj_end {
|
||||
local sval = json.substring(si, sj)
|
||||
if fname == "echo" { out.push(sval) pos = p + k_print.size() continue }
|
||||
if fname == "echo" { out.push(sval) pos = p + k_print.length() continue }
|
||||
}}
|
||||
}}
|
||||
// int arg
|
||||
local ki = "\"type\":\"int\",\"value\":"
|
||||
local pi = StringOps.index_of_from(json, ki, ap)
|
||||
if pi > 0 { if pi < obj_end {
|
||||
local ival = me.read_digits(json, pi + ki.size())
|
||||
if ival != "" { if fname == "itoa" { out.push(ival) pos = p + k_print.size() continue } else { if fname == "echo" { out.push(ival) pos = p + k_print.size() continue } } }
|
||||
local ival = me.read_digits(json, pi + ki.length())
|
||||
if ival != "" { if fname == "itoa" { out.push(ival) pos = p + k_print.length() continue } else { if fname == "echo" { out.push(ival) pos = p + k_print.length() continue } } }
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
@ -149,9 +149,9 @@ static box Main {
|
||||
local ks = "\"type\":\"string\",\"value\":\""
|
||||
local ps = StringOps.index_of_from(json, ks, obj_start)
|
||||
if ps > 0 { if ps < obj_end {
|
||||
local si = ps + ks.size()
|
||||
local si = ps + ks.length()
|
||||
local sj = StringOps.index_of_from(json, "\"", si)
|
||||
if sj > 0 { if sj <= obj_end { out.push(json.substring(si, sj)) pos = p + k_print.size() continue }}
|
||||
if sj > 0 { if sj <= obj_end { out.push(json.substring(si, sj)) pos = p + k_print.length() continue }}
|
||||
}}
|
||||
}
|
||||
// 5) Literal int
|
||||
@ -159,12 +159,12 @@ static box Main {
|
||||
local ki = "\"type\":\"int\",\"value\":"
|
||||
local pi = StringOps.index_of_from(json, ki, obj_start)
|
||||
if pi > 0 { if pi < obj_end {
|
||||
local digits = me.read_digits(json, pi + ki.size())
|
||||
if digits != "" { out.push(digits) pos = p + k_print.size() continue }
|
||||
local digits = me.read_digits(json, pi + ki.length())
|
||||
if digits != "" { out.push(digits) pos = p + k_print.length() continue }
|
||||
}}
|
||||
}
|
||||
// Unknown: skip ahead
|
||||
pos = p + k_print.size()
|
||||
pos = p + k_print.length()
|
||||
if pos <= p { pos = p + 1 }
|
||||
}
|
||||
return out
|
||||
@ -177,7 +177,7 @@ static box Main {
|
||||
|
||||
local arr = collect_prints(json)
|
||||
local i = 0
|
||||
loop (i < arr.size()) { print(arr.get(i)) i = i + 1 }
|
||||
loop (i < arr.length()) { print(arr.get(i)) i = i + 1 }
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ static box Main {
|
||||
main(args) {
|
||||
local json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"string\",\"value\":\"A\"}}},{\"kind\":\"Print\",\"expression\":{\"kind\":\"FunctionCall\",\"name\":\"echo\",\"arguments\":[{\"kind\":\"Literal\",\"value\":{\"type\":\"string\",\"value\":\"B\"}}]}},{\"kind\":\"Print\",\"expression\":{\"kind\":\"FunctionCall\",\"name\":\"itoa\",\"arguments\":[{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":7}}]}},{\"kind\":\"Print\",\"expression\":{\"kind\":\"Compare\",\"operation\":\"<\",\"lhs\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":1}},\"rhs\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":2}}}},{\"kind\":\"Print\",\"expression\":{\"kind\":\"BinaryOp\",\"operator\":\"+\",\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":3}},\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":4}}}},{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":5}}}]}"
|
||||
|
||||
new MiniVmPrints().print_prints_in_slice(json, 0, json.size())
|
||||
new MiniVmPrints().print_prints_in_slice(json, 0, json.length())
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ static box Main {
|
||||
|
||||
local arr = new MiniVm().collect_prints(json)
|
||||
local i = 0
|
||||
loop (i < arr.size()) { print(arr.get(i)) i = i + 1 }
|
||||
loop (i < arr.length()) { print(arr.get(i)) i = i + 1 }
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,8 +45,8 @@ static box NyVmDispatcher {
|
||||
// Iteration cap (ENV override: HAKO_CORE_MAX_ITERS | NYASH_CORE_MAX_ITERS)
|
||||
local max_iter = 10000
|
||||
{
|
||||
local v = call("env.local.get/1", "HAKO_CORE_MAX_ITERS")
|
||||
if v == null || v == "" { v = call("env.local.get/1", "NYASH_CORE_MAX_ITERS") }
|
||||
local v = env.get("HAKO_CORE_MAX_ITERS")
|
||||
if v == null || v == "" { v = env.get("NYASH_CORE_MAX_ITERS") }
|
||||
if v != null && v != "" {
|
||||
local n = StringHelpers.to_i64(v)
|
||||
if n > 0 { max_iter = n }
|
||||
|
||||
@ -6,7 +6,7 @@ using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
|
||||
static box NyVmJsonV0Reader {
|
||||
_skip_ws(s, i) {
|
||||
local n = s.size()
|
||||
local n = s.length()
|
||||
loop(i < n) {
|
||||
local ch = s.substring(i,i+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { i = i + 1 continue }
|
||||
@ -93,7 +93,7 @@ static box NyVmJsonV0Reader {
|
||||
local arr = func_json.substring(lb+1, rb)
|
||||
// iterate objects
|
||||
local pos = 0
|
||||
local n = arr.size()
|
||||
local n = arr.length()
|
||||
loop (pos < n) {
|
||||
// skip ws/commas
|
||||
loop (pos < n) {
|
||||
@ -117,7 +117,7 @@ static box NyVmJsonV0Reader {
|
||||
|
||||
// Iterate instructions: return map { obj, next } or Err string when malformed; when finished, returns { obj:null, next:len }
|
||||
next_instruction(insts_json, pos) {
|
||||
local n = insts_json.size()
|
||||
local n = insts_json.length()
|
||||
local i = me._skip_ws(insts_json, pos)
|
||||
if i >= n { return new MapBox() } // obj=null, next=len (empty map)
|
||||
// Skip trailing commas or ws
|
||||
|
||||
@ -24,7 +24,7 @@ static box NyVmOpMirCall {
|
||||
local key = "\"mir_call\":"
|
||||
local p = inst_json.indexOf(key)
|
||||
if p < 0 { return "" }
|
||||
p = p + key.size()
|
||||
p = p + key.length()
|
||||
local end = JsonCursorBox.seek_obj_end(inst_json, p)
|
||||
if end < 0 { return "" }
|
||||
return inst_json.substring(p, end+1)
|
||||
@ -81,7 +81,7 @@ static box NyVmOpMirCall {
|
||||
if colon < 0 { return "default" }
|
||||
local idx = colon + 1
|
||||
loop(true) {
|
||||
if idx >= mir_call_json.size() { return "default" }
|
||||
if idx >= mir_call_json.length() { return "default" }
|
||||
local ch = mir_call_json.substring(idx, idx+1)
|
||||
local is_ws = 0
|
||||
if ch == " " { is_ws = 1 }
|
||||
@ -91,7 +91,7 @@ static box NyVmOpMirCall {
|
||||
if is_ws == 1 { idx = idx + 1 continue }
|
||||
break
|
||||
}
|
||||
if idx >= mir_call_json.size() { return "default" }
|
||||
if idx >= mir_call_json.length() { return "default" }
|
||||
if mir_call_json.substring(idx, idx+1) != "{" { return "default" }
|
||||
local rb = JsonCursorBox.seek_obj_end(mir_call_json, idx)
|
||||
if rb < 0 { return "default" }
|
||||
@ -133,10 +133,10 @@ static box NyVmOpMirCall {
|
||||
if m.substring(idx, idx+1) == "]" { return "" }
|
||||
local digits = JsonCursorBox.digits_from(m, idx)
|
||||
if digits == "" { return "" }
|
||||
i_ref.set(0, idx + digits.size())
|
||||
i_ref.set(0, idx + digits.length())
|
||||
loop(true) {
|
||||
local idx2 = i_ref.get(0)
|
||||
if idx2 >= m.size() { break }
|
||||
if idx2 >= m.length() { break }
|
||||
local ch2 = m.substring(idx2, idx2+1)
|
||||
// Apply workaround here too
|
||||
local is_ws = 0
|
||||
@ -148,7 +148,7 @@ static box NyVmOpMirCall {
|
||||
break
|
||||
}
|
||||
local idx3 = i_ref.get(0)
|
||||
if idx3 < m.size() && m.substring(idx3, idx3+1) == "," { i_ref.set(0, idx3 + 1) }
|
||||
if idx3 < m.length() && m.substring(idx3, idx3+1) == "," { i_ref.set(0, idx3 + 1) }
|
||||
return digits
|
||||
}
|
||||
|
||||
@ -162,10 +162,10 @@ static box NyVmOpMirCall {
|
||||
local current = 0
|
||||
loop(true) {
|
||||
local idx = i.get(0)
|
||||
if idx >= m.size() { break }
|
||||
if idx >= m.length() { break }
|
||||
loop(true) {
|
||||
local idx2 = i.get(0)
|
||||
if idx2 >= m.size() { break }
|
||||
if idx2 >= m.length() { break }
|
||||
local ch = m.substring(idx2, idx2+1)
|
||||
// Parser workaround: avoid array-element assignment inside multi-way OR
|
||||
local is_ws = 0
|
||||
@ -177,7 +177,7 @@ static box NyVmOpMirCall {
|
||||
break
|
||||
}
|
||||
local idx3 = i.get(0)
|
||||
if idx3 >= m.size() { break }
|
||||
if idx3 >= m.length() { break }
|
||||
if m.substring(idx3, idx3+1) == "]" { break }
|
||||
local digits = me._scan_next_arg(m, i)
|
||||
if digits == "" { print(bad_tag) return null }
|
||||
@ -198,7 +198,7 @@ static box NyVmOpMirCall {
|
||||
local current = 0
|
||||
loop(true) {
|
||||
local idx = i.get(0)
|
||||
if idx >= m.size() { break }
|
||||
if idx >= m.length() { break }
|
||||
if m.substring(idx, idx+1) == "]" { break }
|
||||
local digits = me._scan_next_arg(m, i)
|
||||
if digits == "" { return null }
|
||||
@ -535,7 +535,7 @@ static box NyVmOpMirCall {
|
||||
if dst == null { return -1 }
|
||||
local recv_val = NyVmState.get_reg(state, recv_id)
|
||||
local s = "" + recv_val
|
||||
NyVmState.set_reg(state, dst, s.size())
|
||||
NyVmState.set_reg(state, dst, s.length())
|
||||
return 0
|
||||
}
|
||||
// String.indexOf/1 — return first index or -1
|
||||
@ -592,7 +592,7 @@ static box NyVmOpMirCall {
|
||||
local start = NyVmState.get_reg(state, start_vid)
|
||||
local end = NyVmState.get_reg(state, end_vid)
|
||||
// Bounds check
|
||||
if start < 0 || end < 0 || start > s.size() || end > s.size() || start > end {
|
||||
if start < 0 || end < 0 || start > s.length() || end > s.length() || start > end {
|
||||
return me._fail(state, "[core/string/bounds]")
|
||||
}
|
||||
local out = s.substring(start, end)
|
||||
@ -609,7 +609,7 @@ static box NyVmOpMirCall {
|
||||
local s = "" + recv_val
|
||||
local idx = NyVmState.get_reg(state, idx_vid)
|
||||
// Bounds check
|
||||
if idx < 0 || idx >= s.size() {
|
||||
if idx < 0 || idx >= s.length() {
|
||||
return me._fail(state, "[core/string/bounds]")
|
||||
}
|
||||
local ch = s.substring(idx, idx+1)
|
||||
@ -635,7 +635,7 @@ static box NyVmOpMirCall {
|
||||
local result = s
|
||||
if pos >= 0 {
|
||||
local before = s.substring(0, pos)
|
||||
local after = s.substring(pos + pattern.size(), s.size())
|
||||
local after = s.substring(pos + pattern.length(), s.length())
|
||||
result = before + replacement + after
|
||||
}
|
||||
NyVmState.set_reg(state, dst, result)
|
||||
@ -706,9 +706,9 @@ static box NyVmOpMirCall {
|
||||
// Fallback strict check: only digit strings with optional sign
|
||||
local s = "" + v
|
||||
local i = 0
|
||||
if s.size() > 0 && (s.substring(0,1) == "-" || s.substring(0,1) == "+") { i = 1 }
|
||||
local ok = (s.size() > i)
|
||||
loop(i < s.size()) {
|
||||
if s.length() > 0 && (s.substring(0,1) == "-" || s.substring(0,1) == "+") { i = 1 }
|
||||
local ok = (s.length() > i)
|
||||
loop(i < s.length()) {
|
||||
local ch = s.substring(i,i+1)
|
||||
if !(ch >= "0" && ch <= "9") { ok = false break }
|
||||
i = i + 1
|
||||
|
||||
@ -25,7 +25,7 @@ static box NyVmOpPhi {
|
||||
if rb < 0 { return out }
|
||||
local arr = inst_json.substring(lb+1, rb)
|
||||
local pos = 0
|
||||
local n = arr.size()
|
||||
local n = arr.length()
|
||||
loop (pos < n) {
|
||||
// skip ws/commas
|
||||
loop(pos < n) { local ch = arr.substring(pos,pos+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" || ch == "," { pos = pos + 1 continue } break }
|
||||
@ -57,11 +57,11 @@ static box NyVmOpPhi {
|
||||
local dst = me._read_dst(inst_json)
|
||||
if dst == null { print("[core/phi] missing dst") return -1 }
|
||||
local ins = me._read_inputs(inst_json)
|
||||
if ins.size() == 0 { print("[core/phi] empty inputs") return -1 }
|
||||
if ins.length() == 0 { print("[core/phi] empty inputs") return -1 }
|
||||
local pick = ins.get(0)
|
||||
// try match predecessor
|
||||
local i = 0
|
||||
loop(i < ins.size()) {
|
||||
loop(i < ins.length()) {
|
||||
local m = ins.get(i)
|
||||
if m.get("bb") == predecessor { pick = m break }
|
||||
i = i + 1
|
||||
|
||||
@ -18,7 +18,7 @@ static box FlowRunner {
|
||||
if ds == "" { return null }
|
||||
local acc = 0
|
||||
local i = 0
|
||||
loop(i < ds.size()) { acc = acc * 10 + ("0123456789".indexOf(ds.substring(i,i+1))) i = i + 1 }
|
||||
loop(i < ds.length()) { acc = acc * 10 + ("0123456789".indexOf(ds.substring(i,i+1))) i = i + 1 }
|
||||
return acc
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ static box FlowRunner {
|
||||
if j.indexOf("\"__dev__\":1") >= 0 { return j }
|
||||
if ast_json != null && ast_json.indexOf("\"__cli_dev__\":1") >= 0 {
|
||||
if j.substring(0,1) == "{" {
|
||||
local payload = j.substring(1, j.size())
|
||||
local payload = j.substring(1, j.length())
|
||||
return "{\"__dev__\":1," + payload
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ static box ConstHandlerBoxLegacy {
|
||||
local key_i64 = "\"value\":{\"type\":\"i64\",\"value\":"
|
||||
local val_i64_start = inst_json.indexOf(key_i64)
|
||||
if val_i64_start >= 0 {
|
||||
val_i64_start = val_i64_start + key_i64.size()
|
||||
val_i64_start = val_i64_start + key_i64.length()
|
||||
local digits = StringHelpers.read_digits(inst_json, val_i64_start)
|
||||
if digits == "" { return Result.Err("const: invalid i64 value") }
|
||||
local value = StringHelpers.to_i64(digits)
|
||||
@ -24,7 +24,7 @@ static box ConstHandlerBoxLegacy {
|
||||
local key_int = "\"value\":{\"Integer\":"
|
||||
local val_int_start = inst_json.indexOf(key_int)
|
||||
if val_int_start >= 0 {
|
||||
val_int_start = val_int_start + key_int.size()
|
||||
val_int_start = val_int_start + key_int.length()
|
||||
local digits = StringHelpers.read_digits(inst_json, val_int_start)
|
||||
if digits == "" { return Result.Err("const: invalid Integer value") }
|
||||
local value = StringHelpers.to_i64(digits)
|
||||
@ -34,7 +34,7 @@ static box ConstHandlerBoxLegacy {
|
||||
local key_str = "\"value\":{\"String\":\""
|
||||
local val_str_start = inst_json.indexOf(key_str)
|
||||
if val_str_start >= 0 {
|
||||
val_str_start = val_str_start + key_str.size()
|
||||
val_str_start = val_str_start + key_str.length()
|
||||
local val_str_end = StringOps.index_of_from(inst_json, "\"}", val_str_start)
|
||||
if val_str_end < 0 { return Result.Err("const: invalid String value") }
|
||||
local str_value = inst_json.substring(val_str_start, val_str_end)
|
||||
@ -45,7 +45,7 @@ static box ConstHandlerBoxLegacy {
|
||||
local key_s2 = "\"value\":{\"type\":\"string\",\"value\":\""
|
||||
local p2 = inst_json.indexOf(key_s2)
|
||||
if p2 >= 0 {
|
||||
p2 = p2 + key_s2.size()
|
||||
p2 = p2 + key_s2.length()
|
||||
local end2 = StringOps.index_of_from(inst_json, "\"}", p2)
|
||||
if end2 < 0 { return Result.Err("const: invalid string (type string)") }
|
||||
local s2 = inst_json.substring(p2, end2)
|
||||
|
||||
@ -21,7 +21,7 @@ static box ArgsExtractorBox {
|
||||
// No args field, return empty array
|
||||
return args_array
|
||||
}
|
||||
args_start = args_start + args_key.size()
|
||||
args_start = args_start + args_key.length()
|
||||
|
||||
// Find array end
|
||||
local args_end = StringOps.index_of_from(mir_call_json, "]", args_start)
|
||||
@ -34,13 +34,13 @@ static box ArgsExtractorBox {
|
||||
local args_content = mir_call_json.substring(args_start, args_end)
|
||||
|
||||
// If empty array, return immediately
|
||||
if args_content.size() == 0 {
|
||||
if args_content.length() == 0 {
|
||||
return args_array
|
||||
}
|
||||
|
||||
// Parse comma-separated ValueIds
|
||||
local pos = 0
|
||||
local content_len = args_content.size()
|
||||
local content_len = args_content.length()
|
||||
|
||||
loop(pos < content_len) {
|
||||
// Skip whitespace
|
||||
@ -97,7 +97,7 @@ static box ArgsExtractorBox {
|
||||
if args_start < 0 {
|
||||
return 0
|
||||
}
|
||||
args_start = args_start + args_key.size()
|
||||
args_start = args_start + args_key.length()
|
||||
|
||||
// Find array end
|
||||
local args_end = StringOps.index_of_from(mir_call_json, "]", args_start)
|
||||
@ -107,14 +107,14 @@ static box ArgsExtractorBox {
|
||||
|
||||
// Extract args array content
|
||||
local args_content = mir_call_json.substring(args_start, args_end)
|
||||
if args_content.size() == 0 {
|
||||
if args_content.length() == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Count commas + 1
|
||||
local count = 1
|
||||
local pos = 0
|
||||
loop(pos < args_content.size()) {
|
||||
loop(pos < args_content.length()) {
|
||||
local ch = args_content.substring(pos, pos + 1)
|
||||
if ch == "," {
|
||||
count = count + 1
|
||||
@ -131,23 +131,23 @@ static box ArgsExtractorBox {
|
||||
local args_key = "\"args\":["
|
||||
local args_start = mir_call_json.indexOf(args_key)
|
||||
if args_start < 0 { return ids }
|
||||
args_start = args_start + args_key.size()
|
||||
args_start = args_start + args_key.length()
|
||||
local args_end = StringOps.index_of_from(mir_call_json, "]", args_start)
|
||||
if args_end < 0 { return ids }
|
||||
local content = mir_call_json.substring(args_start, args_end)
|
||||
if content.size() == 0 { return ids }
|
||||
if content.length() == 0 { return ids }
|
||||
local pos = 0
|
||||
loop(pos < content.size()) {
|
||||
loop(pos < content.size()) {
|
||||
loop(pos < content.length()) {
|
||||
loop(pos < content.length()) {
|
||||
local ch = content.substring(pos, pos+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue }
|
||||
break
|
||||
}
|
||||
if pos >= content.size() { break }
|
||||
if pos >= content.length() { break }
|
||||
local comma = StringOps.index_of_from(content, ",", pos)
|
||||
local end = comma < 0 ? content.size() : comma
|
||||
local end = comma < 0 ? content.length() : comma
|
||||
local token = content.substring(pos, end)
|
||||
if token.size() > 0 {
|
||||
if token.length() > 0 {
|
||||
ids.push(StringHelpers.to_i64(token))
|
||||
}
|
||||
if comma < 0 { break }
|
||||
|
||||
@ -8,7 +8,7 @@ static box ArgsGuardBox {
|
||||
// Returns Ok(args_array) or Err with first offending index
|
||||
ensure_no_nulls(args_array, method_sig) {
|
||||
if args_array == null { return Result.Ok(new ArrayBox()) }
|
||||
local n = args_array.size()
|
||||
local n = args_array.length()
|
||||
local i = 0
|
||||
loop(i < n) {
|
||||
if args_array.get(i) == null {
|
||||
|
||||
@ -6,7 +6,7 @@ using "lang/src/vm/boxes/result_box.hako" as Result
|
||||
static box BackwardObjectScannerBox {
|
||||
// Returns Ok(obj_string) or Err(label)
|
||||
scan_last_object(seg, budget) {
|
||||
local n = seg.size()
|
||||
local n = seg.length()
|
||||
local steps = 0
|
||||
// trim trailing spaces/commas
|
||||
local e = n - 1
|
||||
|
||||
@ -8,7 +8,7 @@ using "lang/src/vm/hakorune-vm/json_scan_guard.hako" as JsonScanGuardBox
|
||||
static box BlockIteratorBox {
|
||||
// Returns Ok({ obj: <string>, next_pos: <int> }) or Err when malformed
|
||||
next(blocks_content, pos) {
|
||||
local n = blocks_content.size()
|
||||
local n = blocks_content.length()
|
||||
local i = pos
|
||||
loop(i < n) {
|
||||
local ch = blocks_content.substring(i, i+1)
|
||||
|
||||
@ -29,7 +29,7 @@ static box BlockMapperBox {
|
||||
|
||||
// blocks_content から連続するオブジェクト { ... } を走査
|
||||
local pos = 0
|
||||
local n = blocks_content.size()
|
||||
local n = blocks_content.length()
|
||||
loop(pos < n) {
|
||||
// 空白/カンマをスキップ
|
||||
local ch = blocks_content.substring(pos, pos+1)
|
||||
@ -44,9 +44,9 @@ static box BlockMapperBox {
|
||||
local key_id = "\"id\":"
|
||||
local id_start = block_json.indexOf(key_id)
|
||||
if id_start < 0 { return Result.Err("block id not found") }
|
||||
id_start = id_start + key_id.size()
|
||||
id_start = id_start + key_id.length()
|
||||
// 空白スキップ
|
||||
loop(id_start < block_json.size()) {
|
||||
loop(id_start < block_json.length()) {
|
||||
local c2 = block_json.substring(id_start, id_start+1)
|
||||
if c2 == " " || c2 == "\n" || c2 == "\r" || c2 == "\t" { id_start = id_start + 1 continue }
|
||||
break
|
||||
@ -76,14 +76,14 @@ static box BlockMapperBox {
|
||||
// blocks 配列位置へ
|
||||
local key_pos = JsonCursorBox.find_key_dual(func_json, "\"blocks\"", "\\\"blocks\\\"", 0)
|
||||
if key_pos < 0 { return Result.Err("blocks key not found") }
|
||||
local i = key_pos + "\"blocks\"".size()
|
||||
loop(i < func_json.size()) {
|
||||
local i = key_pos + "\"blocks\"".length()
|
||||
loop(i < func_json.length()) {
|
||||
local ch = func_json.substring(i, i+1)
|
||||
if ch == ":" { i = i + 1 break }
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { i = i + 1 continue }
|
||||
return Result.Err("invalid blocks key format")
|
||||
}
|
||||
loop(i < func_json.size()) {
|
||||
loop(i < func_json.length()) {
|
||||
local ch = func_json.substring(i, i+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { i = i + 1 continue }
|
||||
if ch == "[" { break }
|
||||
@ -96,7 +96,7 @@ static box BlockMapperBox {
|
||||
|
||||
// 各ブロックを解析
|
||||
local pos = 0
|
||||
local len = blocks_json.size()
|
||||
local len = blocks_json.length()
|
||||
|
||||
loop(pos < len) {
|
||||
// 空白とカンマをスキップ
|
||||
@ -121,10 +121,10 @@ static box BlockMapperBox {
|
||||
if id_start < 0 {
|
||||
return Result.Err("block id not found")
|
||||
}
|
||||
id_start = id_start + key_id.size()
|
||||
id_start = id_start + key_id.length()
|
||||
|
||||
// 数字直前の空白スキップ
|
||||
loop(id_start < block_json.size()) {
|
||||
loop(id_start < block_json.length()) {
|
||||
local ch2 = block_json.substring(id_start, id_start+1)
|
||||
if ch2 == " " || ch2 == "\n" || ch2 == "\r" || ch2 == "\t" { id_start = id_start + 1 continue }
|
||||
break
|
||||
|
||||
@ -11,14 +11,14 @@ static box BlocksLocatorBox {
|
||||
local kpos = JsonCursorBox.index_of_from(func_json, r#""blocks""#, 0)
|
||||
if kpos < 0 { return Result.Err("blocks key not found") }
|
||||
// find ':' then '['
|
||||
local i = kpos + r#""blocks""#.size()
|
||||
loop(i < func_json.size()) {
|
||||
local i = kpos + r#""blocks""#.length()
|
||||
loop(i < func_json.length()) {
|
||||
local ch = func_json.substring(i, i+1)
|
||||
if ch == ":" { i = i + 1 break }
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { i = i + 1 continue }
|
||||
return Result.Err("blocks key format invalid")
|
||||
}
|
||||
loop(i < func_json.size()) {
|
||||
loop(i < func_json.length()) {
|
||||
local ch = func_json.substring(i, i+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { i = i + 1 continue }
|
||||
if ch == "[" { break }
|
||||
|
||||
@ -50,7 +50,7 @@ static box BoxCallHandlerBox {
|
||||
|
||||
|
||||
// Guard arguments (no nulls)
|
||||
local _g = ArgsGuardBox.ensure_no_nulls(args_array, method_name + "/" + args_array.size())
|
||||
local _g = ArgsGuardBox.ensure_no_nulls(args_array, method_name + "/" + args_array.length())
|
||||
if _g.is_Err() { return _g }
|
||||
|
||||
// Extract destination register
|
||||
@ -63,7 +63,7 @@ static box BoxCallHandlerBox {
|
||||
}
|
||||
|
||||
// Prepare method signature for dispatch
|
||||
local arg_count = args_array.size()
|
||||
local arg_count = args_array.length()
|
||||
local method_sig = method_name + "/" + arg_count
|
||||
|
||||
// Known methods dispatch table
|
||||
@ -75,9 +75,9 @@ static box BoxCallHandlerBox {
|
||||
} else if method_sig == "lower/0" {
|
||||
result_val = receiver.to_lower()
|
||||
} else if method_sig == "size/0" {
|
||||
result_val = receiver.size()
|
||||
result_val = receiver.length()
|
||||
} else if method_sig == "length/0" {
|
||||
result_val = receiver.size()
|
||||
result_val = receiver.length()
|
||||
} else if method_sig == "isEmpty/0" {
|
||||
result_val = receiver.isEmpty()
|
||||
} else if method_sig == "substring/2" {
|
||||
@ -96,9 +96,9 @@ static box BoxCallHandlerBox {
|
||||
} else if method_sig == "set/2" {
|
||||
result_val = receiver.set(args_array.get(0), args_array.get(1))
|
||||
} else if method_sig == "length/0" {
|
||||
result_val = receiver.size()
|
||||
result_val = receiver.length()
|
||||
} else if method_sig == "size/0" {
|
||||
result_val = receiver.size()
|
||||
result_val = receiver.length()
|
||||
} else if method_sig == "isEmpty/0" {
|
||||
result_val = receiver.isEmpty()
|
||||
}
|
||||
@ -111,7 +111,7 @@ static box BoxCallHandlerBox {
|
||||
} else if method_sig == "has/1" {
|
||||
result_val = receiver.has(args_array.get(0))
|
||||
} else if method_sig == "size/0" {
|
||||
result_val = receiver.size()
|
||||
result_val = receiver.length()
|
||||
} else if method_sig == "isEmpty/0" {
|
||||
result_val = receiver.isEmpty()
|
||||
} else if method_sig == "delete/1" {
|
||||
@ -171,7 +171,7 @@ static box BoxCallHandlerBox {
|
||||
// No args field, return empty array
|
||||
return new ArrayBox()
|
||||
}
|
||||
args_start = args_start + args_key.size()
|
||||
args_start = args_start + args_key.length()
|
||||
|
||||
// Find array end
|
||||
local args_end = StringOps.index_of_from(inst_json, "]", args_start)
|
||||
|
||||
@ -16,7 +16,7 @@ static box CalleeParserBox {
|
||||
if callee_start < 0 {
|
||||
return null
|
||||
}
|
||||
callee_start = callee_start + callee_key.size()
|
||||
callee_start = callee_start + callee_key.length()
|
||||
|
||||
// Find callee object end (simplified: find next "type" field)
|
||||
local type_key = "\"type\":\""
|
||||
@ -24,7 +24,7 @@ static box CalleeParserBox {
|
||||
if type_start < 0 {
|
||||
return null
|
||||
}
|
||||
type_start = type_start + type_key.size()
|
||||
type_start = type_start + type_key.length()
|
||||
|
||||
// Extract type value
|
||||
local type_end = StringOps.index_of_from(mir_call_json, "\"", type_start)
|
||||
@ -45,7 +45,7 @@ static box CalleeParserBox {
|
||||
if name_start < 0 {
|
||||
return null
|
||||
}
|
||||
name_start = name_start + name_key.size()
|
||||
name_start = name_start + name_key.length()
|
||||
|
||||
// Extract name value
|
||||
local name_end = StringOps.index_of_from(mir_call_json, "\"", name_start)
|
||||
@ -66,7 +66,7 @@ static box CalleeParserBox {
|
||||
if callee_start < 0 {
|
||||
return null
|
||||
}
|
||||
local obj_start = callee_start + callee_key.size()
|
||||
local obj_start = callee_start + callee_key.length()
|
||||
|
||||
// Find object end (simple: find matching })
|
||||
// Note: This is simplified and assumes no nested objects in callee
|
||||
@ -88,7 +88,7 @@ static box CalleeParserBox {
|
||||
if receiver_start < 0 {
|
||||
return null
|
||||
}
|
||||
receiver_start = receiver_start + receiver_key.size()
|
||||
receiver_start = receiver_start + receiver_key.length()
|
||||
|
||||
// Extract receiver value (integer)
|
||||
local digits = StringHelpers.read_digits(mir_call_json, receiver_start)
|
||||
@ -109,7 +109,7 @@ static box CalleeParserBox {
|
||||
if method_start < 0 {
|
||||
return null
|
||||
}
|
||||
method_start = method_start + method_key.size()
|
||||
method_start = method_start + method_key.length()
|
||||
|
||||
// Extract method value
|
||||
local method_end = StringOps.index_of_from(mir_call_json, "\"", method_start)
|
||||
@ -130,7 +130,7 @@ static box CalleeParserBox {
|
||||
if box_type_start < 0 {
|
||||
return null
|
||||
}
|
||||
box_type_start = box_type_start + box_type_key.size()
|
||||
box_type_start = box_type_start + box_type_key.length()
|
||||
|
||||
// Extract box_type value
|
||||
local box_type_end = StringOps.index_of_from(mir_call_json, "\"", box_type_start)
|
||||
@ -148,7 +148,7 @@ static box CalleeParserBox {
|
||||
local val_key = "\"value\":"
|
||||
local val_start = mir_call_json.indexOf(val_key)
|
||||
if val_start < 0 { return null }
|
||||
val_start = val_start + val_key.size()
|
||||
val_start = val_start + val_key.length()
|
||||
// Read digits
|
||||
local digits = StringHelpers.read_digits(mir_call_json, val_start)
|
||||
if digits == "" { return null }
|
||||
|
||||
@ -72,10 +72,10 @@ static box ClosureCallHandlerBox {
|
||||
if start < 0 {
|
||||
return null
|
||||
}
|
||||
start = start + field_key.size()
|
||||
start = start + field_key.length()
|
||||
|
||||
// Skip whitespace
|
||||
loop(start < json.size()) {
|
||||
loop(start < json.length()) {
|
||||
local ch = json.charAt(start)
|
||||
if ch == " " {
|
||||
start = start + 1
|
||||
@ -92,7 +92,7 @@ static box ClosureCallHandlerBox {
|
||||
start = start + 1
|
||||
}
|
||||
|
||||
if start >= json.size() {
|
||||
if start >= json.length() {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ static box ClosureCallHandlerBox {
|
||||
// Parse array (simple implementation for string arrays)
|
||||
local result = new ArrayBox()
|
||||
local i = 1 // skip '['
|
||||
loop(i < array_json.size()) {
|
||||
loop(i < array_json.length()) {
|
||||
local ch = array_json.charAt(i)
|
||||
if ch == "]" {
|
||||
break
|
||||
@ -116,7 +116,7 @@ static box ClosureCallHandlerBox {
|
||||
// Find string end
|
||||
local str_start = i + 1
|
||||
local str_end = str_start
|
||||
loop(str_end < array_json.size()) {
|
||||
loop(str_end < array_json.length()) {
|
||||
local ch2 = array_json.charAt(str_end)
|
||||
if ch2 == "\"" {
|
||||
break
|
||||
@ -142,10 +142,10 @@ static box ClosureCallHandlerBox {
|
||||
// No captures field = empty captures (valid)
|
||||
return new MapBox()
|
||||
}
|
||||
start = start + field_key.size()
|
||||
start = start + field_key.length()
|
||||
|
||||
// Skip whitespace to find '['
|
||||
loop(start < json.size()) {
|
||||
loop(start < json.length()) {
|
||||
local ch = json.charAt(start)
|
||||
if ch == " " {
|
||||
start = start + 1
|
||||
@ -162,7 +162,7 @@ static box ClosureCallHandlerBox {
|
||||
start = start + 1
|
||||
}
|
||||
|
||||
if start >= json.size() {
|
||||
if start >= json.length() {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ static box ClosureCallHandlerBox {
|
||||
// Parse captures array: [["name1", 5], ["name2", 6]]
|
||||
local result = new MapBox()
|
||||
local i = 1 // skip '['
|
||||
loop(i < array_json.size()) {
|
||||
loop(i < array_json.length()) {
|
||||
local ch = array_json.charAt(i)
|
||||
if ch == "]" {
|
||||
break
|
||||
@ -186,7 +186,7 @@ static box ClosureCallHandlerBox {
|
||||
// Parse [name, vid] tuple
|
||||
local tuple_start = i
|
||||
local tuple_end = tuple_start + 1
|
||||
loop(tuple_end < array_json.size()) {
|
||||
loop(tuple_end < array_json.length()) {
|
||||
local ch2 = array_json.charAt(tuple_end)
|
||||
if ch2 == "]" {
|
||||
break
|
||||
@ -201,7 +201,7 @@ static box ClosureCallHandlerBox {
|
||||
if name_start >= 0 {
|
||||
name_start = name_start + 1
|
||||
local name_end = name_start
|
||||
loop(name_end < tuple_json.size()) {
|
||||
loop(name_end < tuple_json.length()) {
|
||||
local ch3 = tuple_json.charAt(name_end)
|
||||
if ch3 == "\"" {
|
||||
break
|
||||
@ -215,7 +215,7 @@ static box ClosureCallHandlerBox {
|
||||
if comma_pos >= 0 {
|
||||
local vid_start = comma_pos + 1
|
||||
// Skip whitespace
|
||||
loop(vid_start < tuple_json.size()) {
|
||||
loop(vid_start < tuple_json.length()) {
|
||||
local ch4 = tuple_json.charAt(vid_start)
|
||||
if ch4 != " " {
|
||||
break
|
||||
@ -224,7 +224,7 @@ static box ClosureCallHandlerBox {
|
||||
}
|
||||
|
||||
local vid_end = vid_start
|
||||
loop(vid_end < tuple_json.size()) {
|
||||
loop(vid_end < tuple_json.length()) {
|
||||
local ch5 = tuple_json.charAt(vid_end)
|
||||
if ch5 == "]" {
|
||||
break
|
||||
@ -265,10 +265,10 @@ static box ClosureCallHandlerBox {
|
||||
if start < 0 {
|
||||
return null
|
||||
}
|
||||
start = start + field_key.size()
|
||||
start = start + field_key.length()
|
||||
|
||||
// Skip whitespace
|
||||
loop(start < json.size()) {
|
||||
loop(start < json.length()) {
|
||||
local ch = json.charAt(start)
|
||||
if ch == " " {
|
||||
start = start + 1
|
||||
@ -282,7 +282,7 @@ static box ClosureCallHandlerBox {
|
||||
break
|
||||
}
|
||||
|
||||
if start >= json.size() {
|
||||
if start >= json.length() {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -294,7 +294,7 @@ static box ClosureCallHandlerBox {
|
||||
|
||||
// Extract integer vid
|
||||
local vid_end = start
|
||||
loop(vid_end < json.size()) {
|
||||
loop(vid_end < json.length()) {
|
||||
local ch2 = json.charAt(vid_end)
|
||||
if ch2 >= "0" {
|
||||
if ch2 <= "9" {
|
||||
|
||||
@ -25,7 +25,7 @@ static box ConstructorCallHandlerBox {
|
||||
return Result.Err("Unknown Box type: " + box_type)
|
||||
}
|
||||
|
||||
local argc = args_array.size()
|
||||
local argc = args_array.length()
|
||||
// Store instance before birth so `me` is available during initialization
|
||||
ValueManagerBox.set(regs, dst_reg, instance)
|
||||
// GC v0: metrics only(BoxBirthに近い位置で1カウント)
|
||||
|
||||
@ -178,27 +178,27 @@ static box CoreBridgeOps {
|
||||
if lb >= 0 {
|
||||
local rb = JsonFieldExtractor.seek_array_end != null ? JsonFieldExtractor.seek_array_end(inst_json, lb) : -1
|
||||
// Fallback: if JsonFieldExtractor provides no seek helper, approximate by using core reader later
|
||||
local arr = rb > lb ? inst_json.substring(lb+1, rb) : inst_json.substring(lb+1, inst_json.size())
|
||||
local arr = rb > lb ? inst_json.substring(lb+1, rb) : inst_json.substring(lb+1, inst_json.length())
|
||||
// Walk for numbers in pairs
|
||||
local pos = 0
|
||||
loop(pos < arr.size()) {
|
||||
loop(pos < arr.length()) {
|
||||
// look for '[' of a pair
|
||||
local c = arr.substring(pos,pos+1)
|
||||
if c != "[" { pos = pos + 1 continue }
|
||||
// bb
|
||||
pos = pos + 1
|
||||
// skip spaces
|
||||
loop(pos < arr.size()) { local ch = arr.substring(pos,pos+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue } break }
|
||||
loop(pos < arr.length()) { local ch = arr.substring(pos,pos+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue } break }
|
||||
// read first int (bb) — ignored here
|
||||
// advance to comma
|
||||
local comma = arr.indexOf(",", pos)
|
||||
if comma < 0 { break }
|
||||
pos = comma + 1
|
||||
loop(pos < arr.size()) { local ch2 = arr.substring(pos,pos+1) if ch2 == " " || ch2 == "\n" || ch2 == "\r" || ch2 == "\t" { pos = pos + 1 continue } break }
|
||||
loop(pos < arr.length()) { local ch2 = arr.substring(pos,pos+1) if ch2 == " " || ch2 == "\n" || ch2 == "\r" || ch2 == "\t" { pos = pos + 1 continue } break }
|
||||
// read vid digits
|
||||
local i = pos
|
||||
local ds = ""
|
||||
loop(i < arr.size()) { local ch3 = arr.substring(i,i+1) if ch3 >= "0" && ch3 <= "9" { ds = ds + ch3 i = i + 1 continue } break }
|
||||
loop(i < arr.length()) { local ch3 = arr.substring(i,i+1) if ch3 >= "0" && ch3 <= "9" { ds = ds + ch3 i = i + 1 continue } break }
|
||||
if ds != "" {
|
||||
local vid = ds + 0 // to i64 via implicit
|
||||
// populate candidate with current regs value or 0
|
||||
@ -332,7 +332,7 @@ static box CoreBridgeOps {
|
||||
return Result.Ok(0)
|
||||
}
|
||||
if method == "set" && ValueManagerBox.ensure_map_meta(regs, receiver_id) != null {
|
||||
if args_array.size() < 1 {
|
||||
if args_array.length() < 1 {
|
||||
return Result.Err("method(set): missing key argument")
|
||||
}
|
||||
local key_val = args_array.get(0)
|
||||
@ -354,7 +354,7 @@ static box CoreBridgeOps {
|
||||
// First arg id (key)
|
||||
using "lang/src/vm/hakorune-vm/args_extractor.hako" as ArgsExtractorBox
|
||||
local ids = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
if ids != null && ids.size() > 0 {
|
||||
if ids != null && ids.length() > 0 {
|
||||
local key_id = ids.get(0)
|
||||
local key_val = ValueManagerBox.get(regs, key_id)
|
||||
if key_val != null { NyVmState.set_reg(st, key_id, key_val) }
|
||||
@ -376,7 +376,7 @@ static box CoreBridgeOps {
|
||||
// Arg[0]
|
||||
using "lang/src/vm/hakorune-vm/args_extractor.hako" as ArgsExtractorBox
|
||||
local ids = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
if ids != null && ids.size() > 0 {
|
||||
if ids != null && ids.length() > 0 {
|
||||
local key_id = ids.get(0)
|
||||
local key_val = ValueManagerBox.get(regs, key_id)
|
||||
if key_val != null { NyVmState.set_reg(st, key_id, key_val) }
|
||||
@ -401,7 +401,7 @@ static box CoreBridgeOps {
|
||||
local ids2 = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
if ids2 != null {
|
||||
local i = 0
|
||||
loop(i < ids2.size()) {
|
||||
loop(i < ids2.length()) {
|
||||
local id = ids2.get(i)
|
||||
local val = ValueManagerBox.get(regs, id)
|
||||
if val != null { NyVmState.set_reg(st, id, val) }
|
||||
@ -417,11 +417,11 @@ static box CoreBridgeOps {
|
||||
}
|
||||
|
||||
try_modulefn_collection(name, mir_call_json, args_array, dst_reg, regs) {
|
||||
local want = me._canonical_modulefn_name(name, args_array.size())
|
||||
local want = me._canonical_modulefn_name(name, args_array.length())
|
||||
if want == "ArrayBox.len/0" {
|
||||
local ids = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
local recv_id = null
|
||||
if ids != null && ids.size() > 0 { recv_id = ids.get(0) }
|
||||
if ids != null && ids.length() > 0 { recv_id = ids.get(0) }
|
||||
local len = 0
|
||||
if recv_id != null { len = ValueManagerBox.get_array_size(regs, recv_id) }
|
||||
if dst_reg != null { ValueManagerBox.set(regs, dst_reg, len) }
|
||||
@ -430,7 +430,7 @@ static box CoreBridgeOps {
|
||||
if want == "MapBox.len/0" {
|
||||
local ids = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
local recv_id = null
|
||||
if ids != null && ids.size() > 0 { recv_id = ids.get(0) }
|
||||
if ids != null && ids.length() > 0 { recv_id = ids.get(0) }
|
||||
if recv_id != null { ValueManagerBox.ensure_map_meta(regs, recv_id) }
|
||||
local len = 0
|
||||
if recv_id != null { len = ValueManagerBox.get_map_len(regs, recv_id) }
|
||||
@ -441,7 +441,7 @@ static box CoreBridgeOps {
|
||||
if dst_reg == null { return Result.Err("modulefn(int_to_str): missing destination register") }
|
||||
using "lang/src/vm/hakorune-vm/args_extractor.hako" as ArgsExtractorBox
|
||||
local ids = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
if ids == null || ids.size() < 1 { return Result.Err("modulefn(int_to_str): missing arg") }
|
||||
if ids == null || ids.length() < 1 { return Result.Err("modulefn(int_to_str): missing arg") }
|
||||
local id0 = ids.get(0)
|
||||
local val0 = ValueManagerBox.get(regs, id0)
|
||||
local s = "" + val0
|
||||
@ -452,15 +452,15 @@ static box CoreBridgeOps {
|
||||
if dst_reg == null { return Result.Err("modulefn(to_i64): missing destination register") }
|
||||
using "lang/src/vm/hakorune-vm/args_extractor.hako" as ArgsExtractorBox
|
||||
local ids = ArgsExtractorBox.extract_ids(mir_call_json)
|
||||
if ids == null || ids.size() < 1 { return Result.Err("modulefn(to_i64): missing arg") }
|
||||
if ids == null || ids.length() < 1 { return Result.Err("modulefn(to_i64): missing arg") }
|
||||
local id0 = ids.get(0)
|
||||
local val0 = ValueManagerBox.get(regs, id0)
|
||||
local s = "" + val0
|
||||
// Allow optional sign + digits only
|
||||
local i = 0
|
||||
if s.size() > 0 && (s.substring(0,1) == "+" || s.substring(0,1) == "-") { i = 1 }
|
||||
local ok = (s.size() > i)
|
||||
loop(i < s.size()) {
|
||||
if s.length() > 0 && (s.substring(0,1) == "+" || s.substring(0,1) == "-") { i = 1 }
|
||||
local ok = (s.length() > i)
|
||||
loop(i < s.length()) {
|
||||
local ch = s.substring(i,i+1)
|
||||
if !(ch >= "0" && ch <= "9") { ok = false break }
|
||||
i = i + 1
|
||||
|
||||
@ -4,7 +4,7 @@ static box Main {
|
||||
// Usage: hakorune-vm-exe <mir.json>
|
||||
main(args) {
|
||||
local path = null
|
||||
if args { if args.size() > 0 { @p = args.get(0) if p { path = p } } }
|
||||
if args { if args.length() > 0 { @p = args.get(0) if p { path = p } } }
|
||||
if path == null {
|
||||
print("usage: hakorune-vm-exe <mir.json>")
|
||||
return -1
|
||||
|
||||
@ -26,7 +26,7 @@ static box GlobalCallHandlerBox {
|
||||
// Future: Support multiple types, string formatting
|
||||
_handle_print(args_array, dst_reg, regs) {
|
||||
// Check argument count
|
||||
local argc = args_array.size()
|
||||
local argc = args_array.length()
|
||||
if argc != 1 {
|
||||
return Result.Err("print: expected 1 argument, got " + StringHelpers.int_to_str(argc))
|
||||
}
|
||||
|
||||
@ -85,9 +85,9 @@ static box HakoruneVmCore {
|
||||
local k = r#""entry""#
|
||||
local p = func_json.indexOf(k)
|
||||
if p >= 0 {
|
||||
p = p + k.size()
|
||||
loop(p < func_json.size()) { local ch = func_json.substring(p,p+1) if ch == ":" { p = p + 1 break } if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
|
||||
loop(p < func_json.size()) { local ch = func_json.substring(p,p+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
|
||||
p = p + k.length()
|
||||
loop(p < func_json.length()) { local ch = func_json.substring(p,p+1) if ch == ":" { p = p + 1 break } if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
|
||||
loop(p < func_json.length()) { local ch = func_json.substring(p,p+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
|
||||
local digits = StringHelpers.read_digits(func_json, p)
|
||||
if digits != "" { current_bb = StringHelpers.to_i64(digits) }
|
||||
}
|
||||
@ -102,9 +102,9 @@ static box HakoruneVmCore {
|
||||
local key_id = "\"id\":"
|
||||
local is = first.indexOf(key_id)
|
||||
if is >= 0 {
|
||||
is = is + key_id.size()
|
||||
is = is + key_id.length()
|
||||
// skip ws
|
||||
loop(is < first.size()) {
|
||||
loop(is < first.length()) {
|
||||
local ch = first.substring(is, is+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { is = is + 1 continue }
|
||||
break
|
||||
@ -178,7 +178,7 @@ static box HakoruneVmCore {
|
||||
// No instructions (empty block)
|
||||
return Result.Ok(0)
|
||||
}
|
||||
insts_start = insts_start + key_insts.size()
|
||||
insts_start = insts_start + key_insts.length()
|
||||
// Find instructions array end
|
||||
local insts_end = JsonScanGuardBox.seek_array_end(block_json, insts_start - 1, 200000)
|
||||
if insts_end < 0 {
|
||||
@ -191,7 +191,7 @@ static box HakoruneVmCore {
|
||||
// Execute instructions sequentially
|
||||
_execute_instructions(insts_json, regs, mem) {
|
||||
local pos = 0
|
||||
local len = insts_json.size()
|
||||
local len = insts_json.length()
|
||||
local last_ret_value = 0
|
||||
loop(pos < len) {
|
||||
// Skip whitespace
|
||||
|
||||
@ -17,9 +17,9 @@ static box InstrsLocatorBox {
|
||||
meta0.set("content", "")
|
||||
return Result.Ok(meta0)
|
||||
}
|
||||
local i = k + key.size()
|
||||
local i = k + key.length()
|
||||
// find ':' then '['
|
||||
loop(i < block_json.size()) {
|
||||
loop(i < block_json.length()) {
|
||||
local ch = block_json.substring(i,i+1)
|
||||
if ch == ":" { i = i + 1 break }
|
||||
if ch == " " || ch == "
|
||||
@ -27,7 +27,7 @@ static box InstrsLocatorBox {
|
||||
" || ch == " " { i = i + 1 continue }
|
||||
return Result.Err("instructions key format invalid")
|
||||
}
|
||||
loop(i < block_json.size()) {
|
||||
loop(i < block_json.length()) {
|
||||
local ch = block_json.substring(i,i+1)
|
||||
if ch == " " || ch == "
|
||||
" || ch == "
|
||||
@ -59,12 +59,12 @@ static box InstrsLocatorBox {
|
||||
// slice content
|
||||
local content = block_json.substring(start, endi)
|
||||
// normalize if large
|
||||
if content.size() > 8192 { content = JsonNormalizeBox.normalize(content, 500000) }
|
||||
if content.length() > 8192 { content = JsonNormalizeBox.normalize(content, 500000) }
|
||||
// detect single-object fast path
|
||||
local single_flag = 0
|
||||
{
|
||||
local cs = 0
|
||||
local ce = content.size() - 1
|
||||
local ce = content.length() - 1
|
||||
loop(cs <= ce) {
|
||||
local ch2 = content.substring(cs, cs+1)
|
||||
if ch2 == " " || ch2 == "
|
||||
|
||||
@ -34,7 +34,7 @@ static box InstructionDispatcherBox {
|
||||
if op_start < 0 {
|
||||
return Result.Err("op field not found")
|
||||
}
|
||||
op_start = op_start + key_op.size()
|
||||
op_start = op_start + key_op.length()
|
||||
|
||||
local op_end = StringOps.index_of_from(inst_json, "\"", op_start)
|
||||
if op_end < 0 {
|
||||
|
||||
@ -15,9 +15,9 @@ static box JsonFieldExtractor {
|
||||
if start < 0 {
|
||||
return null
|
||||
}
|
||||
start = start + key.size()
|
||||
start = start + key.length()
|
||||
// skip whitespace
|
||||
loop(start < json.size()) {
|
||||
loop(start < json.length()) {
|
||||
local ch = json.substring(start, start+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { start = start + 1 continue }
|
||||
break
|
||||
@ -34,9 +34,9 @@ static box JsonFieldExtractor {
|
||||
local key_val = "\"value\":"
|
||||
local val_pos = StringOps.index_of_from(json, key_val, start)
|
||||
if val_pos >= 0 {
|
||||
val_pos = val_pos + key_val.size()
|
||||
val_pos = val_pos + key_val.length()
|
||||
// skip whitespace
|
||||
loop(val_pos < json.size()) {
|
||||
loop(val_pos < json.length()) {
|
||||
local ch2 = json.substring(val_pos, val_pos+1)
|
||||
if ch2 == " " || ch2 == "\n" || ch2 == "\r" || ch2 == "\t" { val_pos = val_pos + 1 continue }
|
||||
break
|
||||
@ -58,7 +58,7 @@ static box JsonFieldExtractor {
|
||||
if start < 0 {
|
||||
return null
|
||||
}
|
||||
start = start + key.size()
|
||||
start = start + key.length()
|
||||
|
||||
local end_pos = StringOps.index_of_from(json, "\"", start)
|
||||
if end_pos < 0 {
|
||||
|
||||
@ -6,7 +6,7 @@ using "lang/src/shared/json/core/string_scan.hako" as StringScanBox
|
||||
static box JsonNormalizeBox {
|
||||
normalize(seg, budget) {
|
||||
if seg == null { return "" }
|
||||
local n = seg.size()
|
||||
local n = seg.length()
|
||||
local i = 0
|
||||
local out = ""
|
||||
local steps = 0
|
||||
|
||||
@ -8,9 +8,9 @@ static box JsonScanGuardBox {
|
||||
// Returns: end index or -1 on failure/budget exceeded.
|
||||
seek_obj_end(text, start, budget) {
|
||||
if text == null { return -1 }
|
||||
if start < 0 || start >= text.size() { return -1 }
|
||||
if start < 0 || start >= text.length() { return -1 }
|
||||
if text.substring(start, start+1) != "{" { return -1 }
|
||||
local n = text.size()
|
||||
local n = text.length()
|
||||
local depth = 0
|
||||
local i = start
|
||||
local steps = 0
|
||||
@ -37,9 +37,9 @@ static box JsonScanGuardBox {
|
||||
// Returns: end index or -1 on failure/budget exceeded.
|
||||
seek_array_end(text, start, budget) {
|
||||
if text == null { return -1 }
|
||||
if start < 0 || start >= text.size() { return -1 }
|
||||
if start < 0 || start >= text.length() { return -1 }
|
||||
if text.substring(start, start+1) != "[" { return -1 }
|
||||
local n = text.size()
|
||||
local n = text.length()
|
||||
local depth = 0
|
||||
local i = start
|
||||
local steps = 0
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// MethodCallHandlerBox - Handle Method calls (MirCall with Method callee)
|
||||
// Single Responsibility: Execute instance methods (e.g., array.size(), string.substring())
|
||||
// Single Responsibility: Execute instance methods (e.g., array.length(), string.substring())
|
||||
|
||||
using "lang/src/vm/boxes/result_box.hako" as Result
|
||||
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
@ -39,11 +39,11 @@ static box MethodCallHandlerBox {
|
||||
|
||||
// Extract arguments from mir_call.args
|
||||
local args_array = ArgsExtractorBox.extract_and_load(mir_call_json, regs)
|
||||
local _g = ArgsGuardBox.ensure_no_nulls(args_array, method_name + "/" + StringHelpers.int_to_str(args_array.size()))
|
||||
local _g = ArgsGuardBox.ensure_no_nulls(args_array, method_name + "/" + StringHelpers.int_to_str(args_array.length()))
|
||||
if _g.is_Err() { return _g }
|
||||
|
||||
// Build signature and guard
|
||||
local arg_count = args_array.size()
|
||||
local arg_count = args_array.length()
|
||||
local method_sig = method_name + "/" + StringHelpers.int_to_str(arg_count)
|
||||
// Load receiver and guard
|
||||
local receiver = ValueManagerBox.get(regs, receiver_id)
|
||||
|
||||
@ -47,7 +47,7 @@ static box MirCallHandlerBox {
|
||||
if mir_call_start < 0 {
|
||||
return Result.Err("mir_call: mir_call field not found")
|
||||
}
|
||||
mir_call_start = mir_call_start + mir_call_key.size()
|
||||
mir_call_start = mir_call_start + mir_call_key.length()
|
||||
|
||||
// Find mir_call object end (using balanced bracket matching)
|
||||
// mir_call_start now points to '{' (first char of mir_call object)
|
||||
|
||||
@ -25,7 +25,7 @@ static box ModuleFunctionCallHandlerBox {
|
||||
// Future: Extend with more module functions as needed
|
||||
|
||||
local result_val
|
||||
local argc = args_array.size()
|
||||
local argc = args_array.length()
|
||||
local want_name = me._canonical_name(name, argc)
|
||||
|
||||
local core_shortcut = CoreBridgeOps.try_modulefn_collection(name, mir_call_json, args_array, dst_reg, regs)
|
||||
|
||||
@ -25,7 +25,7 @@ static box NewBoxHandlerBox {
|
||||
if type_start < 0 {
|
||||
return Result.Err("newbox: box_type field not found")
|
||||
}
|
||||
type_start = type_start + key_type.size()
|
||||
type_start = type_start + key_type.length()
|
||||
|
||||
local type_end = StringOps.index_of_from(inst_json, "\"", type_start)
|
||||
if type_end < 0 {
|
||||
|
||||
@ -19,7 +19,7 @@ static box PhiHandlerBox {
|
||||
// No instructions array (empty block)
|
||||
return Result.Ok(0)
|
||||
}
|
||||
insts_start = insts_start + key_insts.size()
|
||||
insts_start = insts_start + key_insts.length()
|
||||
|
||||
// Find instructions array end
|
||||
local insts_end = JsonCursorBox.seek_array_end(block_json, insts_start - 1)
|
||||
@ -31,7 +31,7 @@ static box PhiHandlerBox {
|
||||
|
||||
// Scan for PHI instructions
|
||||
local pos = 0
|
||||
local len = insts_json.size()
|
||||
local len = insts_json.length()
|
||||
|
||||
loop(pos < len) {
|
||||
// Skip whitespace and comma
|
||||
@ -77,7 +77,7 @@ static box PhiHandlerBox {
|
||||
// Returns: value_id or -1 if not found
|
||||
_find_phi_value(inputs_json, predecessor) {
|
||||
local pos = 0
|
||||
local len = inputs_json.size()
|
||||
local len = inputs_json.length()
|
||||
|
||||
loop(pos < len) {
|
||||
// Skip whitespace and comma
|
||||
@ -104,7 +104,7 @@ static box PhiHandlerBox {
|
||||
}
|
||||
|
||||
local block_str = pair_json.substring(0, comma_pos)
|
||||
local value_str = pair_json.substring(comma_pos + 1, pair_json.size())
|
||||
local value_str = pair_json.substring(comma_pos + 1, pair_json.length())
|
||||
|
||||
// Trim whitespace
|
||||
block_str = me._trim(block_str)
|
||||
@ -131,7 +131,7 @@ static box PhiHandlerBox {
|
||||
_find_array_end(json, start) {
|
||||
local depth = 0
|
||||
local pos = start
|
||||
local len = json.size()
|
||||
local len = json.length()
|
||||
|
||||
loop(pos < len) {
|
||||
local ch = json.substring(pos, pos + 1)
|
||||
@ -156,7 +156,7 @@ static box PhiHandlerBox {
|
||||
// Helper: trim whitespace
|
||||
_trim(str) {
|
||||
local start = 0
|
||||
local len = str.size()
|
||||
local len = str.length()
|
||||
|
||||
// Trim start
|
||||
loop(start < len) {
|
||||
|
||||
@ -25,7 +25,7 @@ static box TerminatorHandlerBox {
|
||||
return Result.Err("terminator not found")
|
||||
}
|
||||
|
||||
local term_json_start = term_start + key_term.size() - 1
|
||||
local term_json_start = term_start + key_term.length() - 1
|
||||
local term_end = me._find_terminator_end(block_json, term_json_start)
|
||||
if term_end < 0 {
|
||||
return Result.Err("terminator end not found")
|
||||
@ -42,9 +42,9 @@ static box TerminatorHandlerBox {
|
||||
if fb.is_Ok() { return fb }
|
||||
return Result.Err("terminator op not found")
|
||||
}
|
||||
pos = pos + key_opk.size()
|
||||
pos = pos + key_opk.length()
|
||||
// find ':' then skip whitespace
|
||||
loop(pos < term_json.size()) {
|
||||
loop(pos < term_json.length()) {
|
||||
local ch = term_json.substring(pos, pos+1)
|
||||
if ch == ":" { pos = pos + 1 break }
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue }
|
||||
@ -52,7 +52,7 @@ static box TerminatorHandlerBox {
|
||||
if fb.is_Ok() { return fb }
|
||||
return Result.Err("terminator op colon not found")
|
||||
}
|
||||
loop(pos < term_json.size()) {
|
||||
loop(pos < term_json.length()) {
|
||||
local ch = term_json.substring(pos, pos+1)
|
||||
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue }
|
||||
break
|
||||
@ -103,9 +103,9 @@ static box TerminatorHandlerBox {
|
||||
local k = "\"op\""
|
||||
local p = term_json.indexOf(k)
|
||||
if p < 0 { return Result.Err("terminator op not found") }
|
||||
p = p + k.size()
|
||||
loop(p < term_json.size()) { local ch = term_json.substring(p,p+1) if ch == ":" { p = p + 1 break } if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } return Result.Err("terminator op colon not found") }
|
||||
loop(p < term_json.size()) { local ch = term_json.substring(p,p+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
|
||||
p = p + k.length()
|
||||
loop(p < term_json.length()) { local ch = term_json.substring(p,p+1) if ch == ":" { p = p + 1 break } if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } return Result.Err("terminator op colon not found") }
|
||||
loop(p < term_json.length()) { local ch = term_json.substring(p,p+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
|
||||
if term_json.substring(p,p+1) != "\"" { return Result.Err("terminator op quote not found") }
|
||||
local e = StringOps.index_of_from(term_json, "\"", p+1)
|
||||
if e < 0 { return Result.Err("terminator op end not found") }
|
||||
@ -129,7 +129,7 @@ static box TerminatorHandlerBox {
|
||||
result_map.set("value", 0)
|
||||
return Result.Ok(result_map)
|
||||
}
|
||||
val_start = val_start + key_val.size()
|
||||
val_start = val_start + key_val.length()
|
||||
|
||||
local val_digits = StringHelpers.read_digits(term_json, val_start)
|
||||
if val_digits == "" {
|
||||
@ -171,7 +171,7 @@ static box TerminatorHandlerBox {
|
||||
_find_terminator_end(json, start) {
|
||||
local depth = 0
|
||||
local pos = start
|
||||
local len = json.size()
|
||||
local len = json.length()
|
||||
|
||||
loop(pos < len) {
|
||||
local ch = json.substring(pos, pos + 1)
|
||||
|
||||
@ -5,14 +5,14 @@ static box Main {
|
||||
if a.isEmpty() != 1 { print("FAIL: empty array not empty") return 1 }
|
||||
a.push(1)
|
||||
if a.isEmpty() != 0 { print("FAIL: non-empty array empty") return 1 }
|
||||
if a.size() != 1 { print("FAIL: array size!=1") return 1 }
|
||||
if a.length() != 1 { print("FAIL: array size!=1") return 1 }
|
||||
|
||||
// Map
|
||||
local m = new MapBox()
|
||||
if m.isEmpty() != 1 { print("FAIL: empty map not empty") return 1 }
|
||||
m.set("k", 10)
|
||||
if m.isEmpty() != 0 { print("FAIL: non-empty map empty") return 1 }
|
||||
if m.size() != 1 { print("FAIL: map size!=1") return 1 }
|
||||
if m.length() != 1 { print("FAIL: map size!=1") return 1 }
|
||||
|
||||
print("OK: Array/Map size/isEmpty")
|
||||
return 0
|
||||
|
||||
@ -39,9 +39,9 @@ static box Main {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Test 5: ArrayBox.size()
|
||||
// Test 5: ArrayBox.length()
|
||||
local test5 = me._test_array_size()
|
||||
print("[Test 5] ArrayBox.size() - result: " + StringHelpers.int_to_str(test5))
|
||||
print("[Test 5] ArrayBox.length() - result: " + StringHelpers.int_to_str(test5))
|
||||
if test5 != 0 {
|
||||
print("[FAIL] Test 5: expected 0, got " + StringHelpers.int_to_str(test5))
|
||||
return 1
|
||||
@ -55,9 +55,9 @@ static box Main {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Test 7: MapBox.size()
|
||||
// Test 7: MapBox.length()
|
||||
local test7 = me._test_map_size()
|
||||
print("[Test 7] MapBox.size() - result: " + StringHelpers.int_to_str(test7))
|
||||
print("[Test 7] MapBox.length() - result: " + StringHelpers.int_to_str(test7))
|
||||
if test7 != 0 {
|
||||
print("[FAIL] Test 7: expected 0, got " + StringHelpers.int_to_str(test7))
|
||||
return 1
|
||||
@ -164,9 +164,9 @@ static box Main {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Test 5: ArrayBox.size()
|
||||
// Test 5: ArrayBox.length()
|
||||
_test_array_size() {
|
||||
// MIR JSON: newbox ArrayBox -> v%2, const 10 -> v%3, boxcall v%2.push(v%3) -> v%4, const 20 -> v%5, boxcall v%2.push(v%5) -> v%6, boxcall v%2.size() -> v%1, ret v%1
|
||||
// MIR JSON: newbox ArrayBox -> v%2, const 10 -> v%3, boxcall v%2.push(v%3) -> v%4, const 20 -> v%5, boxcall v%2.push(v%5) -> v%6, boxcall v%2.length() -> v%1, ret v%1
|
||||
local mir_json = "{\"functions\":[{\"name\":\"Main.main\",\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"newbox\",\"dst\":2,\"box_type\":\"ArrayBox\",\"args\":[]},{\"op\":\"const\",\"dst\":3,\"value\":{\"Integer\":10}},{\"op\":\"boxcall\",\"dst\":4,\"box\":2,\"method\":\"push\",\"args\":[3]},{\"op\":\"const\",\"dst\":5,\"value\":{\"Integer\":20}},{\"op\":\"boxcall\",\"dst\":6,\"box\":2,\"method\":\"push\",\"args\":[5]},{\"op\":\"boxcall\",\"dst\":1,\"box\":2,\"method\":\"size\",\"args\":[]},{\"op\":\"copy\",\"dst\":7,\"src\":1}],\"terminator\":{\"op\":\"ret\",\"value\":7}}]}]}"
|
||||
|
||||
local vm_result = HakoruneVmCore.run(mir_json)
|
||||
@ -206,9 +206,9 @@ static box Main {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Test 7: MapBox.size()
|
||||
// Test 7: MapBox.length()
|
||||
_test_map_size() {
|
||||
// MIR JSON: newbox MapBox -> v%2, const "key1" -> v%3, const 100 -> v%4, boxcall v%2.set(v%3, v%4) -> v%5, const "key2" -> v%6, const 200 -> v%7, boxcall v%2.set(v%6, v%7) -> v%8, boxcall v%2.size() -> v%1, ret v%1
|
||||
// MIR JSON: newbox MapBox -> v%2, const "key1" -> v%3, const 100 -> v%4, boxcall v%2.set(v%3, v%4) -> v%5, const "key2" -> v%6, const 200 -> v%7, boxcall v%2.set(v%6, v%7) -> v%8, boxcall v%2.length() -> v%1, ret v%1
|
||||
local mir_json = "{\"functions\":[{\"name\":\"Main.main\",\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"newbox\",\"dst\":2,\"box_type\":\"MapBox\",\"args\":[]},{\"op\":\"const\",\"dst\":3,\"value\":{\"String\":\"key1\"}},{\"op\":\"const\",\"dst\":4,\"value\":{\"Integer\":100}},{\"op\":\"boxcall\",\"dst\":5,\"box\":2,\"method\":\"set\",\"args\":[3,4]},{\"op\":\"const\",\"dst\":6,\"value\":{\"String\":\"key2\"}},{\"op\":\"const\",\"dst\":7,\"value\":{\"Integer\":200}},{\"op\":\"boxcall\",\"dst\":8,\"box\":2,\"method\":\"set\",\"args\":[6,7]},{\"op\":\"boxcall\",\"dst\":1,\"box\":2,\"method\":\"size\",\"args\":[]},{\"op\":\"copy\",\"dst\":9,\"src\":1}],\"terminator\":{\"op\":\"ret\",\"value\":9}}]}]}"
|
||||
|
||||
local vm_result = HakoruneVmCore.run(mir_json)
|
||||
@ -250,7 +250,7 @@ static box Main {
|
||||
|
||||
// Test 9: MapBox.keys()
|
||||
_test_map_keys() {
|
||||
// MIR JSON: newbox MapBox -> v%2, const "a" -> v%3, const 1 -> v%4, boxcall v%2.set(v%3, v%4) -> v%5, const "b" -> v%6, const 2 -> v%7, boxcall v%2.set(v%6, v%7) -> v%8, boxcall v%2.keys() -> v%1, boxcall v%1.size() -> v%9, ret v%9
|
||||
// MIR JSON: newbox MapBox -> v%2, const "a" -> v%3, const 1 -> v%4, boxcall v%2.set(v%3, v%4) -> v%5, const "b" -> v%6, const 2 -> v%7, boxcall v%2.set(v%6, v%7) -> v%8, boxcall v%2.keys() -> v%1, boxcall v%1.length() -> v%9, ret v%9
|
||||
local mir_json = "{\"functions\":[{\"name\":\"Main.main\",\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"newbox\",\"dst\":2,\"box_type\":\"MapBox\",\"args\":[]},{\"op\":\"const\",\"dst\":3,\"value\":{\"String\":\"a\"}},{\"op\":\"const\",\"dst\":4,\"value\":{\"Integer\":1}},{\"op\":\"boxcall\",\"dst\":5,\"box\":2,\"method\":\"set\",\"args\":[3,4]},{\"op\":\"const\",\"dst\":6,\"value\":{\"String\":\"b\"}},{\"op\":\"const\",\"dst\":7,\"value\":{\"Integer\":2}},{\"op\":\"boxcall\",\"dst\":8,\"box\":2,\"method\":\"set\",\"args\":[6,7]},{\"op\":\"boxcall\",\"dst\":1,\"box\":2,\"method\":\"keys\",\"args\":[]},{\"op\":\"boxcall\",\"dst\":9,\"box\":1,\"method\":\"size\",\"args\":[]},{\"op\":\"copy\",\"dst\":10,\"src\":9}],\"terminator\":{\"op\":\"ret\",\"value\":10}}]}]}"
|
||||
|
||||
local vm_result = HakoruneVmCore.run(mir_json)
|
||||
|
||||
@ -13,7 +13,7 @@ static box Main {
|
||||
// mir_call new ArrayBox() → v1
|
||||
// const 42 → v2
|
||||
// mir_call v1.push(v2) → null
|
||||
// mir_call v1.size() → v3
|
||||
// mir_call v1.length() → v3
|
||||
// ret v3
|
||||
local mir1 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"mir_call","dst":1,"mir_call":{"callee":{"type":"Constructor","box_type":"ArrayBox"},"args":[],"effects":["alloc"],"flags":{}}},{"op":"const","dst":2,"value":{"type":"i64","value":42}},{"op":"mir_call","dst":null,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"push"},"args":[2],"effects":[],"flags":{}}},{"op":"mir_call","dst":3,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"size"},"args":[],"effects":[],"flags":{}}},{"op":"ret","value":3}],"terminator":{"op":"ret","value":3}}]}]}"#
|
||||
|
||||
@ -29,7 +29,7 @@ static box Main {
|
||||
// Test 2: new MapBox() - birth()なしConstructor
|
||||
// Block 0:
|
||||
// mir_call new MapBox() → v1
|
||||
// mir_call v1.size() → v2
|
||||
// mir_call v1.length() → v2
|
||||
// ret v2
|
||||
local mir2 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"mir_call","dst":1,"mir_call":{"callee":{"type":"Constructor","box_type":"MapBox"},"args":[],"effects":["alloc"],"flags":{}}},{"op":"mir_call","dst":2,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"size"},"args":[],"effects":[],"flags":{}}},{"op":"ret","value":2}],"terminator":{"op":"ret","value":2}}]}]}"#
|
||||
|
||||
@ -50,8 +50,8 @@ static box Main {
|
||||
// mir_call new ArrayBox() → v3
|
||||
// const 20 → v4
|
||||
// mir_call v3.push(v4) → null
|
||||
// mir_call v1.size() → v5
|
||||
// mir_call v3.size() → v6
|
||||
// mir_call v1.length() → v5
|
||||
// mir_call v3.length() → v6
|
||||
// binop Add v5+v6 → v7
|
||||
// ret v7
|
||||
local mir3 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"mir_call","dst":1,"mir_call":{"callee":{"type":"Constructor","box_type":"ArrayBox"},"args":[],"effects":["alloc"],"flags":{}}},{"op":"const","dst":2,"value":{"type":"i64","value":10}},{"op":"mir_call","dst":null,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"push"},"args":[2],"effects":[],"flags":{}}},{"op":"mir_call","dst":3,"mir_call":{"callee":{"type":"Constructor","box_type":"ArrayBox"},"args":[],"effects":["alloc"],"flags":{}}},{"op":"const","dst":4,"value":{"type":"i64","value":20}},{"op":"mir_call","dst":null,"mir_call":{"callee":{"type":"Method","receiver":3,"method":"push"},"args":[4],"effects":[],"flags":{}}},{"op":"mir_call","dst":5,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"size"},"args":[],"effects":[],"flags":{}}},{"op":"mir_call","dst":6,"mir_call":{"callee":{"type":"Method","receiver":3,"method":"size"},"args":[],"effects":[],"flags":{}}},{"op":"binop","op_kind":"Add","dst":7,"lhs":5,"rhs":6},{"op":"ret","value":7}],"terminator":{"op":"ret","value":7}}]}]}"#
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// test_mircall_phase2_method.hako — MirCall Phase 2 tests (Method)
|
||||
// Expected: Method calls (array.size(), string.substring(), etc.) work correctly
|
||||
// Expected: Method calls (array.length(), string.substring(), etc.) work correctly
|
||||
|
||||
using "lang/src/vm/hakorune-vm/hakorune_vm_core.hako" as HakoruneVmCore
|
||||
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
@ -8,23 +8,23 @@ static box Main {
|
||||
main() {
|
||||
print("=== MirCall Phase 2 Tests (Method) ===")
|
||||
|
||||
// Test 1: Array.size() - no arguments
|
||||
// Test 1: Array.length() - no arguments
|
||||
// Block 0:
|
||||
// newbox ArrayBox → v1
|
||||
// const 42 → v2
|
||||
// boxcall v1.push(v2) → null
|
||||
// mir_call v1.size() → v3
|
||||
// mir_call v1.length() → v3
|
||||
// ret v3
|
||||
local mir1 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"newbox","dst":1,"box_type":"ArrayBox","args":[]},{"op":"const","dst":2,"value":{"type":"i64","value":42}},{"op":"boxcall","dst":null,"box":1,"method":"push","args":[2]},{"op":"mir_call","dst":3,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"size"},"args":[],"effects":[],"flags":{}}},{"op":"ret","value":3}],"terminator":{"op":"ret","value":3}}]}]}"#
|
||||
|
||||
print("[Test 1] Array.size() - no arguments (expect 1)")
|
||||
print("[Test 1] Array.length() - no arguments (expect 1)")
|
||||
local result1 = HakoruneVmCore.run(mir1)
|
||||
print("Test 1 result: " + StringHelpers.int_to_str(result1))
|
||||
if result1 != 1 {
|
||||
print("[FAIL] Test 1: expected 1 (array size), got " + StringHelpers.int_to_str(result1))
|
||||
return 1
|
||||
}
|
||||
print("[PASS] Test 1: Array.size() works")
|
||||
print("[PASS] Test 1: Array.length() works")
|
||||
|
||||
// Test 2: Array.get(index) - single argument
|
||||
// Block 0:
|
||||
@ -51,7 +51,7 @@ static box Main {
|
||||
// const 1 → v2
|
||||
// const 4 → v3
|
||||
// mir_call v1.substring(v2, v3) → v4
|
||||
// boxcall v4.size() → v5
|
||||
// boxcall v4.length() → v5
|
||||
// ret v5
|
||||
local mir3 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"String":"hello"}},{"op":"const","dst":2,"value":{"type":"i64","value":1}},{"op":"const","dst":3,"value":{"type":"i64","value":4}},{"op":"mir_call","dst":4,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"substring"},"args":[2,3],"effects":[],"flags":{}}},{"op":"boxcall","dst":5,"box":4,"method":"size","args":[]},{"op":"ret","value":5}],"terminator":{"op":"ret","value":5}}]}]}"#
|
||||
|
||||
@ -64,7 +64,7 @@ static box Main {
|
||||
}
|
||||
print("[PASS] Test 3: String.substring(start, end) works")
|
||||
|
||||
// Test 4: Map.size() - method chaining pattern
|
||||
// Test 4: Map.length() - method chaining pattern
|
||||
// Block 0:
|
||||
// newbox MapBox → v1
|
||||
// const "key1" → v2
|
||||
@ -73,15 +73,15 @@ static box Main {
|
||||
// const "key2" → v4
|
||||
// const "value2" → v5
|
||||
// boxcall v1.set(v4, v5) → null
|
||||
// mir_call v1.size() → v6
|
||||
// mir_call v1.length() → v6
|
||||
// ret v6
|
||||
local mir4 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"newbox","dst":1,"box_type":"MapBox","args":[]},{"op":"const","dst":2,"value":{"String":"key1"}},{"op":"const","dst":3,"value":{"String":"value1"}},{"op":"boxcall","dst":null,"box":1,"method":"set","args":[2,3]},{"op":"const","dst":4,"value":{"String":"key2"}},{"op":"const","dst":5,"value":{"String":"value2"}},{"op":"boxcall","dst":null,"box":1,"method":"set","args":[4,5]},{"op":"mir_call","dst":6,"mir_call":{"callee":{"type":"Method","receiver":1,"method":"size"},"args":[],"effects":[],"flags":{}}},{"op":"ret","value":6}],"terminator":{"op":"ret","value":6}}]}]}"#
|
||||
|
||||
// Test 4 & 5: Skipped (Map methods have implementation gaps in Hakorune VM)
|
||||
// Note: Method calling mechanism WORKS - verified by Tests 1-3
|
||||
// Issue: Map.set()/Map.size() not fully functional in current Hakorune VM
|
||||
// Issue: Map.set()/Map.length() not fully functional in current Hakorune VM
|
||||
// This is a VM limitation, not a Method calling issue
|
||||
print("[Test 4] SKIPPED: Map.size() (VM limitation)")
|
||||
print("[Test 4] SKIPPED: Map.length() (VM limitation)")
|
||||
print("[Test 5] SKIPPED: Map.isEmpty() (VM limitation)")
|
||||
|
||||
print("=== MirCall Phase 2 (Method) CORE tests PASSED! (3/3 core) ===")
|
||||
|
||||
@ -29,7 +29,7 @@ static box Main {
|
||||
// Block 0:
|
||||
// const 0 → v1
|
||||
// mir_call StringHelpers.int_to_str(v1) → v2
|
||||
// boxcall v2.size() → v3
|
||||
// boxcall v2.length() → v3
|
||||
// ret v3
|
||||
local mir2 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"i64","value":0}},{"op":"mir_call","dst":2,"mir_call":{"callee":{"type":"ModuleFunction","name":"StringHelpers.int_to_str"},"args":[1],"effects":[],"flags":{}}},{"op":"boxcall","dst":3,"box":2,"method":"size","args":[]},{"op":"ret","value":3}],"terminator":{"op":"ret","value":3}}]}]}"#
|
||||
|
||||
@ -46,7 +46,7 @@ static box Main {
|
||||
// Block 0:
|
||||
// const 100 → v1
|
||||
// mir_call StringHelpers.int_to_str(v1) → v2
|
||||
// boxcall v2.size() → v3
|
||||
// boxcall v2.length() → v3
|
||||
// ret v3
|
||||
local mir3 = r#"{"functions":[{"name":"test","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"i64","value":100}},{"op":"mir_call","dst":2,"mir_call":{"callee":{"type":"ModuleFunction","name":"StringHelpers.int_to_str"},"args":[1],"effects":[],"flags":{}}},{"op":"boxcall","dst":3,"box":2,"method":"size","args":[]},{"op":"ret","value":3}],"terminator":{"op":"ret","value":3}}]}]}"#
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
static box Main {
|
||||
main() {
|
||||
local s = "Nyash"
|
||||
if s.size() != 5 { print("FAIL: size!=5") return 1 }
|
||||
if s.length() != 5 { print("FAIL: size!=5") return 1 }
|
||||
if s.isEmpty() { print("FAIL: isEmpty on non-empty") return 1 }
|
||||
if s.substring(0, 2) != "Ny" { print("FAIL: substring") return 1 }
|
||||
if s.charAt(2) != "a" { print("FAIL: charAt") return 1 }
|
||||
|
||||
@ -12,7 +12,7 @@ static box MiniJsonLoader {
|
||||
if s.substring(i, i+1) != "\"" { return "" }
|
||||
i = i + 1
|
||||
local out = ""
|
||||
local n = s.size()
|
||||
local n = s.length()
|
||||
loop (i < n) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch == "\"" { break }
|
||||
@ -39,7 +39,7 @@ static box MiniJsonLoader {
|
||||
}
|
||||
next_non_ws(s, pos) {
|
||||
local i = pos
|
||||
local n = s.size()
|
||||
local n = s.length()
|
||||
loop (i < n) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch != " " && ch != "\n" && ch != "\r" && ch != "\t" { return i }
|
||||
|
||||
@ -5,7 +5,7 @@ using "lang/src/vm/mini_vm_lib.hako" as MiniVm
|
||||
static box Main {
|
||||
main(args) {
|
||||
@json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":42}}}]}"
|
||||
if args { if args.size() > 0 { @s = args.get(0) if s { json = s } } }
|
||||
if args { if args.length() > 0 { @s = args.get(0) if s { json = s } } }
|
||||
return new MiniVm().run(json)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ static box MiniVm {
|
||||
@key = "\"value\":{\"type\":\"int\",\"value\":"
|
||||
@idx = json.lastIndexOf(key)
|
||||
if idx < 0 { return "0" }
|
||||
@start = idx + key.size()
|
||||
@start = idx + key.length()
|
||||
return me.read_digits(json, start)
|
||||
}
|
||||
run_branch(json) {
|
||||
@ -25,7 +25,7 @@ static box Main {
|
||||
@json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":1}}}]}"
|
||||
// If provided, override by argv[0]
|
||||
if args {
|
||||
if args.size() > 0 {
|
||||
if args.length() > 0 {
|
||||
@s = args.get(0)
|
||||
if s { json = s }
|
||||
}
|
||||
@ -39,7 +39,7 @@ function main(args) {
|
||||
@vm = new MiniVm()
|
||||
@json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":1}}}]}"
|
||||
if args {
|
||||
if args.size() > 0 {
|
||||
if args.length() > 0 {
|
||||
@s = args.get(0)
|
||||
if s { json = s }
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ static box MiniVm {
|
||||
@key = "\"value\":{\"type\":\"int\",\"value\":"
|
||||
@idx = json.lastIndexOf(key)
|
||||
if idx < 0 { return "0" }
|
||||
@start = idx + key.size()
|
||||
@start = idx + key.length()
|
||||
return me.read_digits(json, start)
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ static box Main {
|
||||
main(args) {
|
||||
// 既定の最小 MIR(JSON v0)
|
||||
local json = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":42}},{\"op\":\"ret\",\"value\":1}]}]}]}"
|
||||
if args != null { if args.size() > 0 { local s = args.get(0) if s != null { json = s } } }
|
||||
if args != null { if args.length() > 0 { local s = args.get(0) if s != null { json = s } } }
|
||||
local v = MirVmMin.run_min(json)
|
||||
print(MirVmMin._int_to_str(v))
|
||||
return 0
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
static box VMHotPathBox {
|
||||
enabled() {
|
||||
// Accept HAKO_VM_FAST_PATH=1|true|on (case-insensitive)
|
||||
local v = call("env.local.get/1", "HAKO_VM_FAST_PATH")
|
||||
local v = env.get("HAKO_VM_FAST_PATH")
|
||||
if !v { return 0 }
|
||||
local l = v.toLowerCase()
|
||||
if l == "1" || l == "true" || l == "on" { return 1 }
|
||||
|
||||
@ -3,9 +3,9 @@ using "lang/src/vm/mini_vm_lib.hako" as MiniVm
|
||||
static box Main {
|
||||
main(args) {
|
||||
@json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":42}}}]}"
|
||||
if args { if args.size() > 0 { @s = args.get(0) if s { json = s } } }
|
||||
if args { if args.length() > 0 { @s = args.get(0) if s { json = s } } }
|
||||
print("pre")
|
||||
print(json.size())
|
||||
print(json.length())
|
||||
print(json.indexOf("\"kind\":\"Program\""))
|
||||
print(json.indexOf("\"kind\":\"Print\""))
|
||||
print(json.indexOf("\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\""))
|
||||
|
||||
Reference in New Issue
Block a user