Files
hakorune/apps/selfhost-vm/boxes/mini_vm_scan.nyash

174 lines
4.8 KiB
Plaintext
Raw Normal View History

// Mini-VM scanning and numeric helpers
static box MiniVmScan {
// helper: find needle from position pos
index_of_from(hay, needle, pos) {
local tail = hay.substring(pos, hay.length())
local rel = tail.indexOf(needle)
if rel < 0 { return -1 } else { return pos + rel }
}
// helper: find balanced bracket range [ ... ] starting at idx (points to '[')
find_balanced_array_end(json, idx) {
local n = json.length()
if json.substring(idx, idx+1) != "[" { return -1 }
local depth = 0
local i = idx
loop (i < n) {
local ch = json.substring(i, i+1)
if ch == "[" { depth = depth + 1 }
if ch == "]" {
depth = depth - 1
if depth == 0 { return i }
}
i = i + 1
}
return -1
}
// helper: find balanced object range { ... } starting at idx (points to '{')
find_balanced_object_end(json, idx) {
local n = json.length()
if json.substring(idx, idx+1) != "{" { return -1 }
local depth = 0
local i = idx
loop (i < n) {
local ch = json.substring(i, i+1)
if ch == "{" { depth = depth + 1 }
if ch == "}" {
depth = depth - 1
if depth == 0 { return i }
}
i = i + 1
}
return -1
}
_str_to_int(s) {
local i = 0
local n = s.length()
local acc = 0
loop (i < n) {
local ch = s.substring(i, i+1)
if ch == "0" { acc = acc * 10 + 0 i = i + 1 continue }
if ch == "1" { acc = acc * 10 + 1 i = i + 1 continue }
if ch == "2" { acc = acc * 10 + 2 i = i + 1 continue }
if ch == "3" { acc = acc * 10 + 3 i = i + 1 continue }
if ch == "4" { acc = acc * 10 + 4 i = i + 1 continue }
if ch == "5" { acc = acc * 10 + 5 i = i + 1 continue }
if ch == "6" { acc = acc * 10 + 6 i = i + 1 continue }
if ch == "7" { acc = acc * 10 + 7 i = i + 1 continue }
if ch == "8" { acc = acc * 10 + 8 i = i + 1 continue }
if ch == "9" { acc = acc * 10 + 9 i = i + 1 continue }
break
}
return acc
}
_digit_char(d) {
if d == 0 { return "0" }
if d == 1 { return "1" }
if d == 2 { return "2" }
if d == 3 { return "3" }
if d == 4 { return "4" }
if d == 5 { return "5" }
if d == 6 { return "6" }
if d == 7 { return "7" }
if d == 8 { return "8" }
if d == 9 { return "9" }
return "0"
}
_int_to_str(n) {
if n == 0 { return "0" }
local v = n
local out = ""
loop (v > 0) {
local d = v % 10
local ch = _digit_char(d)
out = ch + out
v = v / 10
}
return out
}
// Read digit runs starting at pos
read_digits(json, pos) {
local out = ""
loop (true) {
local s = json.substring(pos, pos+1)
if s == "" { break }
if s == "0" { out = out + s pos = pos + 1 continue }
if s == "1" { out = out + s pos = pos + 1 continue }
if s == "2" { out = out + s pos = pos + 1 continue }
if s == "3" { out = out + s pos = pos + 1 continue }
if s == "4" { out = out + s pos = pos + 1 continue }
if s == "5" { out = out + s pos = pos + 1 continue }
if s == "6" { out = out + s pos = pos + 1 continue }
if s == "7" { out = out + s pos = pos + 1 continue }
if s == "8" { out = out + s pos = pos + 1 continue }
if s == "9" { out = out + s pos = pos + 1 continue }
break
}
return out
}
// Linear pass: sum all numbers outside of quotes
sum_numbers_no_quotes(json) {
local i = 0
local n = json.length()
local total = 0
loop (i < n) {
local ch = json.substring(i, i+1)
if ch == "\"" {
local j = index_of_from(json, "\"", i+1)
if j < 0 { break }
i = j + 1
continue
}
local d = read_digits(json, i)
if d { total = total + _str_to_int(d) i = i + d.length() continue }
i = i + 1
}
return _int_to_str(total)
}
// Naive: sum all digit runs anywhere
sum_all_digits_naive(json) {
local i = 0
local n = json.length()
local total = 0
loop (i < n) {
local d = read_digits(json, i)
if d { total = total + _str_to_int(d) i = i + d.length() continue }
i = i + 1
}
return _int_to_str(total)
}
// Sum first two integers outside quotes; returns string or empty
sum_first_two_numbers(json) {
local i = 0
local n = json.length()
local total = 0
local found = 0
loop (i < n) {
local ch = json.substring(i, i+1)
if ch == "\"" {
local j = index_of_from(json, "\"", i+1)
if j < 0 { break }
i = j + 1
continue
}
local d = read_digits(json, i)
if d {
total = total + _str_to_int(d)
found = found + 1
i = i + d.length()
if found >= 2 { return _int_to_str(total) }
continue
}
i = i + 1
}
return ""
}
}