2025-10-31 20:45:46 +09:00
// mini_collections.hako — Minimal collection boxes for selfhost VM tests
// Simple string-backed dynamic array of i64 (for smoke/testing)
box MiniArray {
field data: String
birth() { me.data = "" return 0 }
push(v) {
2025-11-04 16:50:59 +09:00
using selfhost.vm.hakorune-vm.str_cast as StrCast
v = StrCast.to_str(v)
2025-10-31 20:45:46 +09:00
if me.data == "" { me.data = v } else { me.data = me.data + "," + v }
return 0
}
length() {
if me.data == "" { return 0 }
// count commas + 1
local s = me.data
local i = 0
local c = 1
loop(true) {
local j = s.indexOf(",", i)
if j < 0 { break }
c = c + 1
i = j + 1
}
return c
}
// Fail‑ Fast accessor: returns element string; prints error and returns 0 on OOB
at(index) {
// normalize and validate index
2025-11-04 16:50:59 +09:00
using selfhost.shared.common.string_helpers as StringHelpers
local si = StringHelpers.int_to_str(index)
2025-10-31 20:45:46 +09:00
local idx = 0
if si != "" {
local i = 0
2025-11-01 13:28:56 +09:00
loop(i < si.length()) { idx = idx * 10 + ("0123456789".indexOf(si.substring(i,i+1))) i = i + 1 }
2025-10-31 20:45:46 +09:00
}
local n = me.length()
2025-11-04 16:50:59 +09:00
if idx < 0 || idx >= n { print("[ERROR] MiniArray.at: index out of range: " + StringHelpers.int_to_str(idx) + "/" + StringHelpers.int_to_str(n)) return 0 }
2025-10-31 20:45:46 +09:00
// find start position of idx-th element
local s = me.data
local pos = 0
local cur = 0
loop(cur < idx) {
local j = s.indexOf(",", pos)
if j < 0 { print("[ERROR] MiniArray.at: broken storage") return 0 }
pos = j + 1
cur = cur + 1
}
local endp = s.indexOf(",", pos)
2025-11-01 13:28:56 +09:00
if endp < 0 { endp = s.length() }
2025-10-31 20:45:46 +09:00
return s.substring(pos, endp)
}
}
// Simple string-backed map (key->value as 'k=v\n')
box MiniMap2 {
field store: String
birth() { me.store = "" return 0 }
set(key, value) {
key = "" + key
value = "" + value
// Guard for unsupported characters in key that break line format
if key.indexOf("\n") >= 0 || key.indexOf("=") >= 0 {
print("[ERROR] MiniMap2.set: invalid key contains newline or '='")
return 0
}
// remove and append
local out = ""
local s = me.store
local pos = 0
loop(true) {
local nl = s.indexOf("\n", pos)
if nl < 0 { break }
local line = s.substring(pos, nl)
local eq = line.indexOf("=")
if eq >= 0 {
local k = line.substring(0, eq)
if k != key { out = out + line + "\n" }
}
pos = nl + 1
}
me.store = out + key + "=" + value + "\n"
return 0
}
get(key) {
key = "" + key
local s = me.store
local pos = 0
loop(true) {
local nl = s.indexOf("\n", pos)
if nl < 0 { break }
local line = s.substring(pos, nl)
local eq = line.indexOf("=")
if eq >= 0 {
local k = line.substring(0, eq)
2025-11-01 13:28:56 +09:00
if k == key { return line.substring(eq + 1, line.length()) }
2025-10-31 20:45:46 +09:00
}
pos = nl + 1
}
return null
}
// Strict getter: Fail‑ Fast when key is missing; returns 0 on failure
get_or_fail(key) {
key = "" + key
local v = me.get(key)
if v == null { print("[ERROR] MiniMap2.get: key not found: " + key) return 0 }
return v
}
has(key) {
key = "" + key
local s = me.store
if s == "" { return 0 }
// naive contains of 'key=' at line start or after \n
local needle = key + "="
2025-11-01 13:28:56 +09:00
if s.substring(0, needle.length()) == needle { return 1 }
2025-10-31 20:45:46 +09:00
local p = s.indexOf("\n" + needle)
if p >= 0 { return 1 }
return 0
}
size() {
if me.store == "" { return 0 }
local s = me.store
local i = 0
local c = 0
loop(true) {
local nl = s.indexOf("\n", i)
if nl < 0 { break }
c = c + 1
i = nl + 1
}
return c
}
}