feat(phase-21.8+25): Complete imports resolution + Ring0/Ring1 numeric ABI design

Phase 21.8 完了 (imports resolution):
-  using nyash.core.numeric.matrix_i64 as MatI64 完全対応
-  hakorune_emit_mir.sh で imports 抽出・MirBuilder に配線
-  MatI64/IntArrayCore の静的参照解決が安定動作
-  matmul_core ベンチ MIR 生成成功 (VM/LLVM 両対応)

Phase 25 設計完了 (Ring0/Ring1 + numeric ABI):
- 🎯 Ring0/Ring1 責務分離を明文化 (Rust Freeze Policy 具体化)
- 🎯 Call/ExternCall 明確な分離設計
  - Call: Ring1 Hako 関数 (numeric core 等)
  - ExternCall: Ring0 intrinsic (rt_mem_* 等の FFI のみ)
- 🎯 BoxCall → Call 変換方針確定 (AotPrep で実施)
- 🎯 MatI64.mul_naive を NyNumericMatI64.mul_naive に分離
  (System Hakorune subset で完全実装済み)

実装:
-  AotPrepNumericCoreBox 診断パス実装 (NYASH_AOT_NUMERIC_CORE=1)
-  numeric ABI ドキュメント整備 (NUMERIC_ABI.md)
-  System Hakorune subset 定義 (system-hakorune-subset.md)
-  IntArrayCore/MatI64 仕様固定 (lang/src/runtime/numeric/README.md)
-  ENV_VARS.md に NYASH_AOT_NUMERIC_CORE トグル追記

今後のタスク:
- BoxCall(MatI64) → Call(NyNumericMatI64) 変換実装 (opt-in)
- IntArrayCore の numeric core 整備
- matmul_core スモークテスト (NYASH_AOT_NUMERIC_CORE=0/1 両対応)

🎉 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-14 20:19:00 +09:00
parent 8c4d63bfbb
commit 864a94d013
11 changed files with 716 additions and 34 deletions

View File

