Files
hakorune/docs/development/current/main/phase71-ssa-trim-fix-20251202.md
nyash-codex 4b3eb6b3a9 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>
2025-12-02 11:16:01 +09:00

7.0 KiB

Phase 71-SSA: trim系 SSA undef 完全解消レポート

実施日: 2025-12-02 担当: Claude + Task先生


🎉 エグゼクティブサマリー

SSA undef 完全解消達成!

  • 修正前: 4件の SSA undef
  • 修正後: 0件 (100%解消!)

修正内容:

  1. ParserStringUtilsBox.trim - StringHelpers.skip_wsParserStringUtilsBox.skip_ws (Quick Win)
  2. ParserCommonUtilsBox.trim - 委譲を廃止、直接実装に変更
  3. ParserBox.trim - 委譲を廃止、直接実装に変更

所要時間: 約2時間 (調査 + 実装 + 検証)


📊 SSA undef 推移

フェーズ SSA undef件数 詳細
Phase 71初回観測 4件 ParserCommonUtilsBox.trim/1, ParserBox.trim/1, Main._parse_number/1, ParserBox.parse_block2/2
Quick Win修正後 2件 ParserCommonUtilsBox.trim/1, ParserBox.trim/1 (予想外の効果: _parse_number/parse_block2 消滅)
修正案A実装後 0件 🎉 完全解消!

🔍 根本原因の特定 (Task先生による分析)

ValueId(272)の正体

  • StringHelpers.starts_with_kw/3の戻り値
  • ParserCommonUtilsBox.trim/1 の引数として誤って参照されていた

問題の本質

static boxの委譲でValueIdマッピング失敗:

// ParserCommonUtilsBox.trim (問題あり)
trim(s) {
    return ParserStringUtilsBox.trim(s)  // ← 引数sのValueIdマッピングが失敗
}

ログ証拠:

[ssa-undef-debug] fn=ParserCommonUtilsBox.trim/1 bb=BasicBlockId(800) inst_idx=0
                  used=ValueId(272) inst=Copy { dst: ValueId(2), src: ValueId(272) }

注目点: 引数パラメータ設定ログが一切出力されていない


🛠️ 修正内容の詳細

修正1: ParserStringUtilsBox.trim (Quick Win)

ファイル: lang/src/compiler/parser/scan/parser_string_utils_box.hako

変更箇所 (L76):

// 修正前
local b = StringHelpers.skip_ws(str, 0)  // インスタンスメソッド呼び出し

// 修正後
local b = ParserStringUtilsBox.skip_ws(str, 0)  // 静的呼び出し

効果:

  • SSA undef 4件 → 2件
  • 予想外の副次効果: Main._parse_number と ParserBox.parse_block2 が消滅

修正2: ParserCommonUtilsBox.trim (修正案A)

ファイル: lang/src/compiler/parser/scan/parser_common_utils_box.hako

変更内容 (L50-69):

// 修正前 (委譲パターン)
trim(s) {
    // Delegate to string_utils to keep SSA/semantic consistency.
    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()

    // 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 ""
}

修正3: ParserBox.trim (修正案A)

ファイル: lang/src/compiler/parser/parser_box.hako

変更内容 (L81-98):

  • ParserCommonUtilsBox.trim と同じパターンで直接実装に変更

成功パターンとの比較

FuncScannerBox.trim (成功パターン)

  • box宣言 (通常のbox)
  • methodキーワード使用
  • 同じbox内のメソッド呼び出し
  • 二重委譲なし
  • SSA undef なし

ParserStringUtilsBox.trim (失敗パターン→成功)

  • static box宣言
  • methodキーワードなし
  • 別boxの関数呼び出し (修正後は同じbox)
  • 二重委譲あり (skip_ws → StringHelpers.skip_ws)
  • 修正後 SSA undef なし

ParserCommonUtilsBox.trim (失敗パターン→成功)

  • static box宣言
  • methodキーワードなし
  • 委譲パターン (修正前)
  • 修正後: 直接実装で SSA undef 解消

📈 検証結果

最終確認

NYASH_FEATURES=stage3 NYASH_USE_NY_COMPILER=1 NYASH_NY_COMPILER_EMIT_ONLY=1 \
NYASH_SELFHOST_KEEP_RAW=1 ./tools/selfhost/selfhost_build.sh \
--in apps/tests/stage1_run_min.hako --run

結果:

[warn] dev verify: NewBox StageBDriverBox at v%366 not followed by birth() call
[warn] dev verify: NewBox→birth invariant warnings: 1
[selfhost/debug] RAW log: .../stageb_20251202_111409_2674670.log

SSA undef 件数: 0 ← 🎉 完全解消!

RAWログ確認:

grep -c 'ssa-undef-debug' logs/selfhost/stageb_20251202_111409_2674670.log
# 出力: 0

🎯 残存課題

1. dev verify警告 (1件)

[warn] dev verify: NewBox StageBDriverBox at v%366 not followed by birth() call
  • 対象: StageBDriverBox
  • 対応: Phase 71-SSA次フェーズで実施

2. Program JSON未出力

[selfhost/raw] rc_stageb=0 extract_ok=0
  • 状況: Stage-B rc=0 (実行成功) だが Program JSON 行なし
  • 原因: SSA undef 以外の問題 (dev verify? または別の要因)
  • 対応: 次フェーズでトレース追加して調査

💡 重要な教訓

1. static boxの委譲は危険

  • ValueIdマッピングが正しく行われない可能性
  • 引数パラメータ設定ログが出ないケースあり
  • 推奨: 委譲を避け、直接実装を選択

2. 静的呼び出しの重要性

  • BoxName.method() → SSA-friendly
  • using経由のBox.method() → インスタンスメソッド呼び出しのリスク
  • 推奨: 同じbox内のメソッドを静的呼び出し

3. 成功パターンの活用

  • FuncScannerBox.trim の実装パターンを参考
  • 既存の成功事例を積極的に再利用

📝 次のアクション

Phase 71-SSA次フェーズ

  1. StageBDriverBox birth警告解消 (1件 → 0件)
  2. Program JSON emit調査
    • StageBDriverBox.main にトレース追加
    • RAWログで出口まで到達しているか確認
  3. 最終目標: selfhost_build + stage1_run_min.hako で Program JSON emit成功

🤖 AI協働成果

Task先生の貢献

  • ValueId(272) の正体特定
  • static box委譲問題の発見
  • 修正案A-C の提案
  • FuncScannerBox.trim との比較分析

Claude実装

  • Quick Win (30分で2件削減)
  • 修正案A実装 (委譲廃止で残り2件解消)
  • 検証・ドキュメント化

合計所要時間: 約2時間 (Task先生調査含む)


📚 関連ドキュメント

  • Phase 71初回観測: phase71-findings-20251202.md
  • Phase 71-SSA README: docs/private/roadmap2/phases/phase-71-ssa-debug/README.md
  • Phase 71-SSA TASKS: docs/private/roadmap2/phases/phase-71-ssa-debug/TASKS.md
  • CURRENT_TASK.md: Phase 71-SSA進捗記録

Phase 71-SSA SSA undef 削減完了判定: 100%達成!

次のマイルストーン: dev verify警告解消 + Program JSON emit復活