189 lines
12 KiB
Markdown
189 lines
12 KiB
Markdown
# Phase 25.1 — Stage0/Stage1 Bootstrap & Binary Layout
|
||
|
||
Status: design+partial implementation(Stage1 ビルド導線の初期版まで)
|
||
|
||
## ゴール
|
||
|
||
- Rust 製 `hakorune` を **Stage0 ブートストラップ**と位置付け、Hakorune コード(.hako)で構成された **Stage1 バイナリ**を明確に分離する。
|
||
- Rust 側の責務を「プロセス起動+最小 FFI+VM/LLVM コア」に縮退し、それ以外の機能(パーサ高レイヤ、Stage‑B、MirBuilder、AotPrep、numeric core 等)は Stage1 に寄せる。
|
||
- 将来的に「Stage1 hakorune(Hakorune 実装の EXE)」を日常利用の標準とし、Rust Stage0 は非常用ランチャ/ブートシードとして保持する。
|
||
|
||
## レイヤ構成(Stage0 / Stage1 / Runtime)
|
||
|
||
### Stage0 — Rust Bootstrap Binary
|
||
|
||
**想定バイナリ:**
|
||
- 将来: `target/release/hakorune-bootstrap`
|
||
- 現在: `target/release/nyash`(Rust 製 CLI。Stage0 ブートストラップとして扱う)
|
||
|
||
**責務:**
|
||
- OS エントリポイント(`main()`)とプロセス起動。
|
||
- 標準入出力・環境変数・argv の取得と最低限の整形。
|
||
- LLVM / OS FFI への極小ラッパ(`rt_mem_*` などの intrinsic の土台)。
|
||
- Rust VM/LLVM のコア(MIR インタプリタ/コード生成)の提供。
|
||
- Stage1 で AOT されたコア関数(後述)を呼び出すランチャ。
|
||
|
||
**禁止/抑制:**
|
||
- パーサ高レイヤ/Stage‑B/MirBuilder/AotPrep/numeric core のロジックを Rust 側に新規追加しない。
|
||
- 新しい Box 実装やランタイム機能を Rust に持ち込まない(Phase 25 Rust Freeze を継続)。
|
||
|
||
### Stage1 — Hakorune Selfhost Binary
|
||
|
||
**想定バイナリ:**
|
||
- `target/selfhost/hakorune`(Stage0 が AOT して生成する EXE; ファイル名で Stage1 を表し、配置ディレクトリで Stage0 と分離)
|
||
|
||
**構成要素(.hako 側で実装/AOT):**
|
||
- Stage‑B コンパイラ(`lang/src/compiler/entry/compiler_stageb.hako` など)。
|
||
- MirBuilder / MIR v1→v0 アダプタ。
|
||
- AotPrep(`selfhost.llvm.ir.aot_prep.*`、numeric core パスを含む)。
|
||
- Ring1 VM/runtime の一部(System Hakorune subset で書かれたコアロジック)。
|
||
|
||
**責務:**
|
||
- Source(.hako) → Program(JSON) → MIR → 実行/LLVM AOT の全パイプラインを Hakorune コードで担う。
|
||
- Stage1 自身を再ビルドできる最小セット(自己ホストコア)を提供する。
|
||
|
||
**起動イメージ:**
|
||
- Stage0 `main()`:
|
||
- 環境・argv を集約。
|
||
- AOT 済み `hakorune_main(argc, argv_ptr)`(Stage1 側関数)を呼び出すだけの薄い導線。
|
||
|
||
### Runtime Lines(共通)
|
||
|
||
- VM 実行エンジンと LLVM バックエンドは Stage0/Rust に残す(Ring0)。
|
||
- Ny 側からは `env.mirbuilder.emit` / `env.codegen.emit_object` / `env.codegen.link_object` といった extern 経由で利用する。
|
||
- Stage1 は Rust CLI(`nyash`)を「バックエンド CLI」として前提にせず、C-ABI/extern 経由で Ring0 機能にアクセスする。
|
||
- その上で Stage1/Hakorune コードを AOT したものをリンクして「言語本体」を構成する。
|
||
- 長期的には、Stage1 からさらに Stage1' を再ビルドして差分が収束する自己ホストサイクルを目指す。
|
||
- 具体的には「Stage0→Stage1(本バイナリ)」に加えて「Stage1→Stage1'」を実行し、両者の挙動/インターフェース一致を確認するチェックを設ける。
|
||
|
||
## ディレクトリ/バイナリ配置案
|
||
|
||
### Rust Stage0(Bootstrap)
|
||
|
||
- ソース配置案:
|
||
- `src/bootstrap/` … Stage0 専用のエントリポイント/FFI/VM/LLVM コアの窓口。
|
||
- 既存の Rust コードは徐々にここへ整理(広域リファクタは別フェーズで慎重に)。
|
||
- バイナリ:
|
||
- 現在: `target/release/nyash` … Stage0 実行ファイル(Rust 製 hakorune 相当)。
|
||
- 将来: `target/release/hakorune-bootstrap` … Stage0 専用バイナリ(名称を分離予定)。
|
||
|
||
### Hakorune Stage1(Selfhost)
|
||
|
||
- ソース:
|
||
- 既存どおり `lang/src/**` に配置(Stage‑B / MirBuilder / AotPrep / VM など)。
|
||
- Stage1 としてビルドすべきモジュールセットを `tools/selfhost/` 以下のスクリプトで管理する。
|
||
- バイナリ:
|
||
- 現在(Phase 25.1 初期実装):
|
||
- Dev line:
|
||
- `tools/selfhost/build_stage1.sh` → `apps/selfhost-runtime/runner.hako` を AOT し、`target/selfhost/hakorune` を生成する。
|
||
- 「Ny Executor(MIR v0 ランタイム)+CLI 実験」の開発用 EXE(最新版)。
|
||
- Stable line:
|
||
- `lang/build/build_runner.sh` → `lang/bin/hakorune` を生成(pure-lang launcher / legacy bring-up)。
|
||
- 安定した `target/selfhost/hakorune` を `lang/bin/hakorune` に昇格させて配布基準とする運用を想定。
|
||
- 将来:
|
||
- `lang/bin/hakorune` を「標準 hakorune」として日常利用のメインバイナリに昇格させる(dev line は常に先行する実験用バイナリ)。
|
||
- Stage0 は `hakorune-bootstrap` として非常用ランチャ/自己ホストの起点として残す。
|
||
|
||
## ビルド導線(Phase 25.1 初期版)
|
||
|
||
このフェーズでは「Rust Stage0 バイナリ」と「Hakorune Stage1 バイナリ」を、ビルド導線レベルで分離するところまでを行う。
|
||
|
||
### Makefile ターゲット(開発用)
|
||
|
||
- `make stage0-release`
|
||
- 役割: Rust Stage0(`target/release/nyash`)をビルドする。
|
||
- 実体: `cargo build --release`(既定機能のみ、Rust CLI のみを対象)。
|
||
- `make stage1-selfhost`
|
||
- 役割: Stage0 を利用して Stage1 selfhost バイナリをビルドする。
|
||
- 実体:
|
||
- `make stage0-release`(Stage0 準備)
|
||
- `tools/selfhost/build_stage1.sh`
|
||
- 出力: `target/selfhost/hakorune-selfhost`(Ny Executor 最小 EXE)。
|
||
|
||
### Stage1 ビルドスクリプト
|
||
|
||
- `tools/selfhost/build_stage1.sh`
|
||
- 入力: `apps/selfhost-runtime/runner.hako`(Ny Executor エントリ)。
|
||
- 経路:
|
||
1. `tools/hakorune_emit_mir.sh` で Stage‑B+MirBuilder を通し、MIR(JSON v1) を生成。
|
||
2. `tools/ny_mir_builder.sh --emit exe` で ny-llvmc 経由の EXE を生成。
|
||
- 出力: `target/selfhost/hakorune-selfhost`。
|
||
- 備考:
|
||
- EXE のインターフェースは開発用(MIR v0 ファイルを引数に取る Ny Executor)。フル CLI 化は後続フェーズで行う。
|
||
- `NYASH_LLVM_SKIP_BUILD=1` を指定すると、既存の ny-llvmc / nyash_kernel ビルド成果物を再利用して高速化できる。
|
||
|
||
## フェーズ内タスク(25.1 設計 TODO)
|
||
|
||
### A. Stage0/Stage1 境界のドキュメント固定
|
||
|
||
- [x] 本ファイル(phase-25.1/README.md)に Stage0/Stage1 の責務と禁止事項を明文化する。
|
||
- [x] Phase 25 README に Stage0/Stage1 の関係をリンク(Ring0/Ring1 の上位概念として扱う)。
|
||
- [x] CURRENT_TASK.md に「Stage0=Rust bootstrap / Stage1=Hakorune selfhost」の方針を追記。
|
||
|
||
### B. Stage1 コアセットの定義
|
||
|
||
- [ ] Stage1 で AOT すべきモジュール一覧をドラフトする(例: Stage‑B / MirBuilder / AotPrep / numeric core)。
|
||
- [ ] それらのエントリポイント関数(例: `hakorune_main/argc,argv` 相当)を .hako 側で定義する設計メモを追加。
|
||
|
||
### C. ビルド/配置戦略(設計のみ)
|
||
### C. ビルド/配置戦略(設計 → 初期実装)
|
||
|
||
- [x] `tools/selfhost/` 以下に Stage1 ビルド用スクリプト名と役割を決める(`build_stage1.sh`)。
|
||
- [x] `target/selfhost/` ディレクトリに Stage1 バイナリを配置する方針を Cargo/Makefile コメントに記載。
|
||
- [x] Makefile に `stage0-release` / `stage1-selfhost` ターゲットを追加し、Stage0/Stage1 のビルド導線を分離。
|
||
|
||
### D. 将来の自己ホストサイクルの入口を定義
|
||
|
||
- [ ] Stage0→Stage1→Stage1' のビルドシーケンスを文章で定義(どの組み合わせで自己一致チェックを行うか)。
|
||
- [ ] 「普段使うのは Stage1」「問題発生時に Stage0 から再生成」という運用パターンを docs に記載。
|
||
|
||
## 実装チェックリスト(25.1 実行順案)
|
||
|
||
### 1. バイナリ命名と役割の明確化
|
||
|
||
- [x] Cargo.toml に Stage0/Stage1 の bin ターゲット方針を書き出す(ドキュメントコメントレベル)。
|
||
- 現状: `[[bin]] name = "nyash"` を Stage0(Rust bootstrap)として扱い、Stage1 は `tools/selfhost/build_stage1.sh` で生成される `target/selfhost/hakorune` として外部管理。
|
||
- [ ] CURRENT_TASK.md に「ユーザーが使うのは `hakorune` / Stage0 は `hakorune-rust`」という運用ポリシーを追記。
|
||
|
||
### 2. Stage1 ランチャー(Hako側 Main)の骨組み
|
||
|
||
- [ ] `lang/src/runner/launcher.hako` を Stage1 の論理エントリポイントとして固定し、コメントに責務(モード切り替え)を書く。
|
||
- [ ] ランチャーから呼ぶパイプラインインターフェースを設計する:
|
||
- [ ] `.hako → Program(JSON)` を呼ぶ関数(Stage‑B)。
|
||
- [ ] `Program(JSON) → MIR(JSON)` を呼ぶ関数(MirBuilder)。
|
||
- [ ] `MIR(JSON) → PREP(MIR)` を呼ぶ関数(AotPrep + numeric_core)。
|
||
- [ ] `MIR(JSON) → 実行/EXE` を呼ぶ関数(VM/LLVM)。
|
||
- [ ] `launcher.hako` の `Main.main(args)` から、上記インターフェースを呼び分ける最小のモード分岐を定義する設計メモを追加(実装は後続フェーズでもよい)。
|
||
|
||
### 3. selfhost 用ビルドスクリプトの足場
|
||
|
||
- [ ] `tools/selfhost/` ディレクトリを作成(存在しない場合)。
|
||
- [ ] `tools/selfhost/build_stage1.sh`(仮称)の skeleton を追加:
|
||
- [ ] 必要な Hako モジュールセット(Stage‑B / MirBuilder / AotPrep / runtime)をコメントで列挙。
|
||
- [ ] 現時点では no-op または「未実装」のメッセージだけにして、呼び出し位置を固定。
|
||
- [ ] README(本ファイル)に build_stage1.sh の役割と将来の AOT 手順(.hako→MIR→ny-llvmc→EXE)を文章で書いておく。
|
||
|
||
### 4. Stage0 ↔ Stage1 の切り替えポリシー
|
||
|
||
- [ ] docs に「普段は Stage1 の `hakorune` を使い、壊れたときだけ Stage0 の `hakorune-rust` を直接叩く」という運用例を追記。
|
||
- [ ] `tools/selfhost/` に便利ラッパの案をメモしておく:
|
||
- 例: `hako-vm.sh`(Stage1 + `--backend vm`)、`hako-exe.sh`(Stage1 + `--backend llvm --exe`)。
|
||
|
||
### 5. 将来の自己ホストルートへの接続
|
||
|
||
- [ ] Stage1 の `Main.main(args)` から「自分自身を再ビルドする」エントリポイント名だけ決めておく(例: `selfhost_build_main`)。
|
||
- [ ] Phase 26 以降で、このエントリポイントを `tools/selfhost/build_stage1.sh` から呼ぶ形にする想定を書き残す。
|
||
|
||
このチェックリストは「コードを書く前に何を決めておくか」と「どこから小さく実装を始めるか」の順序を示すだけで、実装自体は後続フェーズで少しずつ進める前提だよ。
|
||
|
||
## このフェーズでやらないこと
|
||
|
||
- Rust コードの削除や広域リファクタ(責務の再ラベリングとロードマップ策定に留める)。
|
||
- Stage1 バイナリを CI で標準に昇格させる変更(ローカル開発用の設計段階に留める)。
|
||
- Stage1 ランチャー(フル CLI モード切り替え)の実装本体(このフェーズでは Ny Executor 最小 EXE まで)。
|
||
|
||
Related docs:
|
||
- `docs/development/roadmap/phases/phase-25/README.md` … Stage0/Ring0-Ring1 再編と numeric_core BoxCall→Call パスのまとめ。
|
||
- `docs/development/runtime/cli-hakorune-stage1.md` … Stage1 hakorune CLI のサブコマンド設計と Stage0 との役割分離。
|
||
- `docs/development/roadmap/phases/phase-25.1a/README.md` … Stage1 build パイプライン(Program→MIR/selfhost AOT)のホットフィックス計画。***
|