feat(phase71-ssa): SSA undef 完全解消達成!(4件→0件)

## Phase 71-SSA SSA undef 削減 完全達成!

### 🎉 成果
- **SSA undef**: 4件 → **0件** (100%解消!)
- **所要時間**: 約2時間 (Task先生調査 + 実装 + 検証)
- **修正ファイル**: 3ファイル (.hako実装のみ、MIR/SSAビルダー不変)

### 🔍 根本原因 (Task先生による徹底分析)
**ValueId(272) = StringHelpers.starts_with_kw/3 の戻り値**
- static boxの委譲でValueIdマッピング失敗
- 引数パラメータ設定ログが一切出力されず
- 別関数の戻り値ValueIdが誤って引数として参照される

### 🛠️ 修正内容

**修正1: ParserStringUtilsBox.trim (Quick Win)**
- L76: `StringHelpers.skip_ws` → `ParserStringUtilsBox.skip_ws`
- 効果: SSA undef 4件 → 2件
- 副次効果: Main._parse_number/ParserBox.parse_block2 消滅

**修正2: ParserCommonUtilsBox.trim (修正案A)**
- L50-69: 委譲を廃止、直接実装に変更
- FuncScannerBox.trimの成功パターンを適用

**修正3: ParserBox.trim (修正案A)**
- L81-98: 委譲を廃止、直接実装に変更
- 効果: 残り2件のSSA undef完全解消

###  検証結果
```bash
grep -c 'ssa-undef-debug' logs/selfhost/stageb_20251202_111409_2674670.log
# 出力: 0 ← 🎉 完全解消!
```

### 📊 SSA undef 推移
| フェーズ | 件数 | 詳細 |
|---------|------|------|
| Phase 71初回 | 4件 | trim×2, _parse_number, parse_block2 |
| Quick Win後 | 2件 | trim×2 (予想外: 他2件消滅) |
| 修正案A後 | **0件** | 🎉 **完全解消!** |

### 🎯 残存課題 (次フェーズ)
1. dev verify警告: 1件 (StageBDriverBox birth)
2. Program JSON未出力: extract_ok=0 (rc=0だが行なし)

### 💡 重要な教訓
- static boxの委譲は危険 (ValueIdマッピング失敗)
- 静的呼び出し (BoxName.method) が SSA-friendly
- 成功パターン (FuncScannerBox.trim) の積極活用

### 📝 ドキュメント
- 詳細レポート: phase71-ssa-trim-fix-20251202.md
- Task先生分析: ValueId(272)特定、修正案A-C提案

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-02 11:16:01 +09:00
parent 13ce9e6888
commit 4b3eb6b3a9
4 changed files with 285 additions and 5 deletions

View File

@ -78,7 +78,24 @@ box ParserBox {
index_of(src, i, pat) { return ParserStringUtilsBox.index_of(src, i, pat) }
trim(s) { return ParserStringUtilsBox.trim(s) }
trim(s) {
// Phase 71-SSA: Direct implementation to avoid ValueId mapping issue in static box delegation
if s == null { return "" }
local str = "" + s
local n = str.length()
local b = ParserStringUtilsBox.skip_ws(str, 0)
if b >= n { return "" }
local e = n
loop(e > b) {
local ch = str.substring(e - 1, e)
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" || ch == ";" { e = e - 1 } else { break }
}
if e > b { return str.substring(b, e) }
return ""
}
starts_with_kw(src, i, kw) { return ParserStringUtilsBox.starts_with_kw(src, i, kw) }

View File

@ -48,8 +48,24 @@ static box ParserCommonUtilsBox {
}
trim(s) {
// Delegate to string_utils to keep SSA/semantic consistency.
return ParserStringUtilsBox.trim(s)
// Phase 71-SSA: Direct implementation to avoid ValueId mapping issue in static box delegation
if s == null { return "" }
local str = "" + s
local n = str.length()
// Leading whitespace: use static method to avoid SSA undef
local b = ParserStringUtilsBox.skip_ws(str, 0)
if b >= n { return "" }
// Trailing whitespace: walk backwards until a non-space is found.
local e = n
loop(e > b) {
local ch = str.substring(e - 1, e)
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" || ch == ";" { e = e - 1 } else { break }
}
if e > b { return str.substring(b, e) }
return ""
}
esc_json(s) {

View File

@ -72,8 +72,8 @@ static box ParserStringUtilsBox {
local str = "" + s
local n = str.length()
// Leading whitespace: reuse shared skip_ws to keep semantics aligned with StageB.
local b = StringHelpers.skip_ws(str, 0)
// Leading whitespace: use static method to avoid SSA undef (Phase 71-SSA Quick Win)
local b = ParserStringUtilsBox.skip_ws(str, 0)
if b >= n { return "" }
// Trailing whitespace: walk backwards until a non-space is found.