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)。
- 現在の entry:
-
tools/hakorune_emit_mir.sh— Program→MIR 部分:- Stage‑B(
compiler_stageb.hako):Stage-B: SUCCESS - Generated Program(JSON)まで成功("version":0,"kind":"Program"を含む JSON が得られている)。
- 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 <N>が出ており、prelude 連結のどこかで Stage‑3 構文と合わない断片が残っている状態(selfhost builder は引き続き要調査)。
- provider 経路(
try_provider_emit→env.mirbuilder.emit):- 当初は
env.mirbuilder.emit実行時に[mirbuilder/parse/error] undefined variable: argsにより失敗していたが、Rust 側の Program→MIR ルート修正によりこのエラーは解消済み。現在は provider 経路経由でlauncher.hakoから MIR(JSON) を安定して生成できている。
- 当初は
- legacy CLI 経路(
--program-json-to-mir):- Program(JSON) を一時ファイルに書いて
nyash --program-json-to-mirを叩くフォールバックも rc!=0 で終了していたが、Phase 25.1a では provider 経路の安定化を優先するため、現在は原則退避路とし、日常の導線では利用しない。
- Program(JSON) を一時ファイルに書いて
- Stage‑B(
-
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」を完全に排除する。
- 関数/ブロック構造・ローカル宣言のスタイルを既存の selfhost コードに合わせる(
- 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 のコードをシンプルに保つ。
- 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 の整理
- 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 復旧
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 パイプラインの上に乗せる形で進める。
- numeric_core AOT / microbench 統合・性能チューニングにフォーカス(
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) → EXEselfhost AOT パス。***- Notes:
- selfhost builder (
HAKO_SELFHOST_BUILDER_FIRST=1) は依然として parse error で落ちるため、Phase 25.1a では 既定を 0(無効) に切り替え、provider ルートを安定化させた。 - builder-first 経路の再有効化は Phase 25.1a 中の後続タスクとして扱う。
- selfhost builder (