# Phase 25.1a — Stage1 Build Pipeline Hotfix (Program→MIR) Status: hotfix-in-progress(緊急タスク/配線修正フェーズ) ## ゴール - Phase 25.1 で導入した Stage1 ランチャー(`lang/src/runner/launcher.hako`)と selfhost AOT パイプライン(`build_stage1.sh` 経由)を「実際に動く状態」に戻す。 - `.hako → Program(JSON v0) → MIR(JSON) → EXE` のうち、**Program(JSON v0) → MIR(JSON)** の導線を再構成し、`tools/hakorune_emit_mir.sh` / `tools/selfhost_exe_stageb.sh` / `tools/selfhost/build_stage1.sh` が代表ケースで成功するようにする。 - selfhost builder / provider / legacy CLI の 3 経路が混在した現状を見直し、**信頼できる1本の Program→MIR 経路**を中心に据える。 ## 現状の問題点(2025-11-15 時点) - `tools/selfhost/build_stage1.sh`: - 現在の entry: `lang/src/runner/launcher.hako`(Stage1 CLI ランチャー)。 - 内部で `tools/selfhost_exe_stageb.sh` → `tools/hakorune_emit_mir.sh` を呼び出しているが、MIR 生成フェーズで失敗。 - ログ: `[FAIL] Program→MIR delegate failed (provider+legacy)`。 - `tools/hakorune_emit_mir.sh` — Program→MIR 部分: 1. Stage‑B(`compiler_stageb.hako`): - `Stage-B: SUCCESS - Generated Program(JSON)` まで成功(`"version":0,"kind":"Program"` を含む JSON が得られている)。 2. selfhost builder 経路(`try_selfhost_builder`): - `builder_box=hako.mir.builder` で Runner を生成し、VM 経由で実行。 - 当初は tmp ハコファイルに対して `Parse error: Unexpected token FN` や `Unexpected token ASSIGN` が発生し rc=1 で失敗していたが、`lang/src/mir/builder/func_lowering.hako` の `local fn = func_jsons.length()` を `local func_len = ...` にリネームすることで `Unexpected token FN` 自体は解消済み。 - 現在は text-merge 後の巨大一時ファイルに対して `Parse error: Invalid expression at line ` が出ており、prelude 連結のどこかで Stage‑3 構文と合わない断片が残っている状態(selfhost builder は引き続き要調査)。 3. provider 経路(`try_provider_emit` → `env.mirbuilder.emit`): - 当初は `env.mirbuilder.emit` 実行時に `[mirbuilder/parse/error] undefined variable: args` により失敗していたが、Rust 側の Program→MIR ルート修正によりこのエラーは解消済み。現在は provider 経路経由で `launcher.hako` から MIR(JSON) を安定して生成できている。 4. legacy CLI 経路(`--program-json-to-mir`): - Program(JSON) を一時ファイルに書いて `nyash --program-json-to-mir` を叩くフォールバックも rc!=0 で終了していたが、Phase 25.1a では provider 経路の安定化を優先するため、現在は原則退避路とし、日常の導線では利用しない。 - Stage1 CLI (`launcher.hako`) の VM 実行: - `nyash --backend vm lang/src/runner/launcher.hako -- emit ...` で、 - `using` の解決(`lang.compiler.build.build_box`)は nyash.toml に追加済みだが、 - まだパーサが Stage‑3 構文/関数宣言の一部を受理できていない箇所があり、`Unexpected token ...` 系のエラーが残っている。 ## フェーズ内タスク(25.1a TODO) ### A. Stage1 CLI ソースの VM 実行復旧 - [ ] `lang/src/runner/launcher.hako` を Stage‑3 パーサが素直に通る形に調整する。 - [ ] 関数/ブロック構造・ローカル宣言のスタイルを既存の selfhost コードに合わせる(`function` 定義や `local` の位置など)。 - [ ] `using lang.compiler.build.build_box as BuildBox` 経路を nyash.toml / hako_module.toml に統一し、「ファイルパス using」を完全に排除する。 - [ ] VM 実行スモーク: - [ ] `NYASH_ALLOW_NYASH=1 ./target/release/nyash --backend vm lang/src/runner/launcher.hako -- emit program-json apps/selfhost-minimal/main.hako` が parse error なく通ること。 - [ ] 同様に `emit mir-json` / `build exe` も、少なくともエラーメッセージ付きで Fail-Fast するところまで確認する(VM 側での構文エラーがないこと)。 ### B. Program→MIR selfhost builder 経路の安定化 - [ ] `try_selfhost_builder` 内で生成される tmp ハコファイル(`__BUILDER_BOX__` 版)を最小ケースで切り出し、単体で parse/実行できるように修正。 - [ ] `args` 未定義エラーや `Invalid expression` の原因となっている記述を特定し、Runner 側の `Main.main(args)` などを正しく宣言する。 - [ ] Stage‑3 構文の使用を必要最小限に抑え、selfhost builder 用 Runner のコードをシンプルに保つ。 - [x] Stage‑3 パーサで予約語となった `fn` をローカル変数名として使っている箇所(例: `lang/src/mir/builder/func_lowering.hako` の `local fn = func_jsons.length()`)をリネームし、`Unexpected token FN, expected identifier` を根本的に解消する。 - [ ] `try_selfhost_builder` を **第一候補** とし、代表ケース(launcher.hako 等)で常にここが成功することを確認。 - [ ] `HAKO_SELFHOST_BUILDER_FIRST=1` で `tools/hakorune_emit_mir.sh` を叩いたときに `[OK] MIR JSON written (selfhost-first)` まで到達することをスモークで確認。 ### C. Provider / legacy delegate の整理 - [x] provider 経路(`env.mirbuilder.emit`)での `undefined variable: args` 原因を修正し、Stage‑B が出力する Program(JSON v0) を正しく受理できるようにする。 - [ ] `HAKO_V1_EXTERN_PROVIDER` / `HAKO_V1_EXTERN_PROVIDER_C_ABI` トグルのデフォルトを見直し、「selfhost builder が成功するなら provider には落ちない」構造に寄せる。 - [ ] legacy CLI 経路(`--program-json-to-mir`)は、「selfhost builder が失敗したときだけ最後に試す」退避路として残しつつ、代表ケースでは通さない方針にする。 - [ ] 必要であれば Phase 25.1a 中は `HAKO_SELFHOST_NO_DELEGATE=1` を既定 ON に近い扱いにし、「selfhost builder が通る範囲」に問題を絞る。 ### D. build_stage1.sh / selfhost_exe_stageb.sh 復旧 - [x] `NYASH_LLVM_SKIP_BUILD=1 tools/selfhost/build_stage1.sh --out /tmp/hakorune-dev` が 0 exit すること(現状は selfhost builder を既定OFFにし、provider ルートで MIR を生成)。 - [ ] 生成された `/tmp/hakorune-dev` について: - [ ] `./hakorune-dev emit program-json apps/selfhost-minimal/main.hako` が Program(JSON v0) を出力すること。 - [ ] `./hakorune-dev emit mir-json apps/selfhost-minimal/main.hako` が MIR(JSON) を出力すること。 - [ ] `./hakorune-dev build exe -o /tmp/hako_min apps/selfhost-minimal/main.hako` で簡単な EXE が生成され、実行して 0 exit を返すこと。 - [ ] `tools/selfhost_exe_stageb.sh` についても同様に `.hako → EXE` のスモークを通しておく(少なくとも launcher.hako / apps/selfhost-minimal/main.hako の2ケース)。 ## 25.1 / 25.1a / 25.2 の関係 - Phase 25.1: - Stage0/Stage1 の責務とバイナリレイアウトを設計し、Stage1 CLI(launcher.hako)の顔と構文を固めるフェーズ。 - Phase 25.1a(本ファイル): - 「設計した Stage1 CLI / selfhost パイプラインが実際に動くようにする」緊急ホットフィックスフェーズ。 - Scope はあくまで **Program→MIR と selfhost AOT の復旧** に限定し、numeric_core などの最適化には踏み込まない。 - Phase 25.2: - numeric_core AOT / microbench 統合・性能チューニングにフォーカス(`matmul_core` など)。 - 25.1a で安定化した selfhost パイプラインの上に乗せる形で進める。 ## Related docs - `docs/development/roadmap/phases/phase-25.1/README.md` … Stage0/Stage1 Bootstrap & Binary Layout(設計+初期実装)。 - `docs/development/roadmap/phases/phase-25/README.md` … Ring0/Ring1 再編と numeric_core BoxCall→Call パス。 - `docs/development/runtime/cli-hakorune-stage1.md` … Stage1 hakorune CLI のサブコマンド設計と実装範囲。 - `tools/hakorune_emit_mir.sh` … Stage‑B → Program(JSON v0) → MIR(JSON) の selfhost+delegate パイプライン。 - `tools/selfhost_exe_stageb.sh` / `tools/selfhost/build_stage1.sh` … `.hako → MIR(JSON) → EXE` selfhost AOT パス。*** - Notes: - selfhost builder (`HAKO_SELFHOST_BUILDER_FIRST=1`) は依然として parse error で落ちるため、Phase 25.1a では **既定を 0(無効)** に切り替え、provider ルートを安定化させた。 - builder-first 経路の再有効化は Phase 25.1a 中の後続タスクとして扱う。