@ -1,17 +1,17 @@
# Phase 21.8 — Numeric Core Integration & Builder Support
Status: proposal (to hand off to Claude Code)
Status: partially completedbuilder/imports導線まで・EXEベンチはPhase 25へ移管
## Goal
Integrate the new numeric core boxes (IntArrayCore + MatI64) into the Hakorune selfhost chain so that:
- StageB → MirBuilder → nyllvmc(crate) can emit MIR(JSON) and EXE for code that uses:
- StageB → MirBuilder → nyllvmc(crate) can emit MIR(JSON) for code that uses:
- `using nyash.core.numeric.intarray as IntArrayCore`
- `using nyash.core.numeric.matrix_i64 as MatI64`
- The `matmul_core` microbench (MatI64 + IntArrayCore) runs endtoend in EXE mode and can be compared fairly against a matching C implementation.
- The `matmul_core` microbenchMatI64 + IntArrayCore)については、**構造的な導線builder/importsまで本フェーズで整備し、EXE/LLVM ベンチ統合は Phase 25 に移管する**。
21.6 provides the core boxes; 21.8 focuses on wiring them into the builder/runtime chain without changing default behaviour for other code.
21.6 provides the core boxes; 21.8 focuses on wiring them into the builder/runtime chainStageB/Bridge/MirBuilderwithout changing default behaviour for other code. LLVM での数値コア実行経路は Phase 25Ring0/Ring1 再編・numeric runtime AOTで扱う。
## Scope (21.8, this host)
@ -73,13 +73,33 @@ Out of scope:
4) **Keep existing behaviour stable**
- No changes to default user behaviour, env toggles, or existing benches beyond adding `matmul_core`.
- Ensure quick/profile smokes (where applicable) remain green with numeric core present.
- Ensure quick/profile smokes (where applicable) remain green with numeric core present.
## Notes
## 結果2025-11-14 時点)
- 21.6 already introduced:
- NyRT `IntArrayCore` (Vec<i64> + RwLock) and handlebased externs (`nyash.intarray.*`).
- Hako wrappers `IntArrayCore` and `MatI64` in `lang/src/runtime/numeric/`.
- `nyash.toml` module aliases for `nyash.core.numeric.intarray` and `nyash.core.numeric.matrix_i64`.
- 21.8 is about wiring these into the builder/emit chain so that Hakorune can compile and benchmark numeric core code endtoend.
本フェーズは「builder/imports 導線の整備」までを完了とし、EXE/LLVM ベンチ統合は Phase 25 に移管する。
**達成済み21.8**
- StageB / Bridge / MirBuilder:
- `BridgeEnv``imports: HashMap<String,String>` フィールドを追加し、using 由来のエイリアス情報alias → box_typeを保持できるようにした。
- `MapVars::resolve` を拡張し、`env.imports` を参照して `MatI64` / `IntArrayCore` などの using エイリアスを「静的 box 参照」として MIR 上で解決できるようにした。
- JSON v0 → MIR(JSON) 経路に `*_with_imports` 版を追加:
- `runner::json_v0_bridge::parse_json_v0_to_module_with_imports`
- `host_providers::mir_builder::program_json_to_mir_json_with_imports`
- `HAKO_MIRBUILDER_IMPORTS` 環境変数を経由して、StageB 側で収集した imports を Rust 側の MirBuilder に渡す配線を追加(読み取り側)。
- Using / imports 収集:
- `collect_using_and_strip` の戻り値を `(cleaned, prelude_paths, imports)` に拡張し、using から alias 情報を収集できるようにした。
- 既存呼び出し側は `_imports` として無視するため、従来挙動は維持。
- MatI64/IntArrayCore:
- `using nyash.core.numeric.matrix_i64 as MatI64` / `using nyash.core.numeric.intarray as IntArrayCore` の構文が StageB/Bridge で undefined variable エラーにならないところまで確認済みbuilder 経路に乗る)。
**未完・移管Phase 25 に送るもの)**
- `matmul_core` microbench の EXE/LLVM 統合:
- MIR 上では `MatI64` が BoxCall として現れるが、LLVM ラインには BoxCall 実行経路がなく、AotPrep も MatI64 向けの書き換えを持たない。
- 「MatI64/IntArrayCore を LLVM までどう運ぶか」numeric ABI / AotPrep / Ring1 AOT 設計は、Phase 25「脱Rustランタイム / Ring0-Ring1再編」で扱う。
- Numeric core AOT ライン:
- IntArrayCore/MatI64 の実装を `.hako`Ring1側に寄せ、LLVM からは汎用 `ExternCall`/numeric ABI のみを見る構造は Phase 25 の設計スコープとする。
詳細な将来計画・numeric runtime AOT 方針については `docs/development/roadmap/phases/phase-25/README.md` を参照。

View File

