diff --git a/docs/development/roadmap/phases/phase-25/README.md b/docs/development/roadmap/phases/phase-25/README.md new file mode 100644 index 00000000..3ed1be70 --- /dev/null +++ b/docs/development/roadmap/phases/phase-25/README.md @@ -0,0 +1,109 @@ +# Phase 25 — 脱Rustランタイム / Ring0-Ring1 再編 + +Status: proposal(設計フェーズ・実装は後続ホスト想定) + +## ゴール + +- Rust 層を **Ring0(最小シード)** に縮退し、それ以外のランタイム・数値コア・箱ロジックを **Hakorune(Ring1)** 側へ段階的に移行する。 +- 具体的には、Phase 21.6/21.8 で導入した: + - `IntArrayCore`(数値一次元配列コア) + - `MatI64`(行列箱・i64版) + などを、「Rust プラグイン実装」ではなく **Hakorune 実装+ごく薄い intrinsic** に置き換えるための設計ロードマップを固める。 +- 新しい箱・数値カーネル・標準ランタイム機能は **原則 .hako で実装する** 方針を明文化し、「Rust Freeze Policy(Self‑Host First)」を Phase 25 で具体化する。 + +## レイヤー方針(Ring0 / Ring1) + +### Ring0(Rust / C 相当 ― 最小シード) + +**責務:** +- プロセス起動・エントリポイント +- OS / FFI / LLVM C API への極小ラッパ +- VM の実行コア(命令デコード・レジスタファイル・GC/alloc の最小部分) +- **汎用 intrinsic** のみ提供(例: メモリ確保・生ポインタload/store・基本的な memcpy 等) + +**禁止 / 抑制:** +- 新しい Box 種類(IntArrayCore / MatI64 / StringBuilder 等)を Rust 側に増やさない。 +- 新しい最適化ロジック・言語ルール・Box メソッド実装を Rust に追加しない(AGENTS.md 5.2 Rust Freeze Policy に準拠)。 + +### Ring1(Hakorune / Nyash ― System サブセット) + +**責務:** +- 数値コア・行列コア・文字列ビルダなどの **「C 言語で書いていた部分」** を、Hakorune で実装する層。 +- 代表例: + - `nyash.core.numeric.intarray.IntArrayCore` + - `nyash.core.numeric.matrix_i64.MatI64` + - `StringBuilder` / 将来の `F64ArrayCore` 等 +- ランタイムポリシー・統計・ログ・一部の AotPrep / MIR パス(構造的なもの)。 + +**方針:** +- Rust 側が提供するのは `alloc/free/copy/load/store` などの **型パラメトリックな intrinsic** のみ。 +- 箱のフィールド管理(ptr+len+stride)、境界チェック、ループ本体、行列演算アルゴリズムなどは **すべて .hako 側で記述**。 +- Ring1 コードは AOT して `stdlib` 相当の成果物(例: `stdlib.hbc`)として VM 起動時にロードする構造を目指す。 + +## スコープ(Phase 25) + +Phase 25 は「設計とロードマップの確定」が主目的。実装・移行作業自体は後続フェーズ(22.x/26.x など)で分割実施する。 + +### 1) Rust Freeze の明文化とチェックリスト + +- 既存の「Rust Freeze Policy(Self‑Host First)」を、ランタイム/箱/数値系に特化して再整理: + - 新規 Box / ランタイム機能は Rust ではなく .hako で実装する。 + - Rust 変更は「最小の intrinsic 追加」か「バグ修正」に限定。 +- PR / フェーズ用チェックリスト案を作成: + - [ ] この変更は Ring0 の責務か?(VM/allocator/LLVM/OS FFI のみ) + - [ ] 新しい Box/アルゴリズムを Rust に追加していないか? + - [ ] .hako に移せる部分が残っていないか? + +### 2) IntArrayCore / MatI64 の移行設計 + +- 現状: + - Phase 21.6: Rust プラグイン `IntArrayCore` + Hako ラッパ Box。 + - Phase 21.8: `MatI64` Box を Hako で実装しつつ、コア配列は IntArrayCore に依存。 +- 目標: + - IntArrayCore の **本体ロジック(len 管理・get/set/fill 等)を Hako 側に移す**。 + - Rust 側は: + - `rt_mem_alloc_i64(len) -> (ptr,len)` + - `rt_mem_free_i64(ptr,len)` + - `rt_unsafe_load_i64(ptr, idx)` + - `rt_unsafe_store_i64(ptr, idx, val)` + など、小さな intrinsic 群に縮退。 +- タスク(設計レベル): + - 必要な intrinsic セットの定義(型・エラー処理ポリシー・Fail‑Fast方針)。 + - `nyash.core.numeric.intarray` の API 仕様と内部構造(ptr+len/所有権/ライフサイクル)を docs に固定。 + - MatI64 が IntArrayCore をどう利用するか(row-major/stride/ビューなど)を整理。 + +### 3) System Hakorune サブセットの定義 + +- Ring1 で「C 代替」として安全に使える記法/機能を定義: + - 推奨: 明示ループ(while/for)、Fail‑Fast、Box フィールドの明示管理。 + - 慎重に: 例外/非同期/動的ロードなど、ランタイム依存が重い機能。 +- ドキュメント案: + - `docs/development/runtime/system-hakorune-subset.md`(候補) + - 想定ユース: + - numeric core / matrix core + - runtime policy / stats + - 一部 MIR/AotPrep ロジック + +### 4) stdlib ビルド/ロード戦略のたたき台 + +- 目標: + - 「Hakorune で書かれた runtime/numeric コード」を AOT して、VM 起動時に一括ロードする仕組みを設計。 +- 方針案: + - `tools/hakc_stdlib.sh`(仮)で: + - `lang/src/runtime/**/*.hako` のうち Ring1 対象をコンパイルして `build/stdlib.hbc` を生成。 + - `hakorune` / `nyash` バイナリ起動時に: + - `stdlib.hbc` を自動ロード(PATH または env で切り替え)。 + - Phase 25 では「どのモジュールを stdlib に含めるか」「ビルド/ロードの責任境界」を文章で決めるところまで。 + +## アウト・オブ・スコープ(Phase 25) + +- 実際のコード移行(Rust 実装の削除や .hako への完全移植)は、このフェーズでは行わない。 +- 新しい機能追加や大規模最適化(VM/LLVM 側)は対象外。 +- 既存の 21.x フェーズのベンチ結果改善は、Phase 25 の直接スコープ外(ただし設計上のゴールには参考としてリンクする)。 + +## このフェーズ終了時の「完成形」 + +- Rust / Hakorune の責務分離が文書として明確になり、「新しい箱・数値カーネルは .hako で書く」がプロジェクトの合意として固定されている。 +- IntArrayCore / MatI64 の「Rust→Hakorune 移行」手順が、段階ごとのタスクリストとして整理されている。 +- System Hakorune サブセットと stdlib ビルド/ロード戦略のたたき台があり、後続フェーズ(例: Phase 22.x / 26.x)でそのまま実装に着手できる状態になっている。 + diff --git a/src/backend/mir_interpreter/handlers/extern_provider.rs b/src/backend/mir_interpreter/handlers/extern_provider.rs index 1817c2a2..b7a125b1 100644 --- a/src/backend/mir_interpreter/handlers/extern_provider.rs +++ b/src/backend/mir_interpreter/handlers/extern_provider.rs @@ -141,7 +141,21 @@ impl MirInterpreter { } if args.is_empty() { return Some(Err(ErrorBuilder::arg_count_mismatch("env.mirbuilder.emit", 1, args.len()))); } let program_json = match self.reg_load(args[0]) { Ok(v) => v.to_string(), Err(e) => return Some(Err(e)) }; - let res = match crate::host_providers::mir_builder::program_json_to_mir_json(&program_json) { + + // Phase 21.8: Read imports from environment variable if present + let imports = if let Ok(imports_json) = std::env::var("HAKO_MIRBUILDER_IMPORTS") { + match serde_json::from_str::>(&imports_json) { + Ok(map) => map, + Err(e) => { + eprintln!("[mirbuilder/imports] Failed to parse HAKO_MIRBUILDER_IMPORTS: {}", e); + std::collections::HashMap::new() + } + } + } else { + std::collections::HashMap::new() + }; + + let res = match crate::host_providers::mir_builder::program_json_to_mir_json_with_imports(&program_json, imports) { Ok(s) => Ok(VMValue::String(Self::patch_mir_json_version(&s))), Err(e) => Err(ErrorBuilder::with_context("env.mirbuilder.emit", &e.to_string())), }; @@ -290,7 +304,20 @@ impl MirInterpreter { } ("env.mirbuilder", "emit") => { if let Some(s) = first_arg_str { - match crate::host_providers::mir_builder::program_json_to_mir_json(&s) { + // Phase 21.8: Read imports from environment variable if present + let imports = if let Ok(imports_json) = std::env::var("HAKO_MIRBUILDER_IMPORTS") { + match serde_json::from_str::>(&imports_json) { + Ok(map) => map, + Err(e) => { + eprintln!("[mirbuilder/imports] Failed to parse HAKO_MIRBUILDER_IMPORTS: {}", e); + std::collections::HashMap::new() + } + } + } else { + std::collections::HashMap::new() + }; + + match crate::host_providers::mir_builder::program_json_to_mir_json_with_imports(&s, imports) { Ok(out) => Ok(VMValue::String(Self::patch_mir_json_version(&out))), Err(e) => Err(self.err_with_context("env.mirbuilder.emit", &e.to_string())), }