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

@ -75,6 +75,11 @@ NYASH_DISABLE_PLUGINS = "1"
- NYASH_AOT_OBJECT_OUT: AOT パイプラインで使用する `.o` 出力ディレクトリ/パス
- NYASH_LLVM_USE_HARNESS: "1" で llvmlite ハーネス経路を有効化MIR(JSON)→Python→.ll→llc→.o
## AotPrep / Numeric CorePhase 25 実験用)
- NYASH_AOT_COLLECTIONS_HOT: Array/Map boxcall を externcall に書き換えるホットパスCollectionsHot パスを有効化)
- NYASH_AOT_NUMERIC_CORE: 数値系 BoxCallMatI64 / IntArrayCore 等)の診断パスを有効化(`AotPrepNumericCoreBox`)。現状はログ出力のみで MIR は変更しない(将来の BoxCall→Call 降ろし用の足場)。
- NYASH_AOT_NUMERIC_CORE_TRACE: 上記 numeric core パスの詳細トレース("1" で `mul_naive/at/set` など候補 BoxCall を stderr にログ出力)
### LLVM Feature 詳細
- **llvm** (デフォルト): llvmlite Python ハーネス使用、LLVM_SYS_180_PREFIX不要
- **llvm-inkwell-legacy**: Rust inkwell bindings使用、LLVM_SYS_180_PREFIX必要

View File

