Phase 20.34: expand MirBuilder internal library with comprehensive lowering boxes; add pattern registry and program scanning infrastructure; implement internal lowerers for if/loop/return patterns; add dev tools and comprehensive canary tests; update VM boxes and host providers for internal delegation; wire phase2034 test suite with 30+ canary scripts covering internal lowering scenarios

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
nyash-codex
2025-11-03 16:09:19 +09:00
parent 8827b8d416
commit a4f30ae827
89 changed files with 4125 additions and 115 deletions

View File

@ -6,10 +6,86 @@ using selfhost.shared.json.core.json_cursor as JsonCursorBox
using selfhost.shared.common.string_helpers as StringHelpers
static box JsonFragBox {
// 基本ヘルパ
index_of_from(hay, needle, pos) { return JsonCursorBox.index_of_from(hay, needle, pos) }
// 基本ヘルパ - VM fallback implementations for cross-box static calls
index_of_from(hay, needle, pos) {
// VM fallback: implement using substring + indexOf
if hay == null || needle == null { return -1 }
local s = "" + hay
local n = s.length()
local p2 = pos
if p2 < 0 { p2 = 0 }
if p2 >= n { return -1 }
// Extract substring from pos onwards
local substr = s.substring(p2, n)
// Find needle in substring
local idx = substr.indexOf(needle)
if idx < 0 { return -1 }
return p2 + idx
}
read_digits(text, pos) { return StringHelpers.read_digits(text, pos) }
_str_to_int(s) { return StringHelpers.to_i64(s) }
_to_bool10(ch) { if ch == "t" { return 1 } if ch == "f" { return 0 } return null }
// Read helpers (pos-based)
read_int_from(text, pos) {
if text == null { return null }
local s = "" + text
local i = pos
local n = s.length()
loop(i < n) { if s.substring(i,i+1) != " " { break } i = i + 1 }
local j = i
if j < n && (s.substring(j,j+1) == "-" || s.substring(j,j+1) == "+") { j = j + 1 }
local had = 0
loop(j < n) {
local ch = s.substring(j,j+1)
if ch >= "0" && ch <= "9" { had = 1 j = j + 1 } else { break }
}
if had == 0 { return null }
return s.substring(i, j)
}
read_bool_from(text, pos) {
if text == null { return null }
local s = "" + text
local i = pos
local n = s.length()
loop(i < n) { if s.substring(i,i+1) != " " { break } i = i + 1 }
if i < n { return me._to_bool10(s.substring(i,i+1)) }
return null
}
read_string_from(text, pos) {
if text == null { return null }
local s = "" + text
local i = pos
local n = s.length()
// Find opening quote
loop(i < n) { if s.substring(i,i+1) == "\"" { i = i + 1 break } if s.substring(i,i+1) != " " { break } i = i + 1 }
local j = i
loop(j < n) { if s.substring(j,j+1) == "\"" { break } j = j + 1 }
if j <= i { return null }
return s.substring(i, j)
}
read_float_from(text, pos) {
if text == null { return null }
local s = "" + text
local i = pos
local n = s.length()
loop(i < n) { if s.substring(i,i+1) != " " { break } i = i + 1 }
local j = i
if j < n && (s.substring(j,j+1) == "+" || s.substring(j,j+1) == "-") { j = j + 1 }
local had = 0
loop(j < n) {
local ch = s.substring(j,j+1)
if (ch >= "0" && ch <= "9") || ch == "." { had = 1 j = j + 1 } else { break }
}
if had == 0 { return null }
return s.substring(i, j)
}
// Read helpers (key-based, start at keyPos)
read_int_after(text, key_pos) { return me.read_int_from(text, key_pos) }
read_bool_after(text, key_pos) { return me.read_bool_from(text, key_pos) }
read_string_after(text, key_pos) { return me.read_string_from(text, key_pos) }
read_float_after(text, key_pos) { return me.read_float_from(text, key_pos) }
// key に続く数値(最初の一致)を返す。見つからなければ null。
get_int(seg, key) {
@ -22,13 +98,61 @@ static box JsonFragBox {
return null
}
// Scan for closing quote (VM fallback for scan_string_end)
_scan_string_end(text, quote_pos) {
// quote_pos is the position of opening quote
// Return position of closing quote, or -1 if not found
if text == null { return -1 }
local s = "" + text
local n = s.length()
local i = quote_pos + 1
loop(i < n) {
local ch = s.substring(i, i+1)
if ch == "\"" { return i }
if ch == "\\" {
i = i + 1 // Skip escaped character
if i >= n { return -1 }
}
i = i + 1
}
return -1
}
// Seek matching closing bracket (VM fallback for seek_array_end)
_seek_array_end(text, lbracket_pos) {
// lbracket_pos is the position of '['
// Return position of matching ']', or -1 if not found
if text == null { return -1 }
local s = "" + text
local n = s.length()
local depth = 0
local i = lbracket_pos
local in_str = 0
loop(i < n) {
local ch = s.substring(i, i+1)
if in_str == 1 {
if ch == "\"" { in_str = 0 }
if ch == "\\" { i = i + 1 } // Skip escaped char
} else {
if ch == "\"" { in_str = 1 }
if ch == "[" { depth = depth + 1 }
if ch == "]" {
depth = depth - 1
if depth == 0 { return i }
}
}
i = i + 1
}
return -1
}
// key に続く "..." の文字列(最初の一致)を返す。見つからなければ空文字。
get_str(seg, key) {
local pat = "\"" + key + "\":\""
local p = me.index_of_from(seg, pat, 0)
if p >= 0 {
local vstart = p + pat.length() // start of value (right after opening quote)
local vend = JsonCursorBox.scan_string_end(seg, vstart - 1)
local vend = me._scan_string_end(seg, vstart - 1)
if vend > vstart { return seg.substring(vstart, vend) }
}
return ""
@ -62,7 +186,7 @@ static box JsonFragBox {
// '[' position
local arr_bracket = pk + key.length() - 1
// Use escape-aware scanner to find matching ']'
local endp = JsonCursorBox.seek_array_end(mjson, arr_bracket)
local endp = me._seek_array_end(mjson, arr_bracket)
if endp < 0 { return "" }
return mjson.substring(arr_bracket + 1, endp)
}