Files
hakorune/docs/development/roadmap/phases/phase-25.3-funcscanner
nyash-codex 3a82633924 refactor(funcscanner): Region+next_i パターン統一 & SSA テスト追加
**FuncScanner .hako 側改善**:
- scan_all_boxes を Region + next_i 形式に統一(continue 多発による SSA/PHI 複雑さ削減)
- インデント修正(タブ→スペース統一)
- デバッグ print 削除

**SSA テスト追加**:
- lang/src/compiler/tests/funcscanner_scan_methods_min.hako
- src/tests/mir_funcscanner_ssa.rs (scan_methods & fib_min SSA デバッグテスト)

**Phase 25.3 ドキュメント**:
- docs/development/roadmap/phases/phase-25.3-funcscanner/ 追加

**関連**: Phase 25.3 FuncScanner 箱化準備作業

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 06:38:43 +09:00
..

Phase 25.3 — FuncScanner / StageB defs 安定化

スコープ / ゴール

  • 対象レイヤ

    • .hako 側:
      • lang/src/compiler/entry/func_scanner.hako (FuncScannerBox)
      • lang/src/compiler/entry/compiler_stageb.hako (StageBFuncScannerBox, StageBDriverBox)
      • 必要に応じて lang/src/compiler/tests/funcscanner_fib_min.hako などのテスト用ハーネス
    • Rust 側:
      • 既存の LoopForm v2 / LoopSnapshotMergeBox / JSON front は「完成済みの土台」として利用するだけで、原則ここでは触らない。
  • ゴール

    • Rust VM 検証付きで FuncScanner を安定させる:
      • NYASH_VM_VERIFY_MIR=1lang/src/compiler/tests/funcscanner_fib_min.hako を実行したときに、
        • FuncScannerBox.scan_all_boxes/1 で Undefined value が発生しないこと。
        • fib 風ソースに対して defsTestBox.fib / Main.main が含まれること(箱レベルの振る舞いが安定)。
    • StageB 側からも同じ結果が得られる:
      • tools/smokes/v2/profiles/quick/core/phase251/stageb_fib_program_defs_canary_vm.sh を実行すると、
        • defsTestBox.fib が存在し、
        • その bodyLoop ノードが含まれていること。
    • Loop/PHI の意味論は LoopFormBuilder + LoopSnapshotMergeBox に完全委譲したまま、
      • FuncScanner / StageB は「テキストスキャンJSON 組み立て」の箱として綺麗に分離された状態にする。

すでに前提としている状態

  • LoopForm v2 / PHI / snapshot:

    • ループ構造・PHI・break/continue スナップショットの意味論は、
      • src/mir/loop_builder.rs
      • src/mir/phi_core/loopform_builder.rs
      • src/mir/phi_core/loop_snapshot_merge.rs に集約されており、AST ルート / JSON ルートともに同じ実装を使っている。
    • canonical continue_merge ブロック(ループごとに 1 つが導入済みで、backedge は
      • latchheader
      • continue_mergeheader の 2 本に限定されている。
  • JSON v0 front:

    • src/runner/json_v0_bridge/lowering/loop_.rs は LoopForm v2 の 薄いアダプタになっている。
      • ブロック ID の確保
      • vars / snapshot の受け渡し
      • LoopFormOps 実装 (LoopFormJsonOps) だけを担い、PHI 生成は LoopForm v2 に一元化された。
  • 25.1e / 25.1q / 25.2:

    • 変数スコープCarrier / Pinned / Invariant / BodyLocalInOutと Env_in/Env_out モデルは文書と実装が一致している。
    • JSON ループ用のスモーク(tests/json_program_loop.rsはすでに緑で、ループbreak/continuebodylocal exit に対して MIR 検証が通っている。

この Phase 25.3 では、「LoopForm / JSON front は触らずに、FuncScanner / StageB ラインをその上に綺麗に載せる」ことが目的になる。

タスク一覧

1. FuncScanner fib 最小ハーネスSSA バグの確認完了)

  • 対象:

    • lang/src/compiler/tests/funcscanner_fib_min.hako
    • FuncScannerBox.scan_all_boxes/1Rust lowering 時の MIR
  • 現状:

    • NYASH_VM_VERIFY_MIR=1 付きで funcscanner_fib_min.hako を実行しても、
      Undefined value / ssa-undef-debug は発生していないLoopForm v2 / LoopSnapshotMergeBox 修正で解消済み)。
    • cargo test mir_funcscanner_fib_min_ssa_debug も緑で、FuncScanner 単体の SSA 破綻は再現しない。
    • このフェーズで導入した __mir__ ロガーは、今後の再現時に経路観測用フックとして利用できる状態になっている。
  • 位置づけ:

    • 「FuncScanner + LoopForm v2 での Undefined Value バグの根治」は完了とみなし、
      以降は StageB 側の defs 欠落(defs=[])を主ターゲットとする。
  • 追加の SSA ガードme-call 周り):

    • Rust 側では MirBuilder::handle_me_method_callMeCallPolicyBox によって箱化し、
      • Box.method/Arity lowered 関数が存在する場合は、従来どおり me を先頭引数とする Global callインスタンス文脈の me-call
      • 存在しない場合は、handle_static_method_call(cls, method, arguments) にフォールバックし、
        static helperFuncScannerBox._parse_params / _strip_comments など)への呼び出しとして扱うようにした。
    • これにより、static box 文脈で「実体のない me を receiver とする Method call」が生成される経路が閉じられ、
      FuncScannerBox._scan_methods/4 + _parse_params + _strip_comments のラインは SSA 的に安全になっている。