@ -0,0 +1,147 @@
# Numeric ABI (IntArrayCore / MatI64) — Design Stage
Status: design-stage; Phase 25 scope; no behaviour change yet.
## Purpose
- Define a minimal, stable **numeric ABI** for IntArrayCore / MatI64 that:
- 実装としては Ring1 Hakorune の通常関数(`Call`)として表現でき、
- 必要に応じて Ring0 Rust / C 側からも同じシグネチャで呼び出せる(将来の FFI/ExternCall 連携の基礎になる)。
- Keep **all box-specific knowledge in Ring1**:
- Box/Handle/Core の構造ptr/len/rows/cols/stride 等)。
- 行列積などの数値アルゴリズム本体。
- 境界チェックと FailFast ポリシー。
- Allow Ring0/LLVM to treat numeric calls as:
- 通常の関数呼び出し(`Call @ny_numeric_*`)として扱えるようにし、
- 必要な場合のみ、既存の `ExternCall`/FFI 構造の上に同じ関数群を載せ替えられるようにするPhase 25 では必須ではない)。
Related docs:
- Phase 25 roadmap: `docs/development/roadmap/phases/phase-25/README.md`
- Ring1 numeric runtime layout: `lang/src/runtime/numeric/README.md`
- System Hakorune subset (runtime/numeric 用記法): `docs/development/runtime/system-hakorune-subset.md`
## Conventions
- **Types / encoding**
- Numeric ABI 関数のシグネチャは **i64 と Handle実体は i64×N** のみを使う。
- `IntArrayHandle` / `MatI64Handle` は「i64×N の値」として表現される:
- C 側イメージ(概念):
- `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 では「複数の i64 をまとめた値」として `Call` の引数/戻り値に現れる。
- **命名**
- Ring1/Hakorune 側では、`ny_numeric_intarray_*` / `ny_numeric_mat_i64_*` 系の関数名(またはそれに相当するモジュール+メソッド名)で実装する。
- C/Rust 側から直接呼びたい場合は、同じ名前でシンボルをエクスポートする(必要になったタイミングで ExternCall に載せ替え可能)。
- **FailFast**
- numeric ABI では、事前条件違反(負の長さ、境界外 index、dims 不整合)は **すべてバグ扱い** とし、FailFast で扱う。
- 「エラーコードを返して上層で if」するスタイルは禁止AGENTS.md の対処療法禁止に準拠)。
## ABI Surface — IntArrayCore (i64 1D)
Conceptual handle:
- `IntArrayHandle`: 実体は「`ptr: i64` + `len: i64`」等で構成される Core 構造体を指す値。
- Box レベル仕様は `lang/src/runtime/numeric/README.md` の IntArrayCore セクションを参照。
Functions (proposal; Phase 25 scope):
- `ny_numeric_intarray_new(len: i64) -> IntArrayHandle`
- Allocate zero-initialized buffer of length `len`.
- Preconditions:
- `len >= 0`
- `len` が i64 範囲内であり、`len * sizeof(i64)` の計算がオーバーフローしない。
- Failure:
- OOM / 明らかな誤りは FailFast戻り値でのエラー表現は行わない
- `ny_numeric_intarray_free(a: IntArrayHandle)`
- Free underlying Core.
- Double-free / invalid handle は未定義動作とし、所有権設計Ring1 側)で防ぐ。
- `ny_numeric_intarray_len(a: IntArrayHandle) -> i64`
- Return current logical length.
- Used mainly for assertions / diagnostics;通常は Box 側で長さを保持しない方向に寄せる。
- `ny_numeric_intarray_get(a: IntArrayHandle, idx: i64) -> i64`
- Load `a[idx]`.
- Preconditions:
- `0 <= idx < len(a)`.
- Failure:
- Precondition violated → FailFast例外 or プロセス終了; 実際の実装は後続フェーズで決定)。
- `ny_numeric_intarray_set(a: IntArrayHandle, idx: i64, v: i64)`
- Store `v` into `a[idx]`.
- Preconditions:
- `0 <= idx < len(a)`.
- Failure:
- Precondition violated → FailFast。
Mapping to MIRPhase 25 の基本方針):
- BoxCall: `BoxCall(IntArrayCore, "get_unchecked", [arr, idx])`
- AotPrep: 数値コア関数への通常 `Call` に書き換え(例: `Call NyNumericIntArray.get(arr_handle, idx)`)。
- LLVM/VM: どちらも同じ `Call` を実行するだけで numeric ABI に到達する。
## ABI Surface — MatI64 (i64 2D matrix)
Conceptual handle:
- `MatI64Handle`: 「`ptr`, `rows`, `cols`, `stride`」を持つ Core 構造を指す値。
- Box レベル仕様は `lang/src/runtime/numeric/README.md` の MatI64 セクションを参照。
Functions (proposal; Phase 25 scope):
- `ny_numeric_mat_i64_new(rows: i64, cols: i64) -> MatI64Handle`
- Allocate zero-initialized `rows x cols` matrix, rowmajor。
- Preconditions:
- `rows >= 0`, `cols >= 0`.
- `rows * cols` が i64 範囲内であり、`rows * cols * sizeof(i64)` がオーバーフローしない。
- `ny_numeric_mat_i64_free(m: MatI64Handle)`
- Free underlying matrix Core所有権は Box 側で管理)。
- `ny_numeric_mat_i64_dims(m: MatI64Handle) -> (rows: i64, cols: i64)`
- Return matrix dimensions行数・列数
- `ny_numeric_mat_i64_get(m: MatI64Handle, row: i64, col: i64) -> i64`
- Load element at `(row, col)`.
- Preconditions:
- `0 <= row < rows(m)`, `0 <= col < cols(m)`.
- `ny_numeric_mat_i64_set(m: MatI64Handle, row: i64, col: i64, v: i64)`
- Store `v` into `(row, col)`.
- Preconditions:
- 同上。
- `ny_numeric_mat_i64_mul_naive(a: MatI64Handle, b: MatI64Handle, n: i64) -> MatI64Handle`
- Naive O(n³) matrix multiplication for `n x n` matrices.
- Preconditions:
- `rows(a) == cols(a) == rows(b) == cols(b) == n`.
- `n >= 0`
- Failure:
- 上記条件を満たさない場合は FailFast。ベンチマークバグを隠さない。
Mapping to MIRPhase 25 の基本方針):
- BoxCall: `BoxCall(MatI64, "mul_naive", [a, b])`
- AotPrep: `Call NyNumericMatI64.mul_naive(a_handle, b_handle, n)` のような numeric core 関数呼び出しに書き換え。
- LLVM/VM: どちらも同じ `Call` を実行するだけで numeric ABI に到達する。
## BoxCall / Call / ExternCall の役割分担
- Initial MIR:
- `BoxCall(MatI64, "new", [rows, cols])`
- `BoxCall(MatI64, "mul_naive", [a, b])`
- AotPrep (Ring1):
- これらを numeric core 関数への `Call` に変換するBoxCall を LLVM まで持ち込まない)。
- Box 名やメソッド名ベースの一時的 if ではなく、「Box 型ID + メソッドID → numeric core 関数 ID」テーブル化を目指す。
- Ring0 / LLVM:
- `Call @ny_numeric_*` を普通の関数呼び出しとして扱う。
- 低レベルのメモリアクセスや OS 連携が必要な場合のみ、既存の `ExternCall`(例: `rt_mem_alloc_i64`を使う。numeric ABI 自体は必須では ExternCall に依存しない。
## Relation to other docs
- Phase 25 roadmap:
- Numeric ABI の設計方針Ring0/Ring1 分離、Call/ExternCall のみ、FailFastを高レベルで説明。
- このファイルは、そのうち IntArrayCore / MatI64 に関わる ABI 面のみを詳細化する。
- `lang/src/runtime/numeric/README.md`:
- IntArrayCore / MatI64 の **Box レベル API**(フィールド・メソッド契約)を定義。
- Numeric ABI はその下で動く「Core/Handle レベル」の境界として扱う。
- `docs/development/runtime/system-hakorune-subset.md`:
- Numeric ABI の実装を記述する際に使う Hakorune 言語機能の subset を規定。
- ループ/FailFast/Box/Handle パターンなど、実装スタイルを制約する。

View File

@ -0,0 +1,87 @@
# System Hakorune Subset — Runtime / Numeric Core Design
Status: design-stage; subset definition only. No behavior change yet.
## Purpose
- Provide a small, predictable subset of Hakorune for implementing **runtime / numeric core logic** in Ring1IntArrayCore, MatI64, stats, policy, etc.)。
- Make this subset explicit so that:
- Box / numeric kernels can be moved from Rust to `.hako` **without increasing semantic complexity**.
- AotPrep / VM / LLVM can rely on a restricted feature set when reasoning about these modules.
- Align with Phase 25 goals:
- Ring0Rustは intrinsic と最小 VM/FFI のみ。
- Ring1Hakoruneは「元・C 相当の実装」をこの subset で記述する。
Related docs:
- Phase 25 roadmap: `docs/development/roadmap/phases/phase-25/README.md`
- Ring1 numeric runtime layout: `lang/src/runtime/numeric/README.md`
- Numeric ABI surface (IntArrayCore / MatI64): `docs/development/runtime/NUMERIC_ABI.md`
## Scope & Typical Use
- 対象モジュールの例:
- `nyash.core.numeric.intarray`IntArrayCore 本体)
- `nyash.core.numeric.matrix_i64`MatI64 本体)
- 将来の数値箱(例: F64ArrayCore, MatF64 など)
- ランタイムポリシー / stats / 軽量な AotPrep 補助ロジック
- 非対象(ここでは扱わないもの):
- 高レベルアプリケーションロジックUI、CLI コマンド等)。
- 重い I/O / ネットワーク / プラグイン動的ロード。
- 実験的な言語機能例外、async 等)を前提とするコード。
## Allowed Features推奨
- 制御構造:
- `if / else``while`、インデックス付きの従来型 `for` ループ。
- ネストは OK だが、循環依存や過度な再帰は避ける。
- データ構造:
- Box フィールドを明示した構造体的なパターン(`handle.ptr`, `handle.len` 等)。
- 固定長 or 単純な一次元/二次元配列アクセスIntArrayCore / MatI64
- 関数:
- 引数/戻り値が `i64` と Box/Handle 型に限定された関数。
- 純粋 or 副作用が局所(配列/行列への書き込み)のみの関数。
- エラーハンドリング:
- **FailFast** を前提とした設計(事前条件違反は即失敗)。
- 戻り値でのエラーコード運搬は禁止AGENTS.md の対処療法禁止と合わせる)。
## Restricted / Forbidden Features
- 例外 / 非同期:
- `throw/try` や async 相当の機能は numeric core の実装では使わない方針(後続フェーズで必要になった場合に個別に設計)。
- 動的ディスパッチ:
- 文字列ベースの `by-name` ディスパッチ(`if method == "mul"` 等)は避け、事前に決まった numeric ABI 関数を直接呼び出す。
- 動的ロード / プラグイン依存:
- numeric core から直接プラグインをロードしない。必要なら上位層(アプリ側)がプラグイン経由で呼ぶ。
- 型拡張:
- 汎用的な「任意型の配列/行列」をここで扱わない。Phase 25 では **i64 専用IntArrayCore / MatI64** にスコープを絞る。
## Design Patterns & Guidelines
- 明示的ループ:
- 数値カーネルは map/filter 的な高階関数ではなく、`for` / `while` による明示ループで書く。
- これにより AotPrep / LLVM でのループ変換・アンローリング等の解析がしやすくなる。
- Box / Handle の役割分離:
- Box例: `MatI64`)は **API と所有権** を管理する層。
- Handle/Core例: `IntArrayCore`, `MatI64Core`)は **実データとループ本体** を持つ層。
- Box メソッドは「引数検査 → numeric ABI 呼び出し」の薄いラッパに留める。
- FailFast:
- インデックスや次元の検査は、「バグを隠さない」方向で実装する。
- `idx < 0``idx >= len` など明らかなバグは例外 or プロセス終了で即座に検出し、フォールバックや silent failure は行わない。
## Relation to Ring0 / Numeric ABI
- Ring0Rust:
- IntArrayCore / MatI64 向けには「ptr/len/rows/cols/stride を受け取る intrinsic」だけを提供する。
- ループ本体や境界チェックは実装しないSystem Hakorune subset 側に責務を寄せる)。
- Ring1Hakorune:
- この subset 上で numeric ABI 関数群(`ny_numeric_intarray_*`, `ny_numeric_mat_i64_*`)を実装する。
- AotPrep は BoxCall → numeric ABI への `ExternCall` 変換を行い、LLVM 側は汎用 Call/ExternCall として扱うだけでよい。
## RoadmapPhase 25 以降)
- Phase 25:
- Subset の定義を docs として固定(このファイル)。
- IntArrayCore / MatI64 の API 仕様と合わせて、どの機能を subset に含めるかを明示する。
- 後続フェーズ22.x / 26.x など):
- 実際の `.hako` 実装を subset 遵守で書き起こす。
- AotPrep / VM / LLVM の観点から「subset で書かれた numeric core を前提にした最適化/診断」を設計する。