Files
hakorune/lang/src/runtime/numeric/README.md
nyash-codex 864a94d013 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>
2025-11-14 20:19:00 +09:00

7.2 KiB
Raw Blame History

lang/src/runtime/numeric — Ring1 Numeric Runtime

Scope: Phase 21.6+ / 21.8 / 25 で導入する 数値コア箱numeric core boxes を配置するディレクトリ。

目的

  • ArrayBox/MapBox などの汎用箱とは別に、数値・行列・ビルダ系の「C 相当コア」を Ring1Hakorune側で実装する。
  • 将来的には、このディレクトリ配下の .hako を AOT して stdlib 相当の成果物にまとめ、VM 起動時にロードするPhase 25 以降)。

代表モジュール

  • intarray_core_box.hako
    • 数値一次元配列コアIntArrayCoreの Box ラッパ。
    • Phase 21.6: Rust プラグイン IntArrayCore に委譲。
    • Phase 25: .hako 実装に移行し、Ring0 は alloc/free/load/store などの intrinsic のみ提供する方針。
  • mat_i64_box.hako
    • 行列箱 MatI64i64 行列)の Box 実装。
    • Phase 21.6/21.8: IntArrayCore に委譲する naive 実装。
    • Phase 25: numeric ABIny_numeric_mat_i64_*の薄ラッパとして整理し、VM / LLVM ともに「BoxCall → numeric core 関数への Call」という同じ MIR を実行する形を目指すnumeric 専用の ExternCall 境界は増やさない)。
    • 現状: 数値核 mul_naive の本体は NyNumericMatI64.mul_naive に分離し、MatI64.mul_naive はその薄ラッパとして実装。

Phase 25 との関係

  • Phase 25 では:
    • IntArrayCore / MatI64 の本体ロジックを .hako 側に移し、Rust 側は最小の numeric intrinsic と LLVM/OS FFI だけを持つ Ring0 とする。
    • AotPrep / builder で BoxCall(MatI64, ...) / BoxCall(IntArrayCore, ...)numeric core 関数への通常 Call に変換する設計を導入するBoxCall を LLVM まで持ち込まない)。
  • このディレクトリはそのための Ring1 numeric runtime の定位置として扱う。
    • 本番やベンチでは、AOT 済み stdlib例: stdlib.hbc)から nyash.core.numeric.* モジュールをロードする embedded モードを使用。
    • 開発時には、NYASH_STDLIB_MODE=source(候補)などで埋め込み stdlib を無効化し、このディレクトリ配下の .hako を直接コンパイルして挙動を確認する運用を想定。

IntArrayCore Box API設計メモ

実装ファイル: lang/src/runtime/numeric/intarray_core_box.hako

フィールド設計

  • handle: i64
    • NyRT/Rust 側で管理される IntArrayCore インスタンスへのハンドル。
    • 現行実装では nyash.intarray.* C シンボル経由で操作されるPhase 25 以降で numeric ABI に移行予定)。
  • len: i64
    • 配列長(要素数)。new(len) 時の引数と一致する前提。
    • 変更不可(再割り当てや resize は想定しない)。

メソッド仕様Box レベル)

  • static new(len: i64) -> IntArrayCore

    • 役割: 長さ len の 0 初期化配列を作成する。
    • 事前条件:
      • len >= 0 を前提とする(負値はバグ扱い; FailFast 寄りのポリシーで扱う)。
    • 実装メモ:
      • 現行: externcall "nyash.intarray.new_h"(len) を呼び、返ってきたハンドルを handle に格納。
      • 将来: numeric ABIny_numeric_intarray_new 等)経由で Core を構築し、Handle/Core の表現を段階的に置き換える。
  • length() -> i64

    • 役割: 現在の要素数を返す。
    • 期待挙動:
      • 通常は len と同値。
      • Core 側の情報と不整合が生じないよう、Phase 25 以降は「単一の SSOTCore 側)」に寄せる設計を検討する。
  • get_unchecked(idx: i64) -> i64

    • 役割: インデックス idx から値を取得する。
    • 事前条件:
      • 0 <= idx < length() を呼び出し側が保証するunchecked の名の通り)。
    • エラー処理:
      • Phase 21.x 実装では、範囲外アクセス時に 0 を返すなどの挙動が残っているため、Phase 25 では「FailFastバグを隠さない」方向に整理する。
    • 用途:
      • MatI64 や numeric カーネル内部でのループ本体から使用する前提System Hakorune subset 内)。
  • set_unchecked(idx: i64, v: i64) -> null

    • 役割: インデックス idx に値 v を書き込む。
    • 事前条件:
      • 0 <= idx < length() を呼び出し側が保証する。
    • エラー処理:
      • Phase 21.x 実装では戻り値でエラーコードを返す形跡があるが、Phase 25 では FailFast で統一し、Box レベルでは成功/失敗を返さない設計を目指す。

MatI64 Box API設計メモ

実装ファイル: lang/src/runtime/numeric/mat_i64_box.hako

フィールド設計

  • rows: i64
    • 行数row countrows >= 0 を前提。
  • cols: i64
    • 列数column countcols >= 0 を前提。
  • stride: i64
    • 1 行あたりのステップ幅。現行実装では cols と同一rowmajor の連続配置)。
    • 将来、ビューやサブ行列を導入する場合に stride != cols を許容する余地を残す。
  • core: IntArrayCore
    • 実データを保持する一次元配列コア(長さは rows * cols を前提)。

メソッド仕様Box レベル)

  • static new(rows: i64, cols: i64) -> MatI64

    • 役割: rows x cols のゼロ初期化行列を作成する。
    • 事前条件:
      • rows >= 0, cols >= 0
      • rows * cols が i64 の範囲内に収まること(オーバーフロー時は FailFast 寄りに扱う)。
    • 実装メモ:
      • IntArrayCore.new(rows * cols) を呼び出し、stride = cols として初期化。
  • rowsCount() -> i64

    • 役割: 行数を返す(読み取り専用)。
  • colsCount() -> i64

    • 役割: 列数を返す。
  • at(r: i64, c: i64) -> i64

    • 役割: 要素 (r, c) を読み取る。
    • 事前条件:
      • 0 <= r < rows, 0 <= c < cols を呼び出し側が保証。
    • 実装メモ:
      • idx = r * stride + c を計算し、core.get_unchecked(idx) を呼ぶ。
    • 将来:
      • デバッグ/strict モードでは範囲チェックを追加するオプションを検討prod ではループ性能優先)。
  • set(r: i64, c: i64, v: i64) -> null

    • 役割: 要素 (r, c)v を書き込む。
    • 事前条件:
      • 0 <= r < rows, 0 <= c < cols
    • 実装メモ:
      • idx = r * stride + c を計算し、core.set_unchecked(idx, v) を呼ぶ。
  • mul_naive(b: MatI64) -> MatI64

    • 役割: me * b のナイーブな O(n³) 行列積を計算する。
    • 事前条件:
      • 現行スケルトンでは「正方行列かつ形状一致」を暗黙前提としているPhase 25 で明示条件に格上げする)。
      • 最低限 me.cols == b.rows を事前条件とし、満たさない場合は FailFast とする方向。
    • 実装メモ:
      • 三重ループ (i,k,j) で out[i,j] += me[i,k] * b[k,j] を計算。
      • out 行列は MatI64.new(me.rows, b.cols) で確保。
    • Phase 25 以降:
      • Box メソッドとしての mul_naive は numeric ABI の薄ラッパに縮退し、ループ本体は System Hakorune subset 上の別関数(ny_numeric_mat_i64_mul_naive)に切り出す。