2.5. MIR ロガー (mir) による観測Dev 専用)

  • 位置づけ:
    • Phase 25.3 では、FuncScanner / StageB のような .hako 側ロジックを LoopForm v2 上でデバッグしやすくするため、 専用の MIR ログ構文 __mir__ を導入する(実行意味論には影響しない dev 専用 Hook
  • 構文:
    • __mir__.log("label", v1, v2, ...)
      • lowering 時に MirInstruction::DebugLog { message: "label", values: [v1, v2, ...] } へ変換される。
    • __mir__.mark("label")
      • 値無し版の DebugLog として debug_log "label" だけを差し込む。
  • 振る舞い:
    • VM 実行時は NYASH_MIR_DEBUG_LOG=1 のときだけ
      • [MIR-LOG] label: %id=value ... の形式でログ出力され、それ以外のときは完全に無視されるEffect::Debug のみ)。
    • LoopForm / PHI / snapshot には関与せず、単に MIR に 1 命令追加するだけの観測レイヤ。
  • 実装ポイント:
    • src/mir/builder/calls/build.rs 内の build_method_call_impl で、
      • receiver が __mir____mir__.log/mark を検出し、
      • try_build_mir_debug_callDebugLog 命令に直接 lowering している。

FuncScanner / StageB のデバッグ時には、scan_all_boxes のループ頭や box 検出直後に
__mir__.log("funcscan/head", i, in_str, in_block) などを埋め込み、VM 実行ログと合わせて
「どの経路で環境スナップショットやステートが崩れているか」を観測する想定だよ。

3. StageB FuncScanner との整合性確保(主ターゲット)

  • 対象:

    • lang/src/compiler/entry/compiler_stageb.hako
      • StageBFuncScannerBox.scan_all_boxes
      • StageBFuncScannerBox._find_matching_brace
      • StageBDriverBox.main 内の defs 組み立てロジック
  • やること:

    • StageBFuncScannerBox のロジックを、可能な範囲で FuncScannerBox と共有・委譲する方向に寄せる。
      • _find_matching_brace などはすでに FuncScannerBox に委譲済みなので、 残りのスキャンロジックも「同じアルゴリズム / 同じ境界条件」で動くように整理する。
    • HAKO_STAGEB_FUNCSCAN_TEST=1StageBFuncScannerBox.test_fib_scan() を走らせ、
      • brace1/brace2 の close_idx が正しく取れること。
      • defs_len > 0 となり、TestBox.fib / Main.main がログに出ること。
    • そのうえで StageBDriverBox.mainStageBFuncScannerBox.scan_all_boxes(src) の結果を
      • Program(JSON v0).defs に正しく注入できているかを確認する。
    • ここでの主なバグは「SSA ではなく、StageB が fib ソースから defs を組み立てきれていないこと」なので、
      ループ構造や LoopForm には手を入れず、StageB 側のテキスト処理と defs 生成パスを中心に見る。

4. fib defs canary & ドキュメント更新

  • 対象:

    • tools/smokes/v2/profiles/quick/core/phase251/stageb_fib_program_defs_canary_vm.sh
    • docs/development/roadmap/phases/phase-25.1q/README.md
    • CURRENT_TASK.md
  • やること:

    • canary スクリプトで:
      • Program.kind == "Program"
      • defsTestBox.fib が存在すること。
      • TestBox.fib.bodyLoop ノードが含まれること。 を満たした状態で rc=0 になるまで確認する。
    • Phase 25.1q / 25.2 の README には、
      • 「loop/PHI/スナップショットの SSOT は LoopForm v2 + LoopSnapshotMergeBox」
      • 「Phase 25.3 で FuncScanner / StageB defs もこの土台の上に載せた」 というつながりを 1〜2 行で追記する。
    • CURRENT_TASK.md には:
      • Phase 25.3 のタスク完了状況FuncScanner fib / StageB fib canary 緑)と、
      • その後に繋がる Stage1 UsingResolver / Stage1 CLI selfhost ラインへのブリッジ を短く整理しておく。

この Phase 25.3 は、

  • LoopForm v2 / JSON front を「箱として完成済み」とみなし、
  • その上で FuncScanner / StageB defs ラインを 構造的に安定させる

ための仕上げフェーズだよ。
ループや PHI の意味論は触らず、テキストスキャンとスコープ設計を整えることで、selfhosting ライン全体の足場を固めるのが狙い。+