feat(parser): Phase 25.1c dev-only progress guard実装

Task 8-4: ParserBox.parse_program2ハング調査のため、開発専用の進捗ガード実装

**実装内容**:
- HAKO_PARSER_PROG_MAX環境変数で最大反復回数を設定可能
- デフォルト挙動は完全不変(max_prog=0=無制限)
- 数値パースは安全実装(不正値→0扱い)
- トレースモード時のみガード到達をログ出力

**Phase 25ポリシー準拠**:
- 仕様変更なし(dev-onlyオプトイン)
- 既存コード完全互換
- 無効値は静かに無視(デフォルト挙動維持)

**調査状況**:
- Hotfix 8適用後、Stage-Bトレースは after_build_body_src まで出力
- parse_program2に入っておらず、パーサートレース未出現
- trace_enabled()呼び出し前後のハング疑惑を調査中

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-19 05:48:51 +09:00
parent dad278caf2
commit 8054875261

View File

@ -270,7 +270,42 @@ box ParserBox {
local first = 1
local cont_prog = 1
// Dev-only program-level progress guard (Phase 25.1c):
// - Enabled when HAKO_PARSER_PROG_MAX > 0
// - Protects StageB/selfhost callers from infinite top-level loops on malformed input
local guard_prog = 0
local max_prog = 0
{
local m = env.get("HAKO_PARSER_PROG_MAX")
if m != null {
// Safely parse to int; invalid values are treated as 0 (disabled)
local mv = 0
local ok = 0
// Minimal numeric parse: allow decimal digits only
local ms = "" + m
local mi = 0
local ml = ms.length()
loop(mi < ml) {
local chm = ms.substring(mi, mi + 1)
if chm < "0" || chm > "9" { ok = 0 break }
if ok == 0 { ok = 1 }
mv = mv * 10 + me.to_int(chm)
mi = mi + 1
}
if ok == 1 && mv > 0 { max_prog = mv }
}
}
loop(cont_prog == 1) {
if max_prog > 0 {
guard_prog = guard_prog + 1
if guard_prog > max_prog {
if trace == 1 {
print("[parser/program2:guard] max iteration reached at pos=" + ("" + i))
}
cont_prog = 0
}
}
if trace == 1 {
local kind = "Stmt"
if i >= n {