Phase 12: 統一TypeBox ABI実装開始 - ChatGPT5による極小コアABI基盤構築
- TypeBox ABI雛形: メソッドスロット管理システム追加 - Type Registry: Array/Map/StringBoxの基本メソッド定義 - Host API: C ABI逆呼び出しシステム実装 - Phase 12ドキュメント整理: 設計文書統合・アーカイブ化 - MIR Builder: クリーンアップと分離実装完了 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -0,0 +1,277 @@
|
||||
# C ABI TypeBox 設計仕様書 v2.0 (2025-09-01)
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
**重要な設計変更**: 複雑なFactory設計から、極限までシンプルなTypeBoxアプローチへ移行しました。
|
||||
|
||||
TypeBoxは、C ABIプラグイン間でBox型情報を受け渡すための最小限の仕組みです。「Everything is Box」の哲学に従い、型情報すらBoxとして扱います。
|
||||
|
||||
### 解決する問題
|
||||
1. **相互依存問題**: C ABIプラグインは他プラグインのヘッダーを直接参照できない
|
||||
2. **循環依存**: MapBox→ArrayBox→StringBoxのような依存関係
|
||||
3. **ABI境界**: 異なるコンパイラ/バージョンでビルドされたプラグイン間の互換性
|
||||
4. **シンプルさ**: MIR層への影響を最小限に抑える
|
||||
|
||||
## 📐 基本設計:TypeBoxアプローチ
|
||||
|
||||
### TypeBox構造体(極限までシンプル)
|
||||
|
||||
```c
|
||||
// nyrt_typebox.h - すべてのプラグインが共有する最小限のヘッダ
|
||||
typedef struct NyrtTypeBox {
|
||||
uint32_t abi_tag; // 'TYBX' (0x58425954) マジックナンバー
|
||||
const char* name; // "ArrayBox", "StringBox" など
|
||||
void* (*create)(void); // Box生成関数(引数なし版)
|
||||
} NyrtTypeBox;
|
||||
|
||||
// オプション:コンテキスト付き版(将来拡張用)
|
||||
typedef struct NyrtTypeBoxV2 {
|
||||
uint32_t abi_tag; // 'TYB2' (0x32425954)
|
||||
uint16_t abi_major; // 1
|
||||
uint16_t abi_minor; // 0
|
||||
const char* name; // 型名
|
||||
void* (*create)(void* context); // コンテキスト付き生成
|
||||
uint32_t size; // sizeof(NyrtTypeBoxV2)
|
||||
} NyrtTypeBoxV2;
|
||||
```
|
||||
|
||||
### 設計原則
|
||||
|
||||
1. **静的メタデータ**: TypeBoxは不変の型情報(参照カウント不要)
|
||||
2. **引数として渡す**: 明示的な依存関係を保つ
|
||||
3. **グローバル変数なし**: すべて引数経由で受け渡し
|
||||
4. **ファクトリーなし**: 直接関数ポインタを呼ぶシンプルさ
|
||||
|
||||
### Rust側実装(ランタイム)
|
||||
|
||||
```rust
|
||||
// src/runtime/type_boxes.rs
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NyrtTypeBox {
|
||||
pub abi_tag: u32,
|
||||
pub name: *const std::os::raw::c_char,
|
||||
pub create: extern "C" fn() -> *mut c_void,
|
||||
}
|
||||
|
||||
// ArrayBox用の静的TypeBox定義
|
||||
#[no_mangle]
|
||||
pub static ARRAY_TYPE_BOX: NyrtTypeBox = NyrtTypeBox {
|
||||
abi_tag: 0x58425954, // 'TYBX'
|
||||
name: b"ArrayBox\0".as_ptr() as *const _,
|
||||
create: create_array_box_impl,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn create_array_box_impl() -> *mut c_void {
|
||||
// ArrayBoxインスタンスを作成
|
||||
let array = ArrayBox::new();
|
||||
let boxed = Box::new(array);
|
||||
Box::into_raw(boxed) as *mut c_void
|
||||
}
|
||||
|
||||
// オプション:型検証ヘルパー
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyrt_validate_typebox(tb: *const NyrtTypeBox) -> bool {
|
||||
if tb.is_null() { return false; }
|
||||
unsafe {
|
||||
(*tb).abi_tag == 0x58425954
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 プラグイン側実装例
|
||||
|
||||
### MapBoxプラグイン(keys()実装)
|
||||
|
||||
```c
|
||||
// plugins/map/map_box.c
|
||||
#include "nyrt_typebox.h"
|
||||
|
||||
// MapBox.keys()の実装 - TypeBoxを引数で受け取る
|
||||
void* map_keys(void* self, void* array_type_box) {
|
||||
MapBox* map = (MapBox*)self;
|
||||
NyrtTypeBox* array_type = (NyrtTypeBox*)array_type_box;
|
||||
|
||||
// 最小限の検証
|
||||
if (!array_type || array_type->abi_tag != 0x58425954) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ArrayBoxを作成(直接関数ポインタを呼ぶ)
|
||||
void* array = array_type->create();
|
||||
if (!array) return NULL;
|
||||
|
||||
// キーをArrayBoxに追加
|
||||
// 注:ArrayBoxのpushメソッドは別途C API経由で呼ぶ必要あり
|
||||
for (size_t i = 0; i < map->size; i++) {
|
||||
// ArrayBox固有のAPIを使用(プラグイン間の取り決め)
|
||||
// array_push(array, map->entries[i].key);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
// 呼び出し側の例
|
||||
void example_usage(void* map) {
|
||||
// ランタイムから型情報を取得(または静的に保持)
|
||||
extern NyrtTypeBox ARRAY_TYPE_BOX; // ランタイムが提供
|
||||
|
||||
void* keys = map_keys(map, &ARRAY_TYPE_BOX);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 なぜTypeBoxアプローチが優れているか
|
||||
|
||||
### 専門家による分析結果
|
||||
|
||||
GeminiとCodexによる深い技術分析の結果、以下の結論に至りました:
|
||||
|
||||
1. **極限のシンプルさ**
|
||||
- 構造体1つ、関数ポインタ1つ
|
||||
- C言語の基本機能のみ使用
|
||||
- 特別なライブラリ不要
|
||||
|
||||
2. **明示的な依存関係**
|
||||
- TypeBoxを引数で渡すことで依存が明確
|
||||
- グローバル状態なし
|
||||
- テスト容易性の向上
|
||||
|
||||
3. **MIR層への影響最小**
|
||||
- 型情報を単なる値として扱う
|
||||
- 新しいディスパッチルール不要
|
||||
- 既存の仕組みで実現可能
|
||||
|
||||
4. **拡張性**
|
||||
- 構造体の末尾に新フィールド追加可能
|
||||
- バージョニングによる互換性維持
|
||||
- 将来の要求に対応可能
|
||||
|
||||
### 代替案の比較
|
||||
|
||||
| アプローチ | 複雑さ | MIR影響 | 保守性 |
|
||||
|-----------|--------|---------|--------|
|
||||
| TypeBox(採用) | ★☆☆☆☆ | 最小 | 優秀 |
|
||||
| Factory Pattern | ★★★★☆ | 中 | 困難 |
|
||||
| COM/JNI風 | ★★★★★ | 大 | 複雑 |
|
||||
| サービスレジストリ | ★★★☆☆ | 中 | 良好 |
|
||||
|
||||
## 💾 メモリ管理とセキュリティ
|
||||
|
||||
### TypeBoxのライフサイクル
|
||||
|
||||
```c
|
||||
// TypeBoxは静的メタデータ(参照カウント不要)
|
||||
// ランタイムが提供する不変のデータとして扱う
|
||||
extern const NyrtTypeBox ARRAY_TYPE_BOX; // 'static lifetime
|
||||
extern const NyrtTypeBox STRING_TYPE_BOX; // 'static lifetime
|
||||
|
||||
// 生成されたBoxインスタンスは通常通り参照カウント管理
|
||||
void* array = array_type->create();
|
||||
// 使用...
|
||||
nyrt_release(array); // 既存の参照カウントAPI
|
||||
```
|
||||
|
||||
### セキュリティ考慮事項
|
||||
|
||||
```c
|
||||
// 最小限の検証で安全性を確保
|
||||
bool is_valid_typebox(const NyrtTypeBox* tb) {
|
||||
return tb != NULL &&
|
||||
tb->abi_tag == 0x58425954 && // 'TYBX'
|
||||
tb->name != NULL &&
|
||||
tb->create != NULL;
|
||||
}
|
||||
|
||||
// 使用例
|
||||
if (!is_valid_typebox(array_type)) {
|
||||
return NULL; // 不正なTypeBoxを拒否
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 実装ロードマップ
|
||||
|
||||
### Phase 1: TypeBox基本実装(3日)
|
||||
- [ ] nyrt_typebox.h定義
|
||||
- [ ] 基本型(Array/String/Map)のTypeBox定義
|
||||
- [ ] 検証関数の実装
|
||||
|
||||
### Phase 2: プラグイン統合(1週間)
|
||||
- [ ] MapBox.keys()のTypeBox対応
|
||||
- [ ] ArrayBox APIの整備
|
||||
- [ ] サンプル実装
|
||||
|
||||
### Phase 3: 完全移行(1週間)
|
||||
- [ ] 全プラグインのTypeBox対応
|
||||
- [ ] ドキュメント更新
|
||||
- [ ] テストスイート
|
||||
|
||||
## 📊 パフォーマンス分析
|
||||
|
||||
### TypeBoxアプローチのオーバーヘッド
|
||||
```
|
||||
直接生成: ~50ns
|
||||
TypeBox経由: ~60ns(関数ポインタ1回)
|
||||
→ ほぼ無視できるレベル
|
||||
```
|
||||
|
||||
### メモリ効率
|
||||
```
|
||||
TypeBox構造体: 24bytes(最小構成)
|
||||
グローバル変数: 0(すべて引数渡し)
|
||||
→ 極めて効率的
|
||||
```
|
||||
|
||||
## 🎯 実装例:MapBox.keys()の完全な実装
|
||||
|
||||
```c
|
||||
// map_box.c
|
||||
void* map_keys(void* self, void* array_type_box, void* string_type_box) {
|
||||
MapBox* map = (MapBox*)self;
|
||||
NyrtTypeBox* array_type = (NyrtTypeBox*)array_type_box;
|
||||
NyrtTypeBox* string_type = (NyrtTypeBox*)string_type_box;
|
||||
|
||||
// TypeBox検証
|
||||
if (!is_valid_typebox(array_type) || !is_valid_typebox(string_type)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ArrayBox作成
|
||||
void* array = array_type->create();
|
||||
if (!array) return NULL;
|
||||
|
||||
// 各キーをStringBoxとして追加
|
||||
for (size_t i = 0; i < map->size; i++) {
|
||||
// 注:実際の実装では、ArrayBoxのpush APIを
|
||||
// 別途定義された方法で呼び出す必要があります
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 まとめ:なぜTypeBoxが最適解なのか
|
||||
|
||||
### Geminiの結論
|
||||
> 「ご提案のTypeBoxアプローチは、NyashのC ABIにおけるBox生成ファクトリの設計として、これ以上ないほどシンプルかつ強力なものです。」
|
||||
|
||||
### Codexの結論
|
||||
> 「Keep the concept, refine it: the TypeBox pointer is the sweet spot — explicit, cheap, zero global cache thrash, and one function pointer."
|
||||
|
||||
### 設計の核心
|
||||
- **Everything is Box**: 型情報すらBoxとして扱う
|
||||
- **極限のシンプルさ**: 構造体1つ、関数ポインタ1つ
|
||||
- **明示的な依存**: すべて引数で渡す
|
||||
|
||||
## 🎯 成功指標
|
||||
|
||||
1. **機能性**: MapBox.keys()のようなクロスプラグインBox生成が動作
|
||||
2. **パフォーマンス**: 直接生成比1.2倍以内のオーバーヘッド(実測値)
|
||||
3. **シンプルさ**: 20行以内のコードで実装可能
|
||||
4. **保守性**: MIR層の変更不要
|
||||
|
||||
---
|
||||
|
||||
*「Everything is Box - 型情報すらBoxとして扱う」- TypeBoxアプローチ*
|
||||
@ -0,0 +1,13 @@
|
||||
# Nyash ABI 概要(統合ABIダイジェスト)
|
||||
|
||||
本ドキュメントは `UNIFIED-ABI-DESIGN.md` の要約です。詳細は統合仕様を参照してください。
|
||||
|
||||
- 目的: C ABI を維持しつつ、NyashValue(3×u64相当)でのゼロコピー呼び出しを段階導入
|
||||
- TypeBox: FQN/stable_id/vtable(C/Nyash) を束ねるディスクリプタ
|
||||
- 所有権: BORROW/TRANSFER/CLONE を明示(release責務の所在を固定)
|
||||
- 例外: C ABIはnothrow。越境例外は nyrt_err へ変換
|
||||
- ディスパッチ: Nyash vtable優先→C vtable/TLVフォールバック(VM/JIT共通)
|
||||
- 導入順序: TypeBoxレジストリ→統一ディスパッチ→Nyash ABI サンプル→最適化
|
||||
|
||||
このフェーズの実装タスクは [TASKS.md](./TASKS.md) を参照。
|
||||
|
||||
@ -0,0 +1,191 @@
|
||||
# C ABI プラグインシステム
|
||||
|
||||
## 📦 概要
|
||||
|
||||
C ABIは、Nyashの**基本プラグインシステム**です。C言語の標準的な関数呼び出し規約を使用し、高速かつ軽量な実装を提供します。
|
||||
|
||||
## 🎯 特徴
|
||||
|
||||
### シンプルさ
|
||||
- **たった3つの関数**で完全なプラグインが作れる
|
||||
- 複雑な型システムや継承は不要
|
||||
- C言語の知識があれば誰でも書ける
|
||||
|
||||
### 高速性
|
||||
- 直接的な関数ポインタ呼び出し
|
||||
- オーバーヘッドがほぼゼロ
|
||||
- JITコンパイラとの相性も抜群
|
||||
|
||||
### 安定性
|
||||
- C ABIは数十年の実績がある標準規格
|
||||
- プラットフォーム間での互換性が高い
|
||||
- バージョン間の互換性も維持しやすい
|
||||
|
||||
## 📝 基本実装
|
||||
|
||||
### 1. 最小限のプラグイン(3つの関数)
|
||||
|
||||
```c
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// 1. create関数:Boxを作成
|
||||
void* string_create(const char* initial_value) {
|
||||
char* str = malloc(strlen(initial_value) + 1);
|
||||
strcpy(str, initial_value);
|
||||
return str;
|
||||
}
|
||||
|
||||
// 2. method関数:メソッドを実行
|
||||
void* string_method(void* self, const char* method_name, void** args, int arg_count) {
|
||||
char* str = (char*)self;
|
||||
|
||||
if (strcmp(method_name, "length") == 0) {
|
||||
int* result = malloc(sizeof(int));
|
||||
*result = strlen(str);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (strcmp(method_name, "toUpperCase") == 0) {
|
||||
char* upper = malloc(strlen(str) + 1);
|
||||
for (int i = 0; str[i]; i++) {
|
||||
upper[i] = toupper(str[i]);
|
||||
}
|
||||
upper[strlen(str)] = '\0';
|
||||
return upper;
|
||||
}
|
||||
|
||||
return NULL; // メソッドが見つからない
|
||||
}
|
||||
|
||||
// 3. destroy関数:メモリを解放
|
||||
void string_destroy(void* self) {
|
||||
free(self);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグイン設定(nyash.toml)
|
||||
|
||||
```toml
|
||||
[[plugins]]
|
||||
name = "StringBox"
|
||||
path = "./string_plugin.so"
|
||||
type = "c-abi"
|
||||
version = 1
|
||||
|
||||
# メソッドの戻り値型を指定
|
||||
[plugins.methods]
|
||||
length = { returns = "integer" }
|
||||
toUpperCase = { returns = "string" }
|
||||
```
|
||||
|
||||
## 🔧 TLV(Type-Length-Value)形式
|
||||
|
||||
### 構造化データのやり取り
|
||||
|
||||
C ABIでは、複雑なデータをTLV形式でやり取りします:
|
||||
|
||||
```c
|
||||
// TLVヘッダー
|
||||
typedef struct {
|
||||
uint8_t type; // 1=bool, 2=i64, 3=f64, 5=string, 6=handle
|
||||
uint32_t length; // データ長
|
||||
// この後にデータが続く
|
||||
} TLVHeader;
|
||||
|
||||
// 複数の値を返す例
|
||||
void* math_stats(void* self, const char* method_name, void** args, int arg_count) {
|
||||
if (strcmp(method_name, "calculate") == 0) {
|
||||
// 3つの値を返す: [min, max, average]
|
||||
size_t total_size = sizeof(TLVHeader) * 3 + sizeof(double) * 3;
|
||||
uint8_t* buffer = malloc(total_size);
|
||||
uint8_t* ptr = buffer;
|
||||
|
||||
// min値
|
||||
TLVHeader* hdr1 = (TLVHeader*)ptr;
|
||||
hdr1->type = 3; // f64
|
||||
hdr1->length = sizeof(double);
|
||||
ptr += sizeof(TLVHeader);
|
||||
*(double*)ptr = 1.0;
|
||||
ptr += sizeof(double);
|
||||
|
||||
// 以下同様にmax値、average値を追加...
|
||||
|
||||
return buffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 TypeBox:C ABIの拡張メカニズム
|
||||
|
||||
### C ABIの限界を超える
|
||||
|
||||
C ABIだけでは、プラグイン間でBoxを生成することができません。例えば、MapBoxがArrayBoxを返したい場合、MapBoxはArrayBoxの実装を知らないため直接作成できません。
|
||||
|
||||
この問題を解決するのが**TypeBox**です。
|
||||
|
||||
### TypeBoxとは?
|
||||
|
||||
TypeBoxは「**型情報をBoxとして扱う**」という概念です。型の生成方法をBoxとして渡すことで、プラグイン間の連携を可能にします。
|
||||
|
||||
```c
|
||||
// TypeBox構造体:型情報をBoxとして扱う
|
||||
typedef struct {
|
||||
uint32_t abi_tag; // 'TYBX' (0x54594258)
|
||||
const char* name; // "ArrayBox"
|
||||
void* (*create)(void); // Box生成関数
|
||||
} TypeBox;
|
||||
|
||||
// MapBox.keys()の実装 - ArrayBoxのTypeBoxを引数で受け取る
|
||||
void* map_keys(void* self, void* array_type_box) {
|
||||
MapBox* map = (MapBox*)self;
|
||||
TypeBox* array_type = (TypeBox*)array_type_box;
|
||||
|
||||
// 検証
|
||||
if (!array_type || array_type->abi_tag != 0x54594258) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ArrayBoxを生成(TypeBox経由)
|
||||
void* array = array_type->create();
|
||||
if (!array) return NULL;
|
||||
|
||||
// MapのキーをArrayに追加
|
||||
// (ArrayBoxのメソッドは別途C API経由で呼ぶ)
|
||||
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
### TypeBoxの利点
|
||||
|
||||
1. **プラグイン間の疎結合**: 直接的な依存関係なし
|
||||
2. **型安全性**: abi_tagによる検証
|
||||
3. **拡張可能**: 新しいBox型の追加が容易
|
||||
4. **シンプル**: 構造体1つ、関数ポインタ1つ
|
||||
|
||||
## 💡 いつC ABIを使うべきか?
|
||||
|
||||
### C ABIが最適な場合
|
||||
- ✅ **シンプルな機能**を追加したい
|
||||
- ✅ **高速性**が重要
|
||||
- ✅ **安定性**を重視する
|
||||
- ✅ 既存のC/C++ライブラリをラップしたい
|
||||
|
||||
### C ABIでは難しい場合
|
||||
- ❌ 複雑な継承関係が必要
|
||||
- ❌ 他言語(Python/Go等)との相互運用
|
||||
- ❌ 動的な型変換が頻繁に必要
|
||||
|
||||
これらの場合は、C ABI + TypeBoxをベースに構築された**Nyash ABI**を検討してください。
|
||||
|
||||
## 📊 まとめ
|
||||
|
||||
C ABIは「**シンプル・高速・安定**」の3拍子が揃った、Nyashの基本プラグインシステムです。
|
||||
|
||||
- 最小3関数で実装可能
|
||||
- オーバーヘッドがほぼゼロ
|
||||
- TypeBoxによる拡張で、プラグイン間連携も可能
|
||||
|
||||
**迷ったらC ABIから始める**のが正解です!
|
||||
@ -0,0 +1,202 @@
|
||||
# Nyash ABI プラグインシステム
|
||||
|
||||
## 📦 概要
|
||||
|
||||
Nyash ABIは、**C ABI + TypeBoxをベースに構築された高度なプラグインシステム**です。C ABIの限界を超えて、より豊富な機能と言語間相互運用を提供します。
|
||||
|
||||
## 🏗️ アーキテクチャ
|
||||
|
||||
```
|
||||
基本層:C ABI(シンプル・高速・安定)
|
||||
↓
|
||||
拡張層:TypeBox(プラグイン間連携)
|
||||
↓
|
||||
高度層:Nyash ABI(言語間相互運用・拡張性)
|
||||
```
|
||||
|
||||
Nyash ABIは、C ABIとTypeBoxの上に構築されているため、既存のC ABIプラグインとの互換性を保ちながら、より高度な機能を提供できます。
|
||||
|
||||
## 🎯 特徴
|
||||
|
||||
### C ABIからの進化点
|
||||
|
||||
1. **セレクターベースの高速ディスパッチ**
|
||||
- 文字列比較ではなく、事前計算されたハッシュ値を使用
|
||||
- メソッド呼び出しの高速化
|
||||
|
||||
2. **NyashValue型による統一的な値表現**
|
||||
- 16バイトに最適化された値表現
|
||||
- インライン値サポート(小さな整数やboolは直接格納)
|
||||
|
||||
3. **言語間相互運用**
|
||||
- Python、Go、JavaScript等との連携が可能
|
||||
- 共通のオブジェクトモデルを提供
|
||||
|
||||
4. **高度なメモリ管理**
|
||||
- アトミック参照カウント
|
||||
- 弱参照による循環参照回避
|
||||
|
||||
## 📝 実装例
|
||||
|
||||
### 基本的なNyash ABIプラグイン
|
||||
|
||||
```c
|
||||
#include "nyash_abi.h"
|
||||
|
||||
// Nyash ABIオブジェクト構造体
|
||||
typedef struct {
|
||||
nyash_obj_header header; // 共通ヘッダー(参照カウント等)
|
||||
int value; // カスタムデータ
|
||||
} CounterBox;
|
||||
|
||||
// メソッドディスパッチャー(セレクターベース)
|
||||
nyash_status counter_call(
|
||||
nyash_ctx* ctx,
|
||||
void* self,
|
||||
nyash_selector selector,
|
||||
nyash_value* args,
|
||||
size_t arg_count,
|
||||
nyash_value* result
|
||||
) {
|
||||
CounterBox* counter = (CounterBox*)self;
|
||||
|
||||
// セレクターに基づいて高速ディスパッチ
|
||||
switch(selector) {
|
||||
case NYASH_SEL_INCREMENT: // 事前計算されたハッシュ値
|
||||
counter->value++;
|
||||
*result = nyash_make_int(counter->value);
|
||||
return NYASH_OK;
|
||||
|
||||
case NYASH_SEL_GET_VALUE:
|
||||
*result = nyash_make_int(counter->value);
|
||||
return NYASH_OK;
|
||||
|
||||
default:
|
||||
return NYASH_ERROR_METHOD_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### NyashValue - 統一的な値表現
|
||||
|
||||
```c
|
||||
// 16バイトに最適化された値構造(JIT/LLVM最適化を考慮)
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t payload; // ポインタまたはインライン値
|
||||
uint64_t metadata; // フラグ・追加情報
|
||||
} nyash_value;
|
||||
|
||||
// インライン値の例
|
||||
nyash_value nyash_make_int(int64_t value) {
|
||||
return (nyash_value){
|
||||
.type_id = NYASH_TYPE_INTEGER,
|
||||
.payload = (uint64_t)value,
|
||||
.metadata = NYASH_TAG_SMALL_INT // インライン整数タグ
|
||||
};
|
||||
}
|
||||
|
||||
// Boxオブジェクトの例
|
||||
nyash_value nyash_make_box(void* box_ptr) {
|
||||
return (nyash_value){
|
||||
.type_id = ((nyash_obj_header*)box_ptr)->type_id,
|
||||
.payload = (uint64_t)box_ptr,
|
||||
.metadata = NYASH_TAG_POINTER // ヒープポインタタグ
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 言語間相互運用
|
||||
|
||||
### Python連携
|
||||
|
||||
```python
|
||||
# Python側のNyash ABIラッパー
|
||||
import nyash
|
||||
|
||||
# Nyashプラグインをロード
|
||||
counter = nyash.load_plugin("counter.so")
|
||||
|
||||
# セレクターベースの呼び出し
|
||||
result = counter.call("increment") # 内部でセレクターに変換
|
||||
print(f"Counter value: {result}")
|
||||
```
|
||||
|
||||
### Go連携
|
||||
|
||||
```go
|
||||
// Go側のNyash ABIバインディング
|
||||
package main
|
||||
|
||||
import "github.com/nyash/go-bindings"
|
||||
|
||||
func main() {
|
||||
counter := nyash.LoadPlugin("counter.so")
|
||||
|
||||
// 型安全な呼び出し
|
||||
value, err := counter.Call("increment")
|
||||
if err == nil {
|
||||
fmt.Printf("Counter value: %d\n", value.(int64))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 Nyash ABIがTypeBoxとして実装される仕組み
|
||||
|
||||
Nyash ABIの革新的な点は、**ABIそのものがTypeBoxとして実装される**ことです:
|
||||
|
||||
```c
|
||||
// Nyash ABIプロバイダーもTypeBox(C ABI)として提供
|
||||
typedef struct {
|
||||
// TypeBox標準ヘッダ
|
||||
uint32_t abi_tag; // 'NABI'
|
||||
const char* name; // "NyashABIProvider"
|
||||
void* (*create)(void); // ABIプロバイダ生成
|
||||
|
||||
// Nyash ABI専用操作
|
||||
struct {
|
||||
nyash_status (*call)(nyash_ctx*, void* obj, nyash_selector, ...);
|
||||
void (*retain)(void* obj);
|
||||
void (*release)(void* obj);
|
||||
} nyash_ops;
|
||||
} NyashABITypeBox;
|
||||
```
|
||||
|
||||
これにより:
|
||||
1. **段階的移行**: C ABIプラグインからNyash ABIへの移行が容易
|
||||
2. **相互運用**: C ABIとNyash ABIプラグインが同じシステムで共存
|
||||
3. **セルフホスティング**: 最終的にNyash自身でNyashを実装可能
|
||||
|
||||
## 💡 いつNyash ABIを使うべきか?
|
||||
|
||||
### Nyash ABIが最適な場合
|
||||
- ✅ **他言語との相互運用**が必要(Python/Go/JS等)
|
||||
- ✅ **高度なメソッドディスパッチ**が必要(セレクター方式)
|
||||
- ✅ **複雑な型システム**を扱う
|
||||
- ✅ **将来の拡張性**を重視
|
||||
|
||||
### C ABIで十分な場合
|
||||
- ✅ シンプルな機能のみ必要
|
||||
- ✅ 最高速度を求める(直接関数呼び出し)
|
||||
- ✅ 既存のC/C++ライブラリの単純なラップ
|
||||
|
||||
## 📊 3つのABIの比較
|
||||
|
||||
| 特徴 | C ABI | C ABI + TypeBox | Nyash ABI |
|
||||
|------|-------|-----------------|-----------|
|
||||
| シンプルさ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||||
| 速度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
|
||||
| プラグイン間連携 | ❌ | ✅ | ✅ |
|
||||
| 言語間連携 | ⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
| 拡張性 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
|
||||
## 📚 まとめ
|
||||
|
||||
Nyash ABIは「**C ABI + TypeBoxの上に構築された高度なプラグインシステム**」です。
|
||||
|
||||
- C ABIの安定性とシンプルさを継承
|
||||
- TypeBoxによるプラグイン間連携をサポート
|
||||
- セレクター方式による高速メソッドディスパッチ
|
||||
- 言語間相互運用による無限の可能性
|
||||
|
||||
**高度な機能や将来の拡張性が必要ならNyash ABI**を選びましょう!
|
||||
Reference in New Issue
Block a user