@ -40,6 +40,14 @@ Status: proposal設計フェーズ・実装は後続ホスト想定
- 箱のフィールド管理ptr+len+stride、境界チェック、ループ本体、行列演算アルゴリズムなどは **すべて .hako 側で記述**
- Ring1 コードは AOT して `stdlib` 相当の成果物(例: `stdlib.hbc`)として VM 起動時にロードする構造を目指す。
### Rust ソースの保存ポリシー
- 本フェーズは **Rust コードの削除ではなく、責務の縮退と凍結** を目的とする。
- `src/` 以下の Ring0 Rust ソースVM コア / LLVM・OS FFI / 起動コード)は、将来もブートストラップ用としてリポジトリに残す前提とする。
- 脱Rustが進み、将来 Hakorune EXE 単独で自己ホスト可能になっても:
- Ring0 Rust は「アーカイブ兼非常用バックアップ」として保持する。
- 削除や完全な Rust 依存断絶は、別フェーズ(かつ明示的な設計・合意)なしには行わない。
## スコープPhase 25
Phase 25 は「設計とロードマップの確定」が主目的。実装・移行作業自体は後続フェーズ22.x/26.x など)で分割実施する。
@ -69,16 +77,136 @@ Phase 25 は「設計とロードマップの確定」が主目的。実装・
など、小さな intrinsic 群に縮退。
- タスク(設計レベル):
- 必要な intrinsic セットの定義型・エラー処理ポリシー・FailFast方針
- `nyash.core.numeric.intarray` の API 仕様と内部構造ptr+len/所有権/ライフサイクル)を docs に固定。
- `nyash.core.numeric.intarray` / `nyash.core.numeric.matrix_i64` の API 仕様と内部構造ptr+len/rows/cols/stride/所有権/ライフサイクル)を docs に固定。
- Box レベルの仕様: `lang/src/runtime/numeric/README.md` に IntArrayCore / MatI64 のフィールド・メソッド契約を記述。
- Core / Handle レベルの仕様: 本ファイルおよび System Hakorune subset / numeric ABI ドキュメントで補完。
- MatI64 が IntArrayCore をどう利用するかrow-major/stride/ビューなど)を整理。
#### 2.1) Numeric ABIIntArrayCore / MatI64の詳細方針
**ゴール:**
- MatI64 / IntArrayCore のような数値箱を LLVM まで運ぶ際に、「箱の知識」は Ring1 に閉じ込め、Ring0Rust+LLVMは汎用的な `Call` / `ExternCall` しか知らなくて済む構造にする。
**基本方針:**
- BoxCall を LLVM まで持ち込まない:
- LLVM に渡す最終 MIR には、原則として:
- `Const / BinOp / Compare / Branch / Jump / Ret`
- `Call`(通常の関数呼び出し)
- `ExternCall`NyRT / 低レベル intrinsic 呼び出し)
- `NewBox`(必要最小限)
- `BoxCall(MatI64, ...)``BoxCall(IntArrayCore, ...)` は AotPrep で潰す。
- 箱の構造・都合は Ring1 で完結させる:
- MatI64 / IntArrayCore のフィールド構造やメソッドは Ring1 が知るだけでよい。
- Ring0/LLVM から見ると「固定 ABI の関数呼び出し」に見えるようにする。
**Ring1 側の責務: numeric ABI 定義とラッパー**
- IntArrayCore / MatI64 向けに固定された numeric ABI 関数セットを定義する(例・概念レベル):
- `ny_numeric_intarray_new(len: i64) -> IntArrayHandle`
- `ny_numeric_intarray_get(a: IntArrayHandle, idx: i64) -> i64`
- `ny_numeric_intarray_set(a: IntArrayHandle, idx: i64, v: i64)`
- `ny_numeric_mat_i64_new(rows: i64, cols: i64) -> MatI64Handle`
- `ny_numeric_mat_i64_mul_naive(a: MatI64Handle, b: MatI64Handle, n: i64) -> MatI64Handle`
- 具体的な関数一覧・事前条件・FailFast 方針は `docs/development/runtime/NUMERIC_ABI.md` に整理する。
- 実装:
- Phase 25 の段階では、これらを **Ring1 の通常の Hako 関数** として実装し、MIR 上では `Call` 命令として現れる形を基本とする。
- 将来、別バイナリや C 実装に差し替える場合のみ、同じ関数群を ExternCall/FFI 経由で公開する案を検討するPhase 26 以降)。
- これらの関数名・引数型を「numeric ABI」として docs に固定する。
- MatI64 / IntArrayCore Box メソッドは「numeric ABI の薄ラッパ」として実装する:
- 例: `MatI64.mul_naive(self, rhs, n)` の本体は Ring1 numeric core 関数(例: `NyNumericMatI64.mul_naive(self, rhs, n)`)を 1 回呼ぶだけ。
- VM/インタープリタライン: BoxCall をそのまま実行すればラッパ経由で numeric core に到達する。
- AOT/LLVM ライン: BoxCall を numeric core 関数への `Call` に書き換えるだけで済むBoxCall を LLVM まで持ち込まない)。
**BoxCall → Callnumeric core変換AotPrep / builder の責務)**
- 初期 MIR では `BoxCall(MatI64, "new", ...)``BoxCall(MatI64, "mul_naive", ...)` が現れる。
- Ring1 の AotPrep パスで、これらを numeric core 関数への `Call` に変換する計画とし、Phase 25 ではそのための診断パス(`AotPrepNumericCoreBox`)を用意する:
- 例(概念レベル):
- `BoxCall(MatI64, "new", ...)``Call NyNumericMatI64.new_core(...)`
- `BoxCall(MatI64, "mul_naive", ...)``Call NyNumericMatI64.mul_naive(...)`
- これらは一時しのぎのハードコードではなく、Ring1 numeric ランタイムの正規インターフェースとして docs に固定する(実際の書き換えは後続フェーズで実装)。
- 拡張性:
- 可能なら「Box 型ID + メソッドID → numeric core 関数 ID」のテーブルで持つメタデータ化
- 少なくとも `MatI64` / `IntArrayCore` を識別する Box 型IDを見てから変換する方針にする文字列 if の乱立を避ける)。
**Ring0 側の責務: 汎用 Call/ExternCall のみ**
- LLVM backend は汎用的な `Call` / `ExternCall` のコード生成のみ実装する。
- `Call` → Hako から生成された通常の関数呼び出しに変換numeric core 関数もここに含まれる)。
- `ExternCall` → NyRT / OS / C など「Hakorune 外部」の FFI だけを扱う(`rt_mem_alloc_i64` 等)。
- Ring0 は「MatI64 という箱がある」「IntArrayCore という型がある」といった情報を持たない。
- numeric core について知っているのは「`Call @ny_numeric_*` という形の関数が存在する」という事実だけであり、Box 型や内部フィールド構造は Ring1 に閉じ込める。
**Handle / Core の設計ポリシー(概念レベル)**
- `IntArrayHandle` / `MatI64Handle` は実質 Core 構造を指すものとして扱う:
- 例: `struct IntArrayCore { i64* ptr; i64 len; };`
- `struct MatI64Core { i64* ptr; i64 rows; i64 cols; i64 stride; };`
- Box 側MatI64 Boxはこれら Core をラップするだけにする。
- GC を導入する場合、numeric Core は pinned / nonmoving 領域または明示的 malloc/free 管理とし、Box→Core の所有権・ライフサイクルを Ring1 側で管理する。
**ABI 関数セット(初期案の固定方針)**
- IntArrayCore1 次元 i64 配列):
- `ny_numeric_intarray_new(len: i64) -> (IntArrayHandle)`
- 役割: 長さ `len` のゼロ初期化配列を確保する。
- 失敗時: OOM など致命的エラーは FailFastプロセス終了または未定義だが「静かに 0 を返す」等は禁止)。
- `ny_numeric_intarray_free(a: IntArrayHandle)`
- 役割: Core を解放する(多重 free は未定義とし、Ring1 側の所有権設計で防ぐ)。
- `ny_numeric_intarray_len(a: IntArrayHandle) -> i64`
- 役割: 現在の長さを返す(境界チェック不要)。
- `ny_numeric_intarray_get(a: IntArrayHandle, idx: i64) -> i64`
- 役割: `0 <= idx < len` を前提とした読み取り。範囲外は FailFast。
- `ny_numeric_intarray_set(a: IntArrayHandle, idx: i64, v: i64)`
- 役割: `0 <= idx < len` を前提とした書き込み。範囲外は FailFast。
- MatI642 次元 i64 行列; rowmajor:
- `ny_numeric_mat_i64_new(rows: i64, cols: i64) -> (MatI64Handle)`
- 役割: 行列本体を `rows * cols` 要素で確保し、ゼロ初期化する。
- `ny_numeric_mat_i64_free(m: MatI64Handle)`
- 役割: Core を解放する(所有権は Box 側が管理)。
- `ny_numeric_mat_i64_dims(m: MatI64Handle) -> (rows: i64, cols: i64)`
- 役割: 行数・列数を返す(構造検査用)。
- `ny_numeric_mat_i64_get(m: MatI64Handle, row: i64, col: i64) -> i64`
- 役割: `0 <= row < rows`, `0 <= col < cols` を前提とした読み取り。範囲外は FailFast。
- `ny_numeric_mat_i64_set(m: MatI64Handle, row: i64, col: i64, v: i64)`
- 役割: 上記と同じ前提の書き込み。範囲外は FailFast。
- `ny_numeric_mat_i64_mul_naive(a: MatI64Handle, b: MatI64Handle, n: i64) -> MatI64Handle`
- 役割: `n x n` 行列同士のナイーブな行列積。`n``dims` の不整合は FailFastベンチ用の前提エラーは早期に止める
**ABI 型と呼び出し規約(概念レベル)**
- `IntArrayHandle` / `MatI64Handle` は LLVM / C 側では「Core 構造体を値渡しする ABI」として扱う案を第一候補とする:
- C 側イメージproposal:
- `typedef struct { int64_t *ptr; int64_t len; } ny_intarray_handle;`
- `typedef struct { int64_t *ptr; int64_t rows; int64_t cols; int64_t stride; } ny_mat_i64_handle;`
- MIR から見ると「2 〜 4 個の `i64` をまとめた値」として ExternCall の引数/戻り値に現れる。
- 将来、GC 等でハンドルをテーブル管理に変えたくなった場合も、「ハンドルは ABI 上は i64×N で表現する」という規約だけを維持すればよい。
- ExternCall 側の型:
- `ExternCall` から見える型はすべて `i64` のみとし、「どのスロットが ptr/len/rows/cols か」は numeric ABI 側の約束で固定する。
- これにより LLVM backend は「i64 のタプルをそのまま C 関数に渡す」だけで済み、箱/行列の構造を知らなくてよい。
**エラー処理と FailFast ポリシー**
- OOM / 致命的エラー:
- numeric ABI レベルでは「戻り値でのエラー表現」は行わず、FailFast を原則とする(プロセス終了 or 例外経路など、実装詳細は後続フェーズで決める)。
- 「負の長さ」「rows*cols のオーバーフロー」など明らかなバグ入力も FailFast。
- 境界違反:
- `*_get` / `*_set` / `*_mul_naive` など、index/dims に依存する API は **事前条件を満たさない呼び出しをすべてバグ扱い** とし、FailFast する。
- 「エラーコードを返して上層で if する」スタイルは禁止AGENTS.md の対処療法禁止と揃える)。
- Box 側との責務分離:
- Box メソッドは「precondition を満たすように引数を構成して numeric ABI を呼ぶ」責務のみを持ち、境界チェックの抜けや重複を避ける。
- numeric ABI 側は「precondition 違反を検出したら即 FailFast」することで、バグを早期発見する。
### 3) System Hakorune サブセットの定義
- Ring1 で「C 代替」として安全に使える記法/機能を定義:
- 推奨: 明示ループwhile/for、FailFast、Box フィールドの明示管理。
- 慎重に: 例外/非同期/動的ロードなど、ランタイム依存が重い機能。
- ドキュメント:
- `docs/development/runtime/system-hakorune-subset.md`候補
- ドキュメント:
- `docs/development/runtime/system-hakorune-subset.md`本ガイド
- 想定ユース:
- numeric core / matrix core
- runtime policy / stats
@ -90,11 +218,91 @@ Phase 25 は「設計とロードマップの確定」が主目的。実装・
- 「Hakorune で書かれた runtime/numeric コード」を AOT して、VM 起動時に一括ロードする仕組みを設計。
- 方針案:
- `tools/hakc_stdlib.sh`(仮)で:
- `lang/src/runtime/**/*.hako` のうち Ring1 対象をコンパイルして `build/stdlib.hbc` を生成。
- `lang/src/runtime/**/*.hako` のうち Ring1 対象(特に `lang/src/runtime/numeric/` 以下)をコンパイルして `build/stdlib.hbc` を生成。
- `hakorune` / `nyash` バイナリ起動時に:
- `stdlib.hbc` を自動ロードPATH または env で切り替え)。
- Phase 25 では「どのモジュールを stdlib に含めるか」「ビルド/ロードの責任境界」を文章で決めるところまで。
### 5) stdlib モードと衝突回避ポリシーembedded / source
- 目的:
- IntArrayCore / MatI64 など、同じモジュール名を持つ数値箱が「埋め込み stdlib」と「開発中 .hako ソース」で二重定義されて衝突しないようにする。
- 方針:
- `nyash.core.numeric.*` 系モジュールは **stdlib 専用の名前空間**として扱い、1 度の実行中に有効な実装は常に 1 つだけとする。
- 実装の SSOT は `.hako` とし、埋め込みは「その時点の .hako を AOT した成果物」としてのみ存在させる(別実装は持たない)。
- モード案env ベースの切替; 名前は Phase 26 以降で最終決定):
- `NYASH_STDLIB_MODE=embedded`(デフォルト候補):
- 起動時に `stdlib.hbc` をロードし、`nyash.core.numeric.*` は埋め込み stdlib から提供。
- 同じモジュール名をファイルで定義しても、原則として無視 or 警告(開発時のみ許可)とし、実行時には埋め込み版だけが有効になる。
- `NYASH_STDLIB_MODE=source`(開発専用候補):
- `stdlib.hbc` をロードせず、StageB/VM が `lang/src/runtime/numeric/*.hako`(など)を直接コンパイルして runtime/numeric を提供。
- このモードでは埋め込み stdlib は無効化され、`.hako` ソースでのみ挙動が決まる。
- 利点:
- 本番/ベンチでは embedded モードで安定した numeric stdlib を使用できる。
- 開発時は source モードで IntArrayCore/MatI64 の `.hako` を編集しながら試せる。
- 「同じ名前の箱が2つ同時に有効になる」状態を構造的に防げる。
## 実装チェックリストPhase 25 以降で順番にやる)
Phase 25 自体は設計フェーズだが、後続フェーズ22.x / 26.x など)で実装を進める際のチェックリストをここにまとめておく。
### A. 設計・ドキュメント
- [ ] Rust Freezeランタイム/箱/数値系)の詳細ポリシーを docs に固定する。
- [ ] 「新しい箱・数値カーネルは .hako で書く」方針を明文化。
- [ ] Ring0 で許可される変更種別intrinsic 追加 / バグ修正のみ)を列挙。
- [ ] System Hakorune サブセットのガイド(`docs/development/runtime/system-hakorune-subset.md`)を整備する。
- [ ] 使用を推奨する構文/機能ループ、FailFast 等)。
- [ ] 慎重に扱う機能(例外/非同期/動的ロード 等)。
- [ ] IntArrayCore / MatI64 の API 仕様と内部構造を docs で固定する。
- [ ] フィールドptr/len/rows/cols/stride 等)の意味と所有権ポリシー。
- [ ] public メソッドとその契約境界チェック有無、FailFastポリシー
- [ ] Numeric ABI`ny_numeric_*`)の関数セットを文書化する。
- [ ] 関数名・引数型・戻り値型・エラーハンドリング規約。
- [ ] 必要になった場合のみC/Rust から呼ぶ際のシンボル名規約を決める。
### B. Ring0Rust側の最小実装
- [ ] 既存ランタイムに不足している最小 intrinsic を確認し、必要なら追加する。
- [ ] `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)`
- [ ] LLVM backend が既存の `ExternCall` メカニズムで Ring0 intrinsic`rt_mem_*` 等)を扱えることを確認する。
- [ ] numeric 用に特別な分岐を追加せず、必要なら共通の規約ベースでシンボル名を組み立てる。
### C. Ring1.hako側 numeric runtime
- [ ] `nyash.core.numeric.intarray` を Ring1 実装に移行する。
- [ ] IntArrayCore を `.hako` で実装ptr+len 管理 / get/set/fill 等)。
- [ ] 内部で Ring0 intrinsicalloc/free/load/storeを使用する。
- [ ] 既存の Rust プラグイン実装との整合性を確認し、最終的に Rust 実装を縮退 or 退役できるようにする。
- [ ] `nyash.core.numeric.matrix_i64`MatI64を numeric ABI ベースのラッパ Box に整える。
- [ ] フィールドに Core ハンドルMatI64Handleを持つ構造に整理。
- [ ] `new/at/set/mul_naive` などのメソッド本体を Ring1 numeric core 関数(通常の Hako 関数)呼び出しに寄せる。
- [ ] Numeric ABI 関数群(`ny_numeric_intarray_*` / `ny_numeric_mat_i64_*`)を `.hako` で実装し、AOT 可能な状態にする。
### D. AotPrep / builder 経路
- [ ] `BoxCall(MatI64, ...)` / `BoxCall(IntArrayCore, ...)` を Ring1 numeric core 関数への通常 `Call` に変換する AotPrep パスを設計するPhase 25 では診断パスまで、実際の変換は後続フェーズ)。
- [ ] Box 型ID / メソッド名から numeric core 関数 ID にマップする表(メタ)を用意(対処療法的な文字列 if の乱立を避ける)。
- [ ] 変換後の MIR から `BoxCall` が LLVM ラインには残らないことを確認。
- [ ] imports / using 経路Phase 21.8 で導入済みを再確認し、MatI64/IntArrayCore の静的参照が安定して解決されることを確認。
### E. stdlib ビルド/ロード
- [ ] `lang/src/runtime/numeric/*.hako` を含む Ring1 モジュールを AOT して `stdlib.hbc`(仮)にまとめるビルドスクリプト(設計どおりなら `tools/hakc_stdlib.sh` 相当)を用意する。
- [ ] `hakorune` / `nyash` 起動時に `stdlib.hbc` をロードする導線を設計し、Ring0 に最小限のフックを追加する。
- [ ] VM/LLVM 両ラインで numeric runtime が利用できるかを確認する(どちらも BoxCall→Call(numeric core) の同一 MIR を実行する)。
### F. 検証・移行
- [ ] 代表的な数値ベンチ(`matmul_core` など)を:
- [ ] VM ラインBoxCall 経路)で確認。
- [ ] LLVM ラインnumeric ABI 経路)で確認。
- [ ] 21.x の既存ベンチが regression していないことを確認する(数値系以外は挙動不変)。
- [ ] Rust 側の IntArrayCore plugin 実装を「縮退 or optional 化」するタイミングと手順を docs に追記する。
## アウト・オブ・スコープPhase 25
- 実際のコード移行Rust 実装の削除や .hako への完全移植)は、このフェーズでは行わない。
@ -106,4 +314,3 @@ Phase 25 は「設計とロードマップの確定」が主目的。実装・
- Rust / Hakorune の責務分離が文書として明確になり、「新しい箱・数値カーネルは .hako で書く」がプロジェクトの合意として固定されている。
- IntArrayCore / MatI64 の「Rust→Hakorune 移行」手順が、段階ごとのタスクリストとして整理されている。
- System Hakorune サブセットと stdlib ビルド/ロード戦略のたたき台があり、後続フェーズ(例: Phase 22.x / 26.xでそのまま実装に着手できる状態になっている。