Gate‑C(Core) OOB strict fail‑fast; String VM handler normalization; JSON lint Stage‑B root fixes via scanner field boxing and BinOp operand slotify; docs + smokes update

This commit is contained in:
nyash-codex
2025-11-01 18:45:26 +09:00
parent c331296552
commit 47bd2d2ee2
15 changed files with 280 additions and 107 deletions

View File

@ -16,6 +16,7 @@ box JsonScanner {
length: IntegerBox // 文字列長
line: IntegerBox // 現在行番号
column: IntegerBox // 現在列番号
_tmp_pos: IntegerBox // 一時保持(ループ跨ぎの開始位置など)
birth(input_text) {
me.text = input_text
@ -23,6 +24,7 @@ box JsonScanner {
me.length = input_text.length()
me.line = 1
me.column = 1
me._tmp_pos = 0
}
// Runtime-safe initializer (bypass constructor arg loss on some VM paths)
@ -32,6 +34,7 @@ box JsonScanner {
me.length = input_text.length()
me.line = 1
me.column = 1
me._tmp_pos = 0
}
// ===== 基本読み取りメソッド =====
@ -205,7 +208,8 @@ box JsonScanner {
// 条件を満たす間読み取り続ける
read_while(condition_fn) {
local start_pos = me.position
// ループ内で参照する開始位置はフィールドに退避PHIに依存しない箱化
me._tmp_pos = me.position
loop(not me.is_eof()) {
local ch = me.current()
@ -215,24 +219,24 @@ box JsonScanner {
me.advance()
}
return me.text.substring(start_pos, me.position)
return me.text.substring(me._tmp_pos, me.position)
}
// 識別子を読み取り(英数字+アンダースコア)
read_identifier() {
local start_pos = me.position
me._tmp_pos = me.position
if not me.is_alpha_char(me.current()) and me.current() != "_" {
return ""
}
loop(not me.is_eof() and me.is_alphanumeric_or_underscore(me.current())) {
me.advance()
}
return me.text.substring(start_pos, me.position)
return me.text.substring(me._tmp_pos, me.position)
}
// 数値文字列を読み取り
read_number() {
local start_pos = me.position
me._tmp_pos = me.position
// マイナス符号
if me.current() == "-" {
@ -283,7 +287,7 @@ box JsonScanner {
}
}
return me.text.substring(start_pos, me.position)
return me.text.substring(me._tmp_pos, me.position)
}
// 文字列リテラルを読み取り(クォート含む)
@ -304,10 +308,11 @@ box JsonScanner {
// 終了クォート
me.advance()
// Safety: literal must include both quotes → length >= 2
if me.position - start_pos < 2 {
// PHIに依存せず、開始位置はフィールドから読む
if me.position - me._tmp_pos < 2 {
return null
}
return me.text.substring(start_pos, me.position)
return me.text.substring(me._tmp_pos, me.position)
} else {
if ch == "\\" {
// エスケープシーケンス