# Current Task — Phase 21.8 / 25 / 25.1 / 25.2 Snapshot(2025-11-18 時点) > このファイルは「今どこまで終わっていて、次に何をやるか」を 1000 行以内でざっくり把握するためのスナップショットだよ。 > 詳細な履歴やログは `git log CURRENT_TASK.md` からいつでも参照できるようにしておくね。 --- ## 0. 現在地ざっくり - フェーズ軸: - **21.8**: Numeric Core / Core-15 まわりの安定化(既に日常的には安定運用)。 - **25.x**: Stage0/Stage1/Stage‑B / Selfhost ラインのブートストラップと LoopForm v2 / LoopSSA v2 まわりの整備。 - **25.1 系**: Stage‑B / Stage‑1 / selfhost 向けに、Rust MIR / LoopForm v2 / LoopSSA v2 を段階的に整える長期ライン。 - Rust 側: - LoopForm v2 + ControlForm + Conservative PHI は、代表テスト(Stage‑1 UsingResolver / Stage‑B 最小ループ)ではほぼ安定。 - 静的メソッド呼び出し規約と `continue` 絡みの PHI は 25.1m までで根治済み。 - .hako 側: - Stage‑B コンパイラ本体 / LoopSSA v2 / BreakFinderBox / PhiInjectorBox はまだ部分実装。 - JSON v0 / selfhost ルートは Rust 側の LoopForm v2 規約に追いつかせる必要がある。 - Stage‑B / FuncScanner ライン: - Phase 25.3 をクローズし、`stageb_fib_program_defs_canary_vm.sh` が緑(`defs` に `TestBox.fib/Main.main`、fib.body.body[*] に `Loop`)。 - Stage‑B は block パーサ優先 + defs を Block 包みで構造化。次手: Stage‑1 UsingResolver ループの Region+next_i 揃え / Stage‑1 CLI program-json selfhost 準備。 --- ## 1. 最近完了した重要タスク ### 1-0. Phase 25.3 — FuncScanner / Stage‑B defs 安定化(完了) **目的** - Stage‑B / FuncScanner ラインで defs が欠落したり Loop が脱落する問題を塞ぎ、selfhost 側の canary を緑に戻す。 **やったこと** - StageBDriverBox.main: - main 本文を `{…}` で包んだ block パーサ優先で Program(JSON) に組み立て、defs には `{"type":"Block","body":[…]}` 形式で埋め込むよう整理。 - Program パーサ fallback は `HAKO_STAGEB_PROGRAM_PARSE_FALLBACK=1` の opt-in に封じ込め(skip_ws 崩れを回避)。 - StageBFuncScannerBox._scan_methods: - block パーサ優先に統一し、Program パーサは `HAKO_STAGEB_FUNC_SCAN_PROG_FALLBACK=1` でのみ有効化。 - defs パラメータに必ず `me` を足す従来挙動は維持(TestBox/Main いずれも同型で出力)。 - Rust 層の追加変更なし(LoopForm v2 / LoopSnapshotMergeBox をそのまま利用)。 **結果** - `tools/smokes/v2/profiles/quick/core/phase251/stageb_fib_program_defs_canary_vm.sh` が安定して PASS。 - `Program.kind == "Program"` - `defs` に `TestBox.fib` / `Main.main` を保持していること。 - `TestBox.fib.body.body[*]` に `Loop` ノードが含まれること。 を満たした状態で `rc=0` になることを確認。 - FuncScanner / Stage‑B 経由の fib defs ラインは LoopForm v2 + LoopSnapshotMergeBox 上で構造的に安定したとみなし、Phase 25.3 はクローズ。 - 次フェーズの入口が整理できたので、Stage‑1 UsingResolver ループ(Region+next_i 形)と Stage‑1 CLI program-json/selfhost 導線に着手可能。 ### 1-1. Phase 25.1m — Static Method / LoopForm v2 continue + PHI Fix(完了) **目的** - 静的メソッド呼び出し時の「暗黙レシーバ+引数ずれ」バグと、LoopForm v2 経路における `continue` + header PHI の欠落を根本から直す。 **Rust 側(静的メソッド / 暗黙レシーバ / JSON v0 Bridge)** - `src/mir/function.rs::MirFunction::new` - 暗黙 receiver 判定を是正し、**「第 1 パラメータが Box 型の関数だけ」をインスタンスメソッド with receiver** とみなす。 - 非 Box 型(`String`, `Integer` など)で始まるパラメータ列の関数は、暗黙レシーバなしの静的メソッド / Global 関数として扱うように変更。 - その結果: - `static box TraceTest { method log(label) { ... } }` に対して `TraceTest.log("HELLO")` を呼ぶと、 `label` に `"HELLO"` が正しく入る(以前は `label = null` になっていた)。 - `src/mir/builder/decls.rs::build_static_main_box` - `Main.main(args)` を「静的エントリ関数」に lower する経路を **`NYASH_BUILD_STATIC_MAIN_ENTRY=1` のときだけ有効** にし、 通常の VM 実行では wrapper `main()` を正規エントリとして扱うように整理。 - これにより、「`Main.main(args)` 版ではループが 1 度も回らず `return 0` で終わる」バグを解消。 - JSON v0 Bridge 経由の Box メソッド(Stage‑1/Stage‑B defs): - `src/runner/json_v0_bridge/lowering.rs` で `prog.defs` の降下ロジックを調整し、 - `box_name != "Main"` の関数定義をインスタンスメソッドとして扱って `signature.params` に「暗黙 `me` + 明示パラメータ」を載せる。 - `func_var_map` に `me` → `func.params[0]` を事前バインドし、残りのパラメータ名を `params[1..]` に対応づける。 - これにより、`Stage1UsingResolverFull._build_module_map()` のように JSON では `params: []` でも Hako 側で `me._push_module_entry(...)` を使う関数について、 Rust VM 実行時に `me` が未定義(ValueId(0))になるケースを構造的に防止。 **LoopForm v2(continue + header PHI)** - `src/mir/phi_core/loopform_builder.rs::LoopFormBuilder::seal_phis` - シグネチャを `seal_phis(ops, latch_id)` → `seal_phis(ops, latch_id, &continue_snapshots)` に拡張。 - preheader と latch に加え、`LoopBuilder` 側で記録している **`continue_snapshots` からの値も header PHI の入力** として統合。 - pinned / carrier いずれも、header の全 predecessor: - `(preheader, preheader_copy)` - `(continue_bb, value_at_continue)` - `(latch, value_at_latch)` を入力として持つようになり、balanced scan など「continue を含むループ」の SSA が正しく構成される。 - `src/mir/loop_builder.rs::build_loop_with_loopform` - `let continue_snaps = self.continue_snapshots.clone();` - `loopform.seal_phis(self, actual_latch_id, &continue_snaps)?;` - という形で、LoopBuilder → LoopForm 側に `continue` スナップショットを橋渡し。 **ControlForm / LoopShape invariant** - `src/mir/control_form.rs::LoopShape::debug_validate`(debug ビルドのみ) - 既存の: - `preheader -> header` エッジ必須 - `latch -> header` バックエッジ必須 - に加えて、次の invariant を追加: - `continue_targets` の各ブロックから `header` へのエッジが存在すること。 - `break_targets` の各ブロックから `exit` へのエッジが存在すること。 - これにより、LoopForm / LoopBuilder が `continue` / `break` 経路を誤配線した場合に、構造レベルで早期検知できる。 **テスト / 検証** - MIR ユニットテスト: - `src/mir/phi_core/loopform_builder.rs::tests::test_seal_phis_includes_continue_snapshots` - LoopFormBuilder 単体で「preheader + continue + latch」が PHI 入力に含まれることを固定。 - `src/tests/mir_stageb_loop_break_continue_verifies` - Stage‑B 風の `loop + break/continue` パターンで MirVerifier 緑。 - `src/tests/mir_stage1_using_resolver_verify.rs::mir_stage1_using_resolver_full_collect_entries_verifies` - LoopForm v2/PHI v2 経路(現在は既定実装)で Stage‑1 UsingResolver フル版が MirVerifier 緑。 - 実行観測: - 開発用 Hako `loop_continue_fixed.hako`: - 期待 `RC=3` / 実測 `RC=3`、PHI pred mismatch なし。 - Stage‑B balanced scan: - `StageBBodyExtractorBox` のバランススキャンループに trace を入れて 228 回イテレーションが回ること、 `ch == "{"` ブランチで `depth` / `i` を更新 → `continue` → 次イテレーションに **確実に戻っている** ことを確認。 --- ### 1-2. Phase 25.1k — LoopSSA v2 (.hako) & Stage‑B harness 追従(Rust 側はおおむね完了) **目的** - Rust 側の LoopForm v2 / ControlForm / Conservative PHI を SSOT としつつ、Stage‑B / selfhost で使っている `.hako` 側 LoopSSA/BreakFinderBox/PhiInjectorBox をその規約に追従させる準備フェーズ。 **Rust 側でやったこと(サマリ)** - Receiver / pinning: - `CallMaterializerBox::materialize_receiver_in_callee` を事実上 no-op にし、 receiver の pinning / LocalSSA 連携を `receiver::finalize_method_receiver` に一本化。 - `MirBuilder` に `pin_slot_names: HashMap` を持たせ、 `LocalSSA.ensure` が「同じ slot にぶらさがる最新の ValueId」へ自動でリダイレクトできるようにした。 - Compiler Box の分類: - `CalleeResolverBox::classify_box_kind` に `BreakFinderBox` / `PhiInjectorBox` / `LoopSSA` を追加し、 Stage‑1/Stage‑B 用 LoopSSA 箱を `CalleeBoxKind::StaticCompiler` として明示。 **IfForm / empty else-branch の SSA fix(Stage‑1 UsingResolverFull 対応)** - `src/mir/builder/if_form.rs`: - `if cond { then }`(else なし)のパターンで、 - else-entry 用に pre_if の `variable_map` から PHI ノードを生成したあと、 - その PHI 適用後の `variable_map` を `else_var_map_end_opt=Some(...)` として merge フェーズに渡すように修正。 - 以前は empty else の場合に `else_var_map_end_opt` が `None` になっており、 `merge_modified_vars` が pre_if の古い ValueId にフォールバックして、 merge ブロックで未定義の `%0` などを参照するケースがあった(`Stage1UsingResolverFull.main/0` の UndefinedValue)。 - 修正後は then/else 両ブランチで「PHI 適用後の variable_map」が merge に渡されるため、 empty else でも header/merge の SSA が崩れない。 - 検証: - `src/tests/mir_stage1_using_resolver_verify.rs::mir_stage1_using_resolver_full_collect_entries_verifies` が `MirVerifier` 緑になり、`Stage1UsingResolverFull.main/0()` の merge ブロックで PHI 後の値(例: `%24`)を正しく参照していることを MIR dump で確認済み。 **.hako 側の今後(25.1k 後半)** - `LoopSSA.stabilize_merges(json)` を Rust LoopForm v2 の Carrier/Pinned 規約に合わせて実装する(現在はほぼ stub)。 - Stage‑B Test2(`tools/test_stageb_min.sh`)で得られる Program(JSON v0) に対し、 - Rust 側で `NYASH_VM_VERIFY_MIR=1` を立てた実行結果と、 - `.hako` 側 LoopSSA v2 適用後の JSON → Rust 実行結果 を比較し、BreakFinderBox / PhiInjectorBox / LoopSSA の責務を切り分けていく。 --- ### 1-3. Phase 25.1e/f/g — LoopForm PHI v2 / ControlForm 統合(サマリ) - 25.1e(LoopForm PHI v2 migration): - Local SSA(`local a = ...`)の ValueId 分離を完了し、LoopForm v2 を「PHI/SSA の正」とする方向へ寄せた。 - Stage‑1 UsingResolver / 基本的な Stage‑B ループは、LoopForm v2 経路で MirVerifier 緑。 - 25.1f(ControlForm 層の導入): - `ControlForm` / `LoopShape` / `IfShape` を導入し、Loop / If を共通ビューとして扱う箱を定義。 - ここでは挙動を変えず、「構造だけを先に固定」する方針で設計を固めた。 - 25.1g(Conservative PHI ↔ ControlForm ブリッジ): - `phi_core::loopform_builder::build_exit_phis_for_control` など、ControlForm から Conservative PHI を呼び出す薄いラッパを追加。 - 既存の PHI ロジックはそのままに、将来の置き換えポイントだけを明示している。 --- ### 1-4. Phase 25.1A‑3 — Stage‑1 CLI bridge(stub 実装) - Rust 側: `src/runner/stage1_bridge.rs` を `run_refactored` 入口に組み込み、`NYASH_USE_STAGE1_CLI=1` かつ再入ガードなしのときに `lang/src/runner/stage1_cli.hako` を子プロセスで起動する。`STAGE1_EMIT_PROGRAM_JSON` / `STAGE1_EMIT_MIR_JSON` / `STAGE1_BACKEND` / `STAGE1_PROGRAM_JSON` で mode 選択。entry override は `STAGE1_CLI_ENTRY` / `HAKORUNE_STAGE1_ENTRY`。 - .hako 側: `Stage1Cli` に最低限の本体を実装。 - `emit_program_json`: Stage‑1 UsingResolver で prefix を結合し、BuildBox.emit_program_json_v0 で Program(JSON v0) を返す。 - `emit_mir_json`: `MirBuilderBox.emit_from_program_json_v0` をそのまま呼ぶ(delegate 未設定なら null)。 - `run_program_json`: backend==llvm の場合は `env.codegen.emit_object` まで通す。vm/pyvm は当面 MIR(JSON) を stdout に出すのみ(実行は Stage0 橋渡し未配線)。 - CLI: `emit program-json|mir-json` / `run --backend ... ` を受理。`NYASH_SCRIPT_ARGS_JSON` を JSON で best-effort 伝播。 - Docs: `docs/development/roadmap/phases/phase-25.1/stage1-usingresolver-loopform.md` に stub 状態を追記(run は暫定挙動)。 - Known gaps: vm/pyvm 実行はまだ Stage0 への橋渡し未着手。llvm も emit object 止まり(link/exec は後続)。 ### 1-5. Phase 25.1A‑4 — Using SSOT 薄設計+BuildBox include 除去 - SSOT: `lang/src/using/resolve_ssot_box.hako` に README 相当のコメントと I/F(resolve_modules/resolve_prefix)を追加。現状は no-op だが「using をここで扱う」窓口を固定。 - Stage1UsingResolver: `resolve_for_program_json` を追加し、SSOT を呼ぶ導線だけ確保(現状は透過返し)。 - BuildBox: 先頭の `include` を削除し、`using lang.compiler.entry.bundle_resolver as BundleResolver` に置換(Stage‑B パーサが include を解せない問題の足場づくり)。 - 実行確認: `NYASH_ALLOW_NYASH=1 HAKO_ALLOW_NYASH=1 NYASH_USE_STAGE1_CLI=1 STAGE1_EMIT_PROGRAM_JSON=1 ... cargo run --bin hakorune -- basic_test.hako` が RC=0 で完走(ただし stdout は `RC: 0` のみ、program-json 出力は未配線)。`cargo run ... emit program-json` は Rust CLI 側の表面が未対応のためエラー(想定挙動)。 --- ## 2. まだ残っている問題・課題(2025-11-18 時点) ### 2-1. Stage‑B 本体の型エラー(`String > Integer(13)`) - 症状: - Stage‑B の `Main.main` 実行時に、 `Type error: unsupported compare Gt on String(...) and Integer(13)` が発生。 - LoopForm v2 / PHI / continue 修正とは **独立の Stage‑B 固有のロジック問題**。 - 想定される原因: - Stage‑B 側の body 構築 / JSON 生成で、本来数値比較にすべき箇所で「生の文字列」と整数を比較している。 - もしくは、Parser/Scanner が `len` やインデックスを文字列のまま扱っている部分がある。 - 対応方針(次フェーズ向けメモ): - `StageBBodyExtractorBox.build_body_src` が吐く `body_src` を最小ケースで抽出し、 その中から問題の比較式(`>`)がどのように生成されているかを特定する。 - Stage‑B の box レベルで: - 「どのフェーズで型を決めるか」(例: ParserBox / Stage‑B / VM 手前)を決めてから修正する。 - このタスクは 25.1c 続き or 新フェーズ(25.1n 相当)として、Stage‑B 箱の設計側で扱う。 --- ### 2-2. Stage‑B 再入ガード `env.set/2` の扱い - 現状: - 一部 Stage‑B コードが `env.set/2` を使った再入ガードに依存しており、 Rust VM 側には `env.set/2` extern が定義されていないため、 `❌ VM error: Invalid instruction: extern function: Unknown: env.set/2` が発生するケースがある。 - 方針メモ: - 選択肢 A: Stage‑B 再入ガードを Box 内 state(フィールド)に寄せて、`env.set/2` 依存をなくす。 - 選択肢 B: Stage‑B ハーネス専用に、最小限の `env.set/2` extern を Rust 側に実装する(本番経路では使わない)。 - 25.1m では構造修正(Loop/PHI/receiver)を優先し、この extern の話は据え置き。 --- ### 2-3. .hako 側 LoopSSA v2(Rust LoopForm v2 との乖離) - 現状: - `lang/src/compiler/builder/ssa/loopssa.hako` の `stabilize_merges()` はまだ実質的に stub に近い。 - Stage‑B Test2(`compiler_stageb.hako` 経由)では、Rust MIR 側で LoopForm v2 / PHI v2 が安定した後も、 `.hako` 側 LoopSSA 経由の JSON から生成した MIR で PHI/SSA 問題が残る可能性がある。 - 目標: - Rust LoopForm v2 を「制御構造と PHI の SSOT」とみなし、 `.hako` 側 LoopSSA が同じ Carrier/Pinned / preheader/header/exit の規約を JSON レベルで再現する。 - やること(フェーズ 25.1k 後半〜 25.1f/g 連携): - 特定の関数(例: `BreakFinderBox._find_loops/2`)を対象に、Rust 側 / .hako 側のそれぞれで生成されるループ構造を比較。 - LoopSSA v2 の中に: - Carrier 変数の検出、 - pinned 変数の扱い、 - exit PHI の構築 を Rust LoopForm v2 に合わせて実装。 - 2025-11-19 追記: - `BreakFinderBox._find_loops/2` については、まず .hako 側を「region box」的に整理した。 - `header_pos` / `header_id` / `exit_pos` / `exit_id` まわりの異常系を `continue` ではなく `next_i` ローカルへの代入で表現し、1 イテレーションの末尾で `i = next_i` に合流させる形に変更。 - これにより、LoopForm v2 / LoopSSA 側から見ると「単一 region 内での分岐+最後に合流」という構造になり、 carrier/pinned 検出や今後の SSA 解析が行いやすくなった(挙動は従来と同じ)。 ### 2-5. static box / me セマンティクス(観測タスクへ移行) - 現状: - `static box StringHelpers` のようなユーティリティ箱で、`me.starts_with(src, i, kw)` のように 同一箱内のヘルパー(`starts_with`)を `me.` 経由で呼んでいたため、Stage‑3 降下時に引数ずれが発生していた。 - 具体的には、`StringHelpers.starts_with_kw/3` → `StringHelpers.starts_with/3` の降下で 実際の呼び出しが `starts_with("StringHelpers", src, i, kw)` のような 4 引数形になり、 `starts_with(src, i, pat)` 側では `src="StringHelpers"` / `i=<ソース全文>` となって、 `if i + m > n` が `String > Integer(13)` 比較に化けていた。 - 対応(完了済み・局所修正): - `lang/src/shared/common/string_helpers.hako` の `starts_with_kw` を、 `if me.starts_with(src, i, kw) == 0` から `if starts_with(src, i, kw) == 0` に書き換え、 static box ユーティリティに対する `me` 依存を除去した。 - これにより、`starts_with` 内でのガード比較 `i + m > n` はすべて整数同士となり、 Stage‑B fib ケースで発生していた `String("...") > Integer(13)` の TypeError は解消済み。 - 今後(Phase 25.1p 以降): - static box 全般における `me` セマンティクス(本当に「シングルトンインスタンス」として扱う箱と、 純粋な名前空間箱をどう区別するか)は、25.1p の DebugLog フェーズで観測しながら設計を詰める。 - 実際に Rust 層(`build_me_expression` / `lower_static_method_as_function` / `FunctionDefBuilder::is_instance_method`)を 統一規約に寄せる作業は、25.1p 以降のサブタスクとして扱う(現時点では局所修正でバグのみ解消)。 --- ### 2-4. Builder / Selfhost まわりの残タスク(超ざっくり) - Builder 内部ルート(20.43 系): - `MirBuilderBox` 経由の internal ルートで、MIR を stdout 経由ではなく一時ファイル / FileBox に書き出し、 ハーネスがそこから読む形に揃える案が残タスク。 - Selfhost CLI / Stage1 CLI: - Stage‑B / Stage‑1 CLI を「Rust VM / LLVM / PyVM / selfhost」の 4 経路で安定確認するラインは進行中。 - 25.1m では Rust VM + Stage‑B balanced scan を優先し、CLI 全体は次のフェーズで詰める。 --- ## 3. 次にやること(候補タスク) ここから先は「どのフェーズを進めるか」をそのときの優先度で選ぶ感じだよ。 Rust 側は LoopForm v2 / Stage‑B fib / Stage‑1 UsingResolver 構造テストまで一通り整ったので、当面は Stage‑1 CLI / selfhost ラインの小さな箱から進める。 ### A. Stage‑1 CLI / Stage0 ブリッジ(Phase 25.1 — いまここ) - A‑1: Stage‑1 CLI stub を Stage0 Rust ランナーから呼び出すブリッジ(DONE) - 実装: `src/runner/stage1_bridge.rs` + `src/runner/mod.rs` に `maybe_run_stage1_cli_stub` を追加。 - `NYASH_USE_STAGE1_CLI=1`(既定 OFF)かつ `NYASH_STAGE1_CLI_CHILD!=1` のときにだけ有効。 - entry `.hako` は `STAGE1_CLI_ENTRY` / `HAKORUNE_STAGE1_ENTRY` で上書き可能(既定: `lang/src/runner/stage1_cli.hako`)。 - 入力ファイル / モード: - `STAGE1_EMIT_PROGRAM_JSON=1`: `hakorune emit program-json ` を子プロセスで実行。 - `STAGE1_EMIT_MIR_JSON=1`: `STAGE1_PROGRAM_JSON` があれば `--from-program-json`、なければ `` から `emit mir-json`。 - 上記どちらも無い場合: `hakorune run --backend `(backend は `STAGE1_BACKEND` か CLI の backend 設定)。 - `NYASH_SCRIPT_ARGS_JSON` を拾って `--` 以降の script 引数も Stage‑1 側に転送。 - 再入防止として子プロセスには `NYASH_STAGE1_CLI_CHILD=1` を付与(子側からは Rust ブリッジを素通り)。 - A‑2: Stage‑1 CLI skeleton の責務を doc に固定(DONE) - `lang/src/runner/stage1_cli.hako` で `Stage1Cli.emit_program_json/emit_mir_json/run_program_json/stage1_main` のシグネチャとトグルトポロジーを固定。 - `docs/development/roadmap/phases/phase-25.1/stage1-usingresolver-loopform.md` に Rust 側ブリッジの振る舞いとトグル名(`NYASH_USE_STAGE1_CLI` / `STAGE1_EMIT_*` / `STAGE1_BACKEND` / `NYASH_STAGE1_CLI_CHILD`)を追記。 - A‑3: 次ステップ(未着手) - Stage‑1 CLI skeleton に Stage‑B/BuildBox/MirBuilder 呼び出しを順に実装し、「Program(JSON)/MIR(JSON) を selfhost 経由で emit できる」状態まで持っていく。 - `tools/selfhost/run_stage1_cli.sh` から呼び出す selfhost パスと、Rust CLl からのブリッジパスの両方で JSON I/O 契約が同じになるように揃える。 ### B. Stage‑1 UsingResolver / LoopForm v2 ライン(Phase 25.1e 系フォロー) - B‑1: entry UsingResolver の Region+next_i 化とコメント整備(おおむね DONE) - `lang/src/compiler/entry/using_resolver_box.hako` の 3 ループ(entries / JSON スキャン / modules_list)は Region+next_i 形に揃え済み。 - 役割コメント: `resolve_for_source`(Stage‑B body_src を受けて prefix を返す)、`_collect_using_entries`(JSON スキャンして entries を集める)、`_build_module_map`(modules_list を map 化)を明記済み。 - `HAKO_STAGEB_APPLY_USINGS=0` の時は prefix を空 string にしつつ、depth ガードだけは走らせる仕様もコメントで固定。 - B‑2: UsingResolver 構造テスト(ループ形/PHI)の拡充(DONE) - `src/tests/mir_stage1_using_resolver_verify.rs` に Region+next_i ループと early-exit JSON スキャンパターンの軽量テストを追加。 - これらは cargo test 経路で常時緑を維持し、v2 quick スモークへの昇格は「実行時間とノイズを見ながら後続フェーズで検討」という扱いにする(docs にメモ済み)。 - B‑3: pipeline_v2 UsingResolver との責務境界(DONE) - `lang/src/compiler/pipeline_v2/using_resolver_box.hako` 冒頭に、「entry 側=ファイル I/O + using 収集」「pipeline_v2 側=modules_json 上の alias/path 解決」と役割メモを追加。 - RegexFlow ベースの単一路ループは Region 化不要(stateful helper)とし、LoopForm v2 の観点からも「観測対象外」とする。 ### C. Stage‑B / LoopSSA / Selfhost まわり(中期タスク) - C‑1: Stage‑B 再入ガード `env.set/2` の整理(据え置き) - dev 専用 extern を Rust 側に追加するか、Stage‑B 箱側で state に寄せるかを決める必要があるが、現在はループ/PHI ラインを優先し保留。 - このタスクに着手するときは「prod/CI 経路から完全に切り離した dev ガード」として設計する。 - C‑2: .hako LoopSSA v2 実装(Rust LoopForm v2 への追従) - Rust LoopForm v2 の Carrier/Pinned/BodyLocalInOut モデルを `.hako` の LoopSSA に輸入し、Stage‑B Test2 / selfhost CLI でも MirVerifier 緑を目指す中〜長期タスク。 - 具体的な対象: `lang/src/compiler/builder/ssa/loopssa.hako` と Stage‑B/BreakFinder 周辺の region 化済みループ。 - C‑3: Selfhost / CLI 周辺のテスト整理 - 代表的な selfhost / Stage‑B / Stage‑1 CLI ケースを tests/tools 側でタグ付け(quick/integration/selfhost)、Phase 25.1 の「どこまでが Rust 側」「どこからが Stage1 側」を見える化する。 --- ## 4. 履歴の見方メモ - 以前の `CURRENT_TASK.md` は ~1900 行の長いログだったけど、読みやすさ重視でこのファイルはスナップショット形式にしたよ。 - 過去の詳細ログが必要になったら: - `git log -p CURRENT_TASK.md` - あるいは特定のコミット時点の `CURRENT_TASK.md` を `git show :CURRENT_TASK.md` でいつでも復元できるよ。 --- 以上が 2025-11-18 時点の Phase 21.8 / 25 / 25.1 / 25.2 ラインの「いまどこ」「なに済み」「なに残り」だよ。 次にどの箱から攻めるか決めたら、ここに箇条書きで足していこうね。 ## 3. これからやるタスクのラフ一覧(25.1 / Stage‑1 系) ここから先は「まず設計と箱分割を書いてから実装」という方針で進めるタスク群だよ。 ### A. Rust 層解析(LoopForm v2 / JSON v0 / Stage‑1 観測) - A-1: LoopForm v2 / LoopSnapshotMerge の入口確認 - `src/mir/loop_builder.rs` / `src/mir/phi_core/loopform_builder.rs` / `src/mir/phi_core/loop_snapshot_merge.rs` を「Stage‑1 から見た導線」として読み直し、どのレイヤで Carrier / Pinned / BodyLocalInOut が決まるかを short メモ化する。 - A-2: JSON v0 → MIR ブリッジの導線整理 - `src/runner/json_v0_bridge/lowering/`(特に `loop_.rs`)を通して、Program(JSON v0).body / defs.body(Block) が LoopForm v2 までどう運ばれるかを図として docs に落とす。 - A-3: Stage‑1 UsingResolver の MIR 観測 - 既存テスト `src/tests/mir_stage1_using_resolver_verify.rs` の MIR dump を元に、「どのループが Region+next_i 化候補か」「既に問題なく LoopForm に乗っている場所はどこか」を箇条書きで整理する。 ### B. Stage‑1 UsingResolver 箱化・ループ整理(.hako 側) - B-1: Stage1UsingResolverBox の責務分割設計 - `lang/src/compiler/entry/using_resolver_box.hako` を、collect_entries / modules_map / file_read などの小さいロジック箱に概念的に分割し、「どの箱が何を責務とするか」を docs に書く(実際のファイル分割は後段)。 - B-2: すべてのループを Region+next_i 形に揃える計画 - entry の UsingResolver 内に残っている「pos++/continue 多発型」ループを洗い出し、Region+next_i 形にどう書き換えるかを phase-25.1 docs に追記する。 - 目的: LoopForm v2 / PHI から見たときに「1 region / 1 backedge / 明確な次位置決定」という形に統一する。 - 状況メモ: entry 側 3 ループ(entries/JSON scan/modules_list)は Region+next_i 化済み。残りなし。 - B-3: pipeline_v2 UsingResolver との役割分担 - `lang/src/compiler/pipeline_v2/using_resolver_box.hako` と entry/Stage1UsingResolverBox のどちらが「テキスト / JSON / modules_map」のどこまでを担当するかを整理し、責務境界をドキュメントに固定する。 - 状況メモ: pipeline_v2 側は modules_json の alias 解決のみ(RegexFlow.find_from の単一路ループ)。Region 化不要として据え置き、境界だけ明記。 - B-4: 構造テストの追加計画 - Region+next_i パターンの軽量 SSA テスト(すでに 1 本追加済み)を基準に、もう 1〜2 本、UsingResolver ソースに近いパターン(JSON スキャン+early-exit)を追加する方針を決める。 ### C. Stage‑1 CLI / program-json / mir-json Self‑Host 準備 - C-1: Stage‑1 CLI インターフェースの設計メモ - `.hako → Program(JSON)` / `Program(JSON) → MIR(JSON)` / `MIR(JSON) → 実行` を Stage‑1 側からどう呼び出すか(関数名・引数レベル)を docs に先に書く。 - C-2: Stage‑B → Stage‑1 データフロー図 - `compiler_stageb.hako` → Program(JSON v0) → Stage‑1 UsingResolver → MirBuilder までのパイプラインを Phase‑25.1 ドキュメントに 1 枚の図としてまとめる。 - C-3: Rust CLI 側ブリッジの最小ガード案 - Stage0/Rust CLI は「Program(JSON/MIR(JSON) を受け取り VM/LLVM に流すだけ」に縮退させる方針と、既定 OFF トグル(selfhost 入口)をどう切るかを設計メモとして追加。 ### D. 将来フェーズ向けメモ(variable_map 決定化ライン) - D-1: MirBuilder::variable_map / BoxCompilationContext::variable_map BTreeMap 化案 - どの構造を HashMap→BTreeMap 化するか、どのテスト(`mir_funcscanner_skip_ws_vm_debug_flaky` など)で決定性を確認するかを Phase‑25.x の設計メモとして書いておく。 - D-2: dev 専用 / flaky テストの扱い方針 - どのテストが dev ignore(手動実行用)で、いつ/何を満たしたら常時有効に戻すかを、このファイルと関連 README に明確に残す。 このセクションは「すぐ実装する TODO ではなく、25.1〜25.x ラインで踏むべき設計タスク一覧」として使う予定だよ。 (静的 me-call 修正の参考メモはここに残しつつ、別セクションは整理済み) ## 3. Phase 25.1q — LoopForm Front Unification(DONE / follow-up 別タスクへ) - 目的: Rust AST ルート (LoopBuilder) と JSON v0 ルート (`json_v0_bridge::lower_loop_stmt`) のループ lowering を “LoopFormBuilder + LoopSnapshotMergeBox” に一本化し、どの経路からでも同じ SSOT を見るだけで良い構造に揃える。 - 完了状態: - AST ルート: - `LoopBuilder::build_loop_with_loopform` で canonical `continue_merge_bb` を常時生成し、`continue_target` を header ではなく `continue_merge_bb` に統一済み。 - `LoopFormBuilder::seal_phis` / `LoopSnapshotMergeBox` の continue/exit 入力は「preheader + continue_merge + latch」「header + break snapshots」で完全管理。 - JSON v0 ルート: - `loop_.rs` で `LoopFormJsonOps` を実装し、preheader/header/body/latch/continue_merge/exit の block ID を AST ルートと同じ形で生成。 - break/continue/exit の snapshot を `LoopSnapshotMergeBox` でマージし、canonical continue_merge → header backedge を JSON 側でも採用。 - `tests/json_program_loop.rs` で JSON v0 だけを入力にした軽量ループ(通常 / continue / body-local exit)を `MirVerifier` で確認するスモークを追加。 - Docs/README: - `docs/development/roadmap/phases/phase-25.1q/README.md` に「AST/JSON ともに LoopForm v2 + LoopSnapshotMergeBox が SSOT」と明記。 - `src/runner/json_v0_bridge/README.md` で “bridge は薄いアダプタであり、新しい PHI 仕様は loopform 側でのみ扱う” とガードを追記。 - `src/mir/phi_core/loop_phi.rs` には “legacy(分析用のみ)” コメントを追加。将来の cleanup (Phase 31.x) で削除対象とする。 - 残タスクは別フェーズへ: - Stage‑1 UsingResolver 周りの SSA バグ(`tests::mir_stage1_using_resolver_verify::mir_stage1_using_resolver_full_collect_entries_verifies` の Undefined Value)は 25.1q の範囲外。LoopForm の SSOT 化は終わっているため、今後は Stage‑1 側の PHI/Env スナップショット設計タスクとして切り出す。 - JSON v0 → Nyash AST への統合案や loop_phi.rs の実ファイル削除は、Phase 31.x cleanup 計画側で扱う。