Files
hakorune/apps/selfhost/common/mini_vm_scan.nyash

206 lines
5.5 KiB
Plaintext

// Mini-VM scanning and numeric helpers
static box MiniVmScan {
// helper: find needle from position pos
index_of_from(hay, needle, pos) {
// Guard position; clamp to valid range to avoid negative substring
if pos < 0 { pos = 0 }
local n = hay.length()
if pos >= n { return -1 }
local m = needle.length()
if m <= 0 { return pos }
local i = pos
local limit = n - m
loop (i <= limit) {
local seg = hay.substring(i, i + m)
if seg == needle { return i }
i = i + 1
}
return -1
}
// helper: find balanced bracket range [ ... ] starting at idx (points to '[')
find_balanced_array_end(json, idx) {
@n = json.length()
if json.substring(idx, idx+1) != "[" { return -1 }
@depth = 0
@i = idx
@in_str = 0
@guard = 0
loop (i < n) {
guard = guard + 1
if guard > 50000 { return -1 }
@ch = json.substring(i, i+1)
if in_str == 1 {
if ch == "\\" { i = i + 2 continue }
if ch == "\"" { in_str = 0 i = i + 1 continue }
i = i + 1
continue
}
if ch == "\"" { in_str = 1 i = i + 1 continue }
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) {
@n = json.length()
if json.substring(idx, idx+1) != "{" { return -1 }
@depth = 0
@i = idx
@in_str = 0
@guard = 0
loop (i < n) {
guard = guard + 1
if guard > 50000 { return -1 }
@ch = json.substring(i, i+1)
if in_str == 1 {
if ch == "\\" { i = i + 2 continue }
if ch == "\"" { in_str = 0 i = i + 1 continue }
i = i + 1
continue
}
if ch == "\"" { in_str = 1 i = i + 1 continue }
if ch == "{" { depth = depth + 1 }
if ch == "}" {
depth = depth - 1
if depth == 0 { return i }
}
i = i + 1
}
return -1
}
_str_to_int(s) {
@i = 0
@n = s.length()
@acc = 0
loop (i < n) {
@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" }
@v = n
@out = ""
loop (v > 0) {
@d = v % 10
@ch = _digit_char(d)
out = ch + out
v = v / 10
}
return out
}
// Read digit runs starting at pos
read_digits(json, pos) {
@out = ""
loop (true) {
@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) {
@i = 0
@n = json.length()
@total = 0
loop (i < n) {
@ch = json.substring(i, i+1)
if ch == "\"" {
@j = index_of_from(json, "\"", i+1)
if j < 0 { break }
i = j + 1
continue
}
@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) {
@i = 0
@n = json.length()
@total = 0
loop (i < n) {
@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) {
@i = 0
@n = json.length()
@total = 0
local found = 0
loop (i < n) {
@ch = json.substring(i, i+1)
if ch == "\"" {
@j = index_of_from(json, "\"", i+1)
if j < 0 { break }
i = j + 1
continue
}
@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 ""
}
}