feat(mir/phi): improve LoopForm parameter detection - track param names

**Problem**: is_parameter() was too simple, checking only ValueId which changes
through copies/PHIs. This caused parameters like 'data' to be misclassified as
carriers, leading to incorrect PHI construction.

**Solution**: Track original parameter names at function entry.

**Changes**:

1. **Added function_param_names field** (builder.rs):
   - HashSet<String> to track original parameter names
   - Populated in lower_static_method_as_function()
   - Cleared and repopulated for each new function

2. **Improved is_parameter()** (loop_builder.rs):
   - Check name against function_param_names instead of ValueId
   - More reliable than checking func.params (ValueIds change)
   - __pin$*$@* variables correctly classified as carriers
   - Added debug logging with NYASH_LOOPFORM_DEBUG

3. **Enhanced debug output** (loopform_builder.rs):
   - Show carrier/pinned classification during prepare_structure()
   - Show variable_map state after emit_header_phis()

**Test Results**:
-  'args' correctly identified as parameter (was working)
-  'data' now correctly identified as parameter (was broken)
-  __pin variables correctly classified as carriers
-  PHI values allocated and variable_map updated correctly
- ⚠️ ValueId undefined errors persist (separate issue)

**Remaining Issue**:
ValueId(10) undefined error suggests PHI visibility problem or VM verification
issue. Needs further investigation of emit_phi_at_block_start() or VM executor.

**Backward Compatibility**:
- Flag OFF: 100% existing behavior preserved (legacy path unchanged)
- Feature-flagged with NYASH_LOOPFORM_PHI_V2=1

🤖 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-17 05:24:07 +09:00
parent f85e485195
commit c459135238
6 changed files with 258 additions and 11 deletions

View File

@ -46,12 +46,12 @@ Status: planning構造整理フェーズ・挙動は変えない
- ParserBox 呼び出し (`parse_program2` → emit JSON)
- defs スキャン (`FuncScannerBox.scan_all_boxes`)
が 1 関数に詰め込まれており、MIR 上でも巨大な `Main.main` になっている。
- 25.1c ではこれを「箱理論」に沿って分割する:
- `StageBArgsBox`CLI 引数と bundle/require の扱いだけを担当
- `StageBBodyExtractorBox``body_src` 抽出ロジックだけを担当)
- `StageBDriverBox`ParserBox/FuncScannerBox を呼んで Program(JSON v0) を emit
- Rust 側 MirBuilder には、この箱ごとの小さな関数をそのまま MIR に落とさせることで、`Main.main` の SSA/Loop の複雑さを減らし、今回のような ValueId 追跡をしやすくする
- 併せて、現状 selfhost CLI サンプルで観測されている `Main.main` 内の `ParserBox.length()` 呼び出しに対する recv 未定義エラー(`Invalid value: use of undefined value ValueId(17)`を、StageB Main 分割LocalSSA/LoopBuilder 整理の一環として根本修正するMethodCall の recv にも SSA/verify を適用する)
- 25.1c ではこれを「箱理論」に沿って分割する方針を立てており、Phase 25.1c 冒頭でまず StageB 側を 4 箱構造にリファクタした:
- `Main`(エントリ薄箱): `main(args){ return StageBDriverBox.main(args) }` のみを担当
- `StageBDriverBox`(オーケストレーション): `StageBArgsBox.resolve_src``StageBBodyExtractorBox.build_body_src` `ParserBox.parse_program2` → defs 挿入 → `print(ast_json)` だけを見る。
- `StageBArgsBox`CLI 引数と bundle/require の扱いだけを担当): もともとの「args/src/src_file/HAKO_SOURCE_FILE_CONTENT/return 0」ロジックを完全移動。
- `StageBBodyExtractorBox``body_src` 抽出ロジックbundle/using/trim を担当): もともとの `body_src` 抽出〜コメント削除〜BundleResolver/Stage1UsingResolverBox〜前後 trim までを丸ごとカプセル化
- いずれもロジックはそのまま移動であり、コメント・using・ログを含めて挙動は完全に不変同じ Program(JSON v0)、同じログ、同じ `VM error: Invalid value`)であることを selfhost CLI サンプルで確認済み。エラーの発生箇所は `Main.main` から `StageBArgsBox.resolve_src/1` に関数名だけ変わっており、SSA/Loop 側の根本修正はこの後のタスクLoopBuilder / LocalSSA 整理)で扱う
6. **LoopBuilder / pin スロットの型付け・箱化**
- いまの LoopBuilder は `__pin$*$@recv` のような文字列ベースの「内部変数名」を `variable_map` に直接突っ込んで、SSA/phi/pin を管理している。