# Phase 71-SSA: trim系 SSA undef 完全解消レポート **実施日**: 2025-12-02 **担当**: Claude + Task先生 --- ## 🎉 エグゼクティブサマリー **SSA undef 完全解消達成!** - **修正前**: 4件の SSA undef - **修正後**: **0件** (100%解消!) **修正内容**: 1. ParserStringUtilsBox.trim - `StringHelpers.skip_ws` → `ParserStringUtilsBox.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マッピング失敗**: ```hako // 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): ```hako // 修正前 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): ```hako // 修正前 (委譲パターン) 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 解消 --- ## 📈 検証結果 ### 最終確認 ```bash 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ログ確認**: ```bash 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復活