feat(phase-9.75g-0): Adopt ChatGPT final BID-FFI design and update specifications
- Update ffi-abi-specification.md to BID-1 Enhanced Edition - Add efficient Handle design (type_id + instance_id) - Define BID-1 TLV unified format for arguments/results - Add Plugin API with NyashHostVtable and metadata support - Include complete FileBox plugin example in C - Standardize error codes (NYB_SUCCESS, NYB_E_*) - Support 8-byte alignment and platform-dependent usize - Add phase_9_75g_0_chatgpt_enhanced_final.md as the final design - Incorporates all ChatGPT-5 recommendations - Confirms 1-week implementation feasibility - Aligns with Everything is Box philosophy - Update CURRENT_TASK.md to reflect Day 1 progress - Mark specification finalization as complete - Ready to start actual implementation Everything is Box philosophy meets practical FFI/ABI design\! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -6,15 +6,23 @@
|
|||||||
**戦略**: 型定義は全部最初に、実装は段階的に(unimplemented!活用)
|
**戦略**: 型定義は全部最初に、実装は段階的に(unimplemented!活用)
|
||||||
**期間**: 1週間(2025-08-17〜2025-08-24)
|
**期間**: 1週間(2025-08-17〜2025-08-24)
|
||||||
**詳細**:
|
**詳細**:
|
||||||
- [phase_9_75g_0_revised_type_first_approach.md](../予定/native-plan/issues/phase_9_75g_0_revised_type_first_approach.md)
|
- [phase_9_75g_0_chatgpt_enhanced_final.md](../予定/native-plan/issues/phase_9_75g_0_chatgpt_enhanced_final.md) ← **ChatGPT最終案採用!**
|
||||||
- [bid_ffi_ai_final_review_2025-08-17.md](../予定/native-plan/issues/bid_ffi_ai_final_review_2025-08-17.md)
|
- [ffi-abi-specification.md](../説明書/reference/box-design/ffi-abi-specification.md) ← **BID-1仕様に更新完了!**
|
||||||
|
|
||||||
### 🎯 今週の実装計画
|
### 🌟 **Day 1 進捗** (2025-08-17)
|
||||||
- **Day 1**: 全型定義(BidType, Transport, Effect, Error)
|
- ✅ ChatGPT先生の最終レビュー完了
|
||||||
- **Day 2**: プラグインローダー(dlopen/dlsym)
|
- ✅ ffi-abi-specification.mdをBID-1 Enhanced Editionに更新
|
||||||
- **Day 3**: 文字列処理(UTF-8, 所有権)
|
- ✅ Handle設計(type_id + instance_id)確定
|
||||||
- **Day 4**: FileBox最小実装
|
- ✅ BID-1 TLVフォーマット仕様確定
|
||||||
- **Day 5**: エラー処理とOption/Result
|
- ✅ プラグインAPI(nyash_plugin_*)仕様確定
|
||||||
|
- 🚀 **実装開始準備完了!**
|
||||||
|
|
||||||
|
### 🎯 今週の実装計画(ChatGPT最終案準拠)
|
||||||
|
- **Day 1**: BID-1基盤実装(TLV仕様、Handle構造体、エンコード/デコード)← **今日!**
|
||||||
|
- **Day 2**: メタデータAPI実装(init/abi/shutdown、HostVtable、レジストリ)
|
||||||
|
- **Day 3**: 既存Box統合(StringBox/IntegerBox/FutureBoxブリッジ)
|
||||||
|
- **Day 4**: FileBoxプラグイン実装(open/read/write/close)
|
||||||
|
- **Day 5**: 統合テスト・最適化(メモリリーク検証、性能測定)
|
||||||
- **Day 6-7**: ドキュメント・CI・仕上げ
|
- **Day 6-7**: ドキュメント・CI・仕上げ
|
||||||
|
|
||||||
### 🔑 技術的決定事項
|
### 🔑 技術的決定事項
|
||||||
|
|||||||
@ -0,0 +1,347 @@
|
|||||||
|
# Phase 9.75g-0 最終決定版: ChatGPT先生の知恵を完全適用
|
||||||
|
|
||||||
|
## 🎯 ChatGPT先生の最終判定
|
||||||
|
|
||||||
|
> **方向性は正しい**: primitives-by-value + box-by-handle は適切で、Everything is Box哲学を維持している。
|
||||||
|
> **1週間Phase 1は現実的**(スコープを限定すれば)
|
||||||
|
|
||||||
|
## 🌟 修正された型システム設計
|
||||||
|
|
||||||
|
### 1. Handle設計の改善(ChatGPT提案)
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/bid/types.rs - ChatGPT推奨の効率的設計
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum BidType {
|
||||||
|
// === プリミティブ(FFI境界で値渡し) ===
|
||||||
|
Bool, // Nyashのbool literal
|
||||||
|
I32, // 32ビット整数
|
||||||
|
I64, // Nyashの標準整数
|
||||||
|
F32, // 32ビット浮動小数点
|
||||||
|
F64, // Nyashの標準浮動小数点
|
||||||
|
String, // UTF-8文字列 (ptr: usize, len: usize)
|
||||||
|
Bytes, // バイナリデータ (ptr: usize, len: usize)
|
||||||
|
|
||||||
|
// === ChatGPT推奨: 効率的なHandle設計 ===
|
||||||
|
Handle {
|
||||||
|
type_id: u32, // StringBox=1, FileBox=6等
|
||||||
|
instance_id: u32, // インスタンス識別子
|
||||||
|
},
|
||||||
|
// 代替: 単一u64として type_id << 32 | instance_id も可
|
||||||
|
|
||||||
|
// === メタ型 ===
|
||||||
|
Void, // 戻り値なし
|
||||||
|
|
||||||
|
// === Phase 2予約(TLVタグ予約済み) ===
|
||||||
|
Option(Box<BidType>), // TLVタグ=21
|
||||||
|
Result(Box<BidType>, Box<BidType>), // TLVタグ=20
|
||||||
|
Array(Box<BidType>), // TLVタグ=22
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything is Box対応表(修正版)
|
||||||
|
/*
|
||||||
|
Handle{type_id: 1, instance_id: 123} → StringBox インスタンス
|
||||||
|
Handle{type_id: 6, instance_id: 456} → FileBox プラグイン
|
||||||
|
Handle{type_id: 7, instance_id: 789} → FutureBox(既存活用)
|
||||||
|
Handle{type_id: 8, instance_id: 101} → P2PBox(既存)
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. BID-1 TLV統一フォーマット(ChatGPT仕様)
|
||||||
|
|
||||||
|
```c
|
||||||
|
// BID-1 TLV仕様 - 引数・結果の統一フォーマット
|
||||||
|
struct BidTLV {
|
||||||
|
u16 version; // 1(BID-1)
|
||||||
|
u16 argc; // 引数数
|
||||||
|
// 後続: TLVエントリの配列
|
||||||
|
};
|
||||||
|
|
||||||
|
// TLVエントリ構造
|
||||||
|
struct TLVEntry {
|
||||||
|
u8 tag; // 型タグ
|
||||||
|
u8 reserved; // 将来用(0)
|
||||||
|
u16 size; // ペイロードサイズ
|
||||||
|
// 後続: ペイロードデータ
|
||||||
|
};
|
||||||
|
|
||||||
|
// タグ定義(Phase 1)
|
||||||
|
#define BID_TAG_BOOL 1 // payload: 1 byte (0/1)
|
||||||
|
#define BID_TAG_I32 2 // payload: 4 bytes (little-endian)
|
||||||
|
#define BID_TAG_I64 3 // payload: 8 bytes (little-endian)
|
||||||
|
#define BID_TAG_F32 4 // payload: 4 bytes (IEEE 754)
|
||||||
|
#define BID_TAG_F64 5 // payload: 8 bytes (IEEE 754)
|
||||||
|
#define BID_TAG_STRING 6 // payload: UTF-8 bytes
|
||||||
|
#define BID_TAG_BYTES 7 // payload: binary data
|
||||||
|
#define BID_TAG_HANDLE 8 // payload: 8 bytes (type_id + instance_id)
|
||||||
|
|
||||||
|
// Phase 2予約
|
||||||
|
#define BID_TAG_RESULT 20 // Result<T,E>
|
||||||
|
#define BID_TAG_OPTION 21 // Option<T>
|
||||||
|
#define BID_TAG_ARRAY 22 // Array<T>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. メタデータAPI追加(ChatGPT推奨)
|
||||||
|
|
||||||
|
```c
|
||||||
|
// src/bid/plugin_api.h - プラグインAPI完全版
|
||||||
|
|
||||||
|
// ホスト機能テーブル
|
||||||
|
typedef struct {
|
||||||
|
void* (*alloc)(size_t size); // メモリ確保
|
||||||
|
void (*free)(void* ptr); // メモリ解放
|
||||||
|
void (*wake)(u32 future_id); // FutureBox起床
|
||||||
|
void (*log)(const char* msg); // ログ出力
|
||||||
|
} NyashHostVtable;
|
||||||
|
|
||||||
|
// プラグイン情報
|
||||||
|
typedef struct {
|
||||||
|
u32 type_id; // Box型ID
|
||||||
|
const char* type_name; // "FileBox"等
|
||||||
|
u32 method_count; // メソッド数
|
||||||
|
const NyashMethodInfo* methods; // メソッドテーブル
|
||||||
|
} NyashPluginInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 method_id; // メソッドID
|
||||||
|
const char* method_name; // "open", "read"等
|
||||||
|
u32 signature_hash; // 型シグネチャハッシュ
|
||||||
|
} NyashMethodInfo;
|
||||||
|
|
||||||
|
// プラグインAPI(必須実装)
|
||||||
|
extern "C" {
|
||||||
|
// ABI版本取得
|
||||||
|
u32 nyash_plugin_abi(void);
|
||||||
|
|
||||||
|
// 初期化(ホスト連携・メタデータ登録)
|
||||||
|
i32 nyash_plugin_init(const NyashHostVtable* host, NyashPluginInfo* info);
|
||||||
|
|
||||||
|
// 統一メソッド呼び出し
|
||||||
|
i32 nyash_plugin_invoke(
|
||||||
|
u32 type_id, // Box型ID
|
||||||
|
u32 method_id, // メソッドID
|
||||||
|
u32 instance_id, // インスタンスID
|
||||||
|
const u8* args, // BID-1 TLV引数
|
||||||
|
size_t args_len, // 引数サイズ
|
||||||
|
u8* result, // BID-1 TLV結果
|
||||||
|
size_t* result_len // 結果サイズ(入出力)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 終了処理
|
||||||
|
void nyash_plugin_shutdown(void);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. メモリ管理の明確化(ChatGPT推奨)
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 2回呼び出しパターン
|
||||||
|
i32 call_plugin_method(...) {
|
||||||
|
size_t result_size = 0;
|
||||||
|
|
||||||
|
// 1回目: サイズ取得(result=null)
|
||||||
|
i32 status = nyash_plugin_invoke(..., NULL, &result_size);
|
||||||
|
if (status != 0) return status;
|
||||||
|
|
||||||
|
// 2回目: ホストがallocateして結果取得
|
||||||
|
u8* result_buffer = host_alloc(result_size);
|
||||||
|
status = nyash_plugin_invoke(..., result_buffer, &result_size);
|
||||||
|
|
||||||
|
// 結果処理...
|
||||||
|
host_free(result_buffer);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// エラーコード定義
|
||||||
|
#define NYB_SUCCESS 0
|
||||||
|
#define NYB_E_SHORT_BUFFER -1 // バッファ不足
|
||||||
|
#define NYB_E_INVALID_TYPE -2 // 不正な型ID
|
||||||
|
#define NYB_E_INVALID_METHOD -3 // 不正なメソッドID
|
||||||
|
#define NYB_E_INVALID_ARGS -4 // 不正な引数
|
||||||
|
#define NYB_E_PLUGIN_ERROR -5 // プラグイン内部エラー
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 修正された実装計画
|
||||||
|
|
||||||
|
### Phase 1実装チェックリスト(ChatGPT提案)
|
||||||
|
|
||||||
|
#### Day 1: BID-1基盤実装
|
||||||
|
- [ ] **BID-1 TLV仕様**とエラーコード定義
|
||||||
|
- [ ] **Handle{type_id,instance_id}**構造体実装
|
||||||
|
- [ ] **基本TLVエンコード/デコード**機能
|
||||||
|
- [ ] テスト: プリミティブ型のTLV変換
|
||||||
|
|
||||||
|
#### Day 2: メタデータAPI実装
|
||||||
|
- [ ] **プラグインinit/abi/shutdown**実装
|
||||||
|
- [ ] **NyashHostVtable**とホスト機能提供
|
||||||
|
- [ ] **型・メソッドレジストリ**管理
|
||||||
|
- [ ] テスト: プラグイン初期化・メタデータ取得
|
||||||
|
|
||||||
|
#### Day 3: 既存Box統合
|
||||||
|
- [ ] **既存StringBox/IntegerBox/FutureBoxブリッジ**
|
||||||
|
- [ ] **NyashBoxRegistry**でハンドル管理
|
||||||
|
- [ ] **FutureBox用wake経路**実装
|
||||||
|
- [ ] テスト: 既存Boxとプラグインの統一操作
|
||||||
|
|
||||||
|
#### Day 4: FileBoxプラグイン実装
|
||||||
|
- [ ] **FileBoxプラグイン**(open/read/close)
|
||||||
|
- [ ] **BID-1フォーマット**での引数・結果処理
|
||||||
|
- [ ] **エラー処理**完全実装
|
||||||
|
- [ ] テスト: ファイル操作e2e動作
|
||||||
|
|
||||||
|
#### Day 5: 統合テスト・最適化
|
||||||
|
- [ ] **適合性テスト**(プリミティブ、ハンドル、エラー)
|
||||||
|
- [ ] **メモリリーク検証**
|
||||||
|
- [ ] **性能測定**(FFI呼び出しオーバーヘッド)
|
||||||
|
- [ ] テスト: 全機能統合動作
|
||||||
|
|
||||||
|
#### Day 6-7: ドキュメント・CI
|
||||||
|
- [ ] **使用例とドキュメント**
|
||||||
|
- [ ] **Linux x86-64 CI設定**
|
||||||
|
- [ ] **プラグイン開発ガイド**
|
||||||
|
- [ ] 予備日(問題対応)
|
||||||
|
|
||||||
|
## 🛠️ 具体的な実装例
|
||||||
|
|
||||||
|
### FileBoxプラグイン例(ChatGPT仕様準拠)
|
||||||
|
|
||||||
|
```c
|
||||||
|
// plugins/nyash-file/src/lib.c
|
||||||
|
|
||||||
|
#include "nyash_plugin_api.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// ABI版本
|
||||||
|
u32 nyash_plugin_abi(void) {
|
||||||
|
return 1; // BID-1対応
|
||||||
|
}
|
||||||
|
|
||||||
|
// メソッドテーブル
|
||||||
|
static const NyashMethodInfo FILE_METHODS[] = {
|
||||||
|
{1, "open", 0x12345678}, // open(path: string, mode: string) -> Handle
|
||||||
|
{2, "read", 0x87654321}, // read(handle: Handle, size: i32) -> Bytes
|
||||||
|
{3, "close", 0xABCDEF00}, // close(handle: Handle) -> Void
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初期化
|
||||||
|
i32 nyash_plugin_init(const NyashHostVtable* host, NyashPluginInfo* info) {
|
||||||
|
info->type_id = 6; // FileBox
|
||||||
|
info->type_name = "FileBox";
|
||||||
|
info->method_count = 3;
|
||||||
|
info->methods = FILE_METHODS;
|
||||||
|
|
||||||
|
// ホスト機能保存
|
||||||
|
g_host = host;
|
||||||
|
return NYB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// メソッド実行
|
||||||
|
i32 nyash_plugin_invoke(u32 type_id, u32 method_id, u32 instance_id,
|
||||||
|
const u8* args, size_t args_len,
|
||||||
|
u8* result, size_t* result_len) {
|
||||||
|
if (type_id != 6) return NYB_E_INVALID_TYPE;
|
||||||
|
|
||||||
|
switch (method_id) {
|
||||||
|
case 1: return file_open(args, args_len, result, result_len);
|
||||||
|
case 2: return file_read(args, args_len, result, result_len);
|
||||||
|
case 3: return file_close(args, args_len, result, result_len);
|
||||||
|
default: return NYB_E_INVALID_METHOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ファイルオープン実装
|
||||||
|
static i32 file_open(const u8* args, size_t args_len,
|
||||||
|
u8* result, size_t* result_len) {
|
||||||
|
// BID-1 TLV解析
|
||||||
|
BidTLV* tlv = (BidTLV*)args;
|
||||||
|
if (tlv->version != 1 || tlv->argc != 2) {
|
||||||
|
return NYB_E_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 引数抽出: path, mode
|
||||||
|
const char* path = extract_string_arg(tlv, 0);
|
||||||
|
const char* mode = extract_string_arg(tlv, 1);
|
||||||
|
|
||||||
|
// ファイルオープン
|
||||||
|
FILE* fp = fopen(path, mode);
|
||||||
|
if (!fp) return NYB_E_PLUGIN_ERROR;
|
||||||
|
|
||||||
|
// ハンドル生成
|
||||||
|
u32 handle_id = register_file_handle(fp);
|
||||||
|
|
||||||
|
// BID-1結果作成
|
||||||
|
if (!result) {
|
||||||
|
*result_len = sizeof(BidTLV) + sizeof(TLVEntry) + 8; // Handle
|
||||||
|
return NYB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle{type_id: 6, instance_id: handle_id}をTLVで返す
|
||||||
|
encode_handle_result(result, 6, handle_id);
|
||||||
|
return NYB_SUCCESS;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚠️ リスク対策(ChatGPT指摘)
|
||||||
|
|
||||||
|
### 実装時の注意点
|
||||||
|
1. **ハンドル再利用/ABA**: generation追加で回避
|
||||||
|
2. **スレッド前提**: シングルスレッド前提を明記
|
||||||
|
3. **メソッドID衝突**: ビルド時固定で回避
|
||||||
|
4. **エラー伝播**: トランスポート/ドメインエラー分離
|
||||||
|
5. **文字列エンコード**: UTF-8必須、内部NUL禁止
|
||||||
|
|
||||||
|
### 安全性確保
|
||||||
|
```rust
|
||||||
|
// Rust側での安全な実装例
|
||||||
|
pub struct SafeHandle {
|
||||||
|
type_id: u32,
|
||||||
|
instance_id: u32,
|
||||||
|
generation: u32, // ABA対策
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SafeHandle {
|
||||||
|
pub fn new(type_id: u32) -> Self {
|
||||||
|
let instance_id = HANDLE_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||||
|
Self { type_id, instance_id, generation: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 期待される成果
|
||||||
|
|
||||||
|
### Phase 1完了時
|
||||||
|
- [ ] **Everything is Box哲学の技術的実現**
|
||||||
|
- [ ] **既存FutureBox等との完全統合**
|
||||||
|
- [ ] **効率的なBID-1 TLVフォーマット**
|
||||||
|
- [ ] **拡張可能なメタデータシステム**
|
||||||
|
- [ ] **1つのFileBoxプラグインが完全動作**
|
||||||
|
|
||||||
|
### 将来への基盤
|
||||||
|
- [ ] **gRPC/RESTへの明確な拡張パス**
|
||||||
|
- [ ] **P2P(NyaMesh)統合の技術的基盤**
|
||||||
|
- [ ] **他言語プラグインへの拡張可能性**
|
||||||
|
|
||||||
|
## 📝 最終まとめ
|
||||||
|
|
||||||
|
**ChatGPT先生の結論**:
|
||||||
|
> **箱理論設計は技術的に妥当!**
|
||||||
|
> **具体的で実装可能な修正案を完全適用**
|
||||||
|
> **1週間実装の現実性を確認**
|
||||||
|
> **将来拡張への明確な道筋を提示**
|
||||||
|
|
||||||
|
### 成功の鍵
|
||||||
|
1. **Handle設計のバイナリ化** - 効率性向上
|
||||||
|
2. **TLV統一フォーマット** - 拡張性確保
|
||||||
|
3. **メタデータAPI** - プラグイン管理強化
|
||||||
|
4. **既存Box活用** - 二重実装回避
|
||||||
|
|
||||||
|
**結論**: Nyashの独特な哲学を技術的に実現する、最適化された実装計画の完成!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**最終確定日**: 2025-08-17
|
||||||
|
**設計者**: Claude + ChatGPT-5の知恵
|
||||||
|
**ステータス**: 実装準備完了 🚀
|
||||||
|
**キーワード**: Everything is Box, Efficient, Extensible, Practical
|
||||||
@ -1,56 +1,153 @@
|
|||||||
# Box FFI/ABI v0 (Draft)
|
# Box FFI/ABI v0 (BID-1 Enhanced Edition)
|
||||||
|
|
||||||
Purpose
|
Purpose
|
||||||
- Define a language-agnostic ABI to call external libraries as Boxes.
|
- Define a language-agnostic ABI to call external libraries as Boxes.
|
||||||
- Serve as a single source of truth for MIR ExternCall, WASM RuntimeImports, VM stubs, and future language codegens (TS/Python/Rust/LLVM IR).
|
- Serve as a single source of truth for MIR ExternCall, WASM RuntimeImports, VM stubs, and future language codegens (TS/Python/Rust/LLVM IR).
|
||||||
|
- Support Everything is Box philosophy with efficient Handle design.
|
||||||
|
|
||||||
Design Goals
|
Design Goals
|
||||||
- Simple first: UTF-8 strings as (ptr,len), i32 for small integers, 32-bit linear memory alignment friendly.
|
- Simple first: UTF-8 strings as (ptr,len), i32 for small integers, 32-bit linear memory alignment friendly.
|
||||||
- Deterministic and portable across WASM/VM/native backends.
|
- Deterministic and portable across WASM/VM/native backends.
|
||||||
- Align with MIR effect system (pure/mut/io/control) to preserve optimization safety.
|
- Align with MIR effect system (pure/mut/io/control) to preserve optimization safety.
|
||||||
|
- Efficient Handle design for Box instances (type_id + instance_id).
|
||||||
|
|
||||||
Core Types
|
Core Types
|
||||||
- i32, i64, f32, f64, bool (0|1)
|
- i32, i64, f32, f64, bool (0|1)
|
||||||
- string: UTF-8 in linear memory as (ptr: i32, len: i32)
|
- string: UTF-8 in linear memory as (ptr: usize, len: usize)
|
||||||
- boxref: opaque 32-bit handle or pointer (backend-dependent)
|
- bytes: Binary data as (ptr: usize, len: usize)
|
||||||
- array(T): (ptr: i32, len: i32, [cap: i32 optional])
|
- handle: Efficient Box handle as {type_id: u32, instance_id: u32} or packed u64
|
||||||
- void, null (represented as 0 for pointer-like values)
|
- array(T): (ptr: usize, len: usize)
|
||||||
|
- void (no return value)
|
||||||
|
|
||||||
Memory & Alignment
|
Memory & Alignment
|
||||||
- All pointers are 32-bit in WASM MVP. Align to 4 bytes.
|
- All pointers are platform-dependent (usize): 32-bit in WASM MVP, 64-bit on native x86-64.
|
||||||
|
- Alignment: 8-byte boundary for all structures.
|
||||||
- Strings/arrays must be contiguous in linear memory; no NUL terminator required (len is authoritative).
|
- Strings/arrays must be contiguous in linear memory; no NUL terminator required (len is authoritative).
|
||||||
- Box layout examples for built-ins (for backends that materialize Boxes in memory):
|
- Box layout examples for built-ins (for backends that materialize Boxes in memory):
|
||||||
- Header: [type_id:i32][ref_count:i32][field_count:i32]
|
- Header: [type_id:i32][ref_count:i32][field_count:i32]
|
||||||
- StringBox: header + [data_ptr:i32][length:i32]
|
- StringBox: header + [data_ptr:usize][length:usize]
|
||||||
|
|
||||||
|
Handle Design (BID-1 Enhancement)
|
||||||
|
- Handle represents a Box instance with two components:
|
||||||
|
- type_id: u32 (1=StringBox, 6=FileBox, 7=FutureBox, 8=P2PBox, etc.)
|
||||||
|
- instance_id: u32 (unique instance identifier)
|
||||||
|
- Can be passed as single u64 (type_id << 32 | instance_id) or struct
|
||||||
|
|
||||||
Naming & Resolution
|
Naming & Resolution
|
||||||
- Interface namespace: `env.console`, `env.canvas`, etc.
|
- Interface namespace: `env.console`, `env.canvas`, `nyash.file`, etc.
|
||||||
- Method: `log`, `fillRect`, `fillText`.
|
- Method: `log`, `fillRect`, `fillText`, `open`, `read`, `write`, `close`.
|
||||||
- Fully-qualified name: `env.console.log`, `env.canvas.fillRect`.
|
- Fully-qualified name: `env.console.log`, `env.canvas.fillRect`, `nyash.file.open`.
|
||||||
|
|
||||||
Calling Convention (v0)
|
Calling Convention (BID-1)
|
||||||
- Positional parameters, no varargs.
|
- Single entry point: `nyash_plugin_invoke`
|
||||||
- Strings/arrays passed as (ptr,len) pairs.
|
- Arguments passed as BID-1 TLV format
|
||||||
- Return values:
|
- Return values in BID-1 TLV format
|
||||||
- Single scalar (i32/i64/f32/f64/bool) or void.
|
- Two-call pattern for dynamic results:
|
||||||
- Box/complex returns are out-of-scope for v0; use out-params if necessary.
|
1. First call with null result buffer to get size
|
||||||
|
2. Second call with allocated buffer to get data
|
||||||
|
|
||||||
Error Model (v0)
|
Error Model (BID-1)
|
||||||
- Prefer total functions for v0 demos.
|
- Standardized error codes:
|
||||||
- If needed, return i32 status (0=ok, nonzero=error) and use out-params.
|
- NYB_SUCCESS (0): Operation successful
|
||||||
- Exceptions/signals are out-of-scope.
|
- NYB_E_SHORT_BUFFER (-1): Buffer too small
|
||||||
|
- NYB_E_INVALID_TYPE (-2): Invalid type ID
|
||||||
|
- NYB_E_INVALID_METHOD (-3): Invalid method ID
|
||||||
|
- NYB_E_INVALID_ARGS (-4): Invalid arguments
|
||||||
|
- NYB_E_PLUGIN_ERROR (-5): Plugin internal error
|
||||||
|
|
||||||
Effects
|
Effects
|
||||||
- Each BID method declares one of: pure | mut | io | control.
|
- Each BID method declares one of: pure | mut | io | control.
|
||||||
- Optimizer/verifier rules:
|
- Optimizer/verifier rules:
|
||||||
- pure: reordering permitted
|
- pure: reordering permitted, memoization possible
|
||||||
- mut: preserve order w.r.t same resource
|
- mut: preserve order w.r.t same resource
|
||||||
- io: preserve program order
|
- io: preserve program order strictly
|
||||||
- control: affects CFG; handled as terminators or dedicated ops
|
- control: affects CFG; handled as terminators or dedicated ops
|
||||||
|
|
||||||
|
BID-1 TLV Format
|
||||||
|
```c
|
||||||
|
// BID-1 TLV specification - unified format for arguments and results
|
||||||
|
struct BidTLV {
|
||||||
|
u16 version; // 1 (BID-1)
|
||||||
|
u16 argc; // argument count
|
||||||
|
// followed by TLVEntry array
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TLVEntry {
|
||||||
|
u8 tag; // type tag
|
||||||
|
u8 reserved; // future use (0)
|
||||||
|
u16 size; // payload size
|
||||||
|
// followed by payload data
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tag definitions (Phase 1)
|
||||||
|
#define BID_TAG_BOOL 1 // payload: 1 byte (0/1)
|
||||||
|
#define BID_TAG_I32 2 // payload: 4 bytes (little-endian)
|
||||||
|
#define BID_TAG_I64 3 // payload: 8 bytes (little-endian)
|
||||||
|
#define BID_TAG_F32 4 // payload: 4 bytes (IEEE 754)
|
||||||
|
#define BID_TAG_F64 5 // payload: 8 bytes (IEEE 754)
|
||||||
|
#define BID_TAG_STRING 6 // payload: UTF-8 bytes
|
||||||
|
#define BID_TAG_BYTES 7 // payload: binary data
|
||||||
|
#define BID_TAG_HANDLE 8 // payload: 8 bytes (type_id + instance_id)
|
||||||
|
|
||||||
|
// Phase 2 reserved
|
||||||
|
#define BID_TAG_RESULT 20 // Result<T,E>
|
||||||
|
#define BID_TAG_OPTION 21 // Option<T>
|
||||||
|
#define BID_TAG_ARRAY 22 // Array<T>
|
||||||
|
```
|
||||||
|
|
||||||
|
Plugin API (BID-1)
|
||||||
|
```c
|
||||||
|
// src/bid/plugin_api.h - Plugin API complete version
|
||||||
|
|
||||||
|
// Host function table
|
||||||
|
typedef struct {
|
||||||
|
void* (*alloc)(size_t size); // Memory allocation
|
||||||
|
void (*free)(void* ptr); // Memory deallocation
|
||||||
|
void (*wake)(u32 future_id); // FutureBox wake
|
||||||
|
void (*log)(const char* msg); // Log output
|
||||||
|
} NyashHostVtable;
|
||||||
|
|
||||||
|
// Plugin information
|
||||||
|
typedef struct {
|
||||||
|
u32 type_id; // Box type ID
|
||||||
|
const char* type_name; // "FileBox" etc.
|
||||||
|
u32 method_count; // Method count
|
||||||
|
const NyashMethodInfo* methods; // Method table
|
||||||
|
} NyashPluginInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 method_id; // Method ID
|
||||||
|
const char* method_name; // "open", "read" etc.
|
||||||
|
u32 signature_hash; // Type signature hash
|
||||||
|
} NyashMethodInfo;
|
||||||
|
|
||||||
|
// Plugin API (required implementation)
|
||||||
|
extern "C" {
|
||||||
|
// Get ABI version
|
||||||
|
u32 nyash_plugin_abi(void);
|
||||||
|
|
||||||
|
// Initialize (host integration & metadata registration)
|
||||||
|
i32 nyash_plugin_init(const NyashHostVtable* host, NyashPluginInfo* info);
|
||||||
|
|
||||||
|
// Unified method invocation
|
||||||
|
i32 nyash_plugin_invoke(
|
||||||
|
u32 type_id, // Box type ID
|
||||||
|
u32 method_id, // Method ID
|
||||||
|
u32 instance_id, // Instance ID
|
||||||
|
const u8* args, // BID-1 TLV arguments
|
||||||
|
size_t args_len, // Arguments size
|
||||||
|
u8* result, // BID-1 TLV result
|
||||||
|
size_t* result_len // Result size (in/out)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Shutdown
|
||||||
|
void nyash_plugin_shutdown(void);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
BID (Box Interface Definition) — YAML
|
BID (Box Interface Definition) — YAML
|
||||||
```yaml
|
```yaml
|
||||||
version: 0
|
version: 1 # BID-1 format
|
||||||
interfaces:
|
interfaces:
|
||||||
- name: env.console
|
- name: env.console
|
||||||
box: Console
|
box: Console
|
||||||
@ -84,6 +181,127 @@ interfaces:
|
|||||||
- {string: color}
|
- {string: color}
|
||||||
returns: void
|
returns: void
|
||||||
effect: io
|
effect: io
|
||||||
|
|
||||||
|
- name: nyash.file
|
||||||
|
box: FileBox
|
||||||
|
type_id: 6
|
||||||
|
methods:
|
||||||
|
- name: open
|
||||||
|
method_id: 1
|
||||||
|
params:
|
||||||
|
- {string: path}
|
||||||
|
- {string: mode}
|
||||||
|
returns: {handle: FileBox}
|
||||||
|
effect: io
|
||||||
|
|
||||||
|
- name: read
|
||||||
|
method_id: 2
|
||||||
|
params:
|
||||||
|
- {handle: handle}
|
||||||
|
- {i32: size}
|
||||||
|
returns: {bytes: data}
|
||||||
|
effect: io
|
||||||
|
|
||||||
|
- name: write
|
||||||
|
method_id: 3
|
||||||
|
params:
|
||||||
|
- {handle: handle}
|
||||||
|
- {bytes: data}
|
||||||
|
returns: {i32: written}
|
||||||
|
effect: io
|
||||||
|
|
||||||
|
- name: close
|
||||||
|
method_id: 4
|
||||||
|
params:
|
||||||
|
- {handle: handle}
|
||||||
|
returns: void
|
||||||
|
effect: io
|
||||||
|
```
|
||||||
|
|
||||||
|
FileBox Plugin Example (BID-1)
|
||||||
|
```c
|
||||||
|
// plugins/nyash-file/src/lib.c
|
||||||
|
|
||||||
|
#include "nyash_plugin_api.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static const NyashHostVtable* g_host = NULL;
|
||||||
|
|
||||||
|
// ABI version
|
||||||
|
u32 nyash_plugin_abi(void) {
|
||||||
|
return 1; // BID-1 support
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method table
|
||||||
|
static const NyashMethodInfo FILE_METHODS[] = {
|
||||||
|
{1, "open", 0x12345678}, // open(path: string, mode: string) -> Handle
|
||||||
|
{2, "read", 0x87654321}, // read(handle: Handle, size: i32) -> Bytes
|
||||||
|
{3, "write", 0x11223344}, // write(handle: Handle, data: Bytes) -> i32
|
||||||
|
{4, "close", 0xABCDEF00}, // close(handle: Handle) -> Void
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
i32 nyash_plugin_init(const NyashHostVtable* host, NyashPluginInfo* info) {
|
||||||
|
info->type_id = 6; // FileBox
|
||||||
|
info->type_name = "FileBox";
|
||||||
|
info->method_count = 4;
|
||||||
|
info->methods = FILE_METHODS;
|
||||||
|
|
||||||
|
// Save host functions
|
||||||
|
g_host = host;
|
||||||
|
return NYB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method execution
|
||||||
|
i32 nyash_plugin_invoke(u32 type_id, u32 method_id, u32 instance_id,
|
||||||
|
const u8* args, size_t args_len,
|
||||||
|
u8* result, size_t* result_len) {
|
||||||
|
if (type_id != 6) return NYB_E_INVALID_TYPE;
|
||||||
|
|
||||||
|
switch (method_id) {
|
||||||
|
case 1: return file_open(args, args_len, result, result_len);
|
||||||
|
case 2: return file_read(instance_id, args, args_len, result, result_len);
|
||||||
|
case 3: return file_write(instance_id, args, args_len, result, result_len);
|
||||||
|
case 4: return file_close(instance_id, args, args_len, result, result_len);
|
||||||
|
default: return NYB_E_INVALID_METHOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// File open implementation
|
||||||
|
static i32 file_open(const u8* args, size_t args_len,
|
||||||
|
u8* result, size_t* result_len) {
|
||||||
|
// BID-1 TLV parsing
|
||||||
|
BidTLV* tlv = (BidTLV*)args;
|
||||||
|
if (tlv->version != 1 || tlv->argc != 2) {
|
||||||
|
return NYB_E_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract arguments: path, mode
|
||||||
|
const char* path = extract_string_arg(tlv, 0);
|
||||||
|
const char* mode = extract_string_arg(tlv, 1);
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
FILE* fp = fopen(path, mode);
|
||||||
|
if (!fp) return NYB_E_PLUGIN_ERROR;
|
||||||
|
|
||||||
|
// Generate handle
|
||||||
|
u32 handle_id = register_file_handle(fp);
|
||||||
|
|
||||||
|
// BID-1 result creation
|
||||||
|
if (!result) {
|
||||||
|
*result_len = sizeof(BidTLV) + sizeof(TLVEntry) + 8; // Handle
|
||||||
|
return NYB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return Handle{type_id: 6, instance_id: handle_id} in TLV
|
||||||
|
encode_handle_result(result, 6, handle_id);
|
||||||
|
return NYB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nyash_plugin_shutdown(void) {
|
||||||
|
// Cleanup resources
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
WASM Mapping (RuntimeImports)
|
WASM Mapping (RuntimeImports)
|
||||||
@ -94,6 +312,7 @@ WASM Mapping (RuntimeImports)
|
|||||||
- Host responsibilities:
|
- Host responsibilities:
|
||||||
- Resolve strings from memory via `(ptr,len)` using TextDecoder('utf-8')
|
- Resolve strings from memory via `(ptr,len)` using TextDecoder('utf-8')
|
||||||
- Map to DOM/Canvas/Console as appropriate
|
- Map to DOM/Canvas/Console as appropriate
|
||||||
|
- For plugins: use dlopen/dlsym to load and invoke nyash_plugin_* functions
|
||||||
|
|
||||||
WASM Mapping Rules (v0)
|
WASM Mapping Rules (v0)
|
||||||
- String marshalling: UTF-8 `(ptr:i32, len:i32)`; memory exported as `memory`.
|
- String marshalling: UTF-8 `(ptr:i32, len:i32)`; memory exported as `memory`.
|
||||||
@ -113,45 +332,89 @@ RuntimeImportsとBIDの関係
|
|||||||
→ `canvas_fillRect(id_ptr, id_len, x, y, w, h, color_ptr, color_len)`
|
→ `canvas_fillRect(id_ptr, id_len, x, y, w, h, color_ptr, color_len)`
|
||||||
|
|
||||||
============================================================
|
============================================================
|
||||||
ABIの確定事項(v0, 日本語)
|
ABIの確定事項(BID-1, 日本語)
|
||||||
============================================================
|
============================================================
|
||||||
|
|
||||||
基本方針(v0)
|
基本方針(BID-1)
|
||||||
- 文字列は UTF-8 の `(ptr:i32, len:i32)` で受け渡す(NUL終端不要)。
|
- 文字列は UTF-8 の `(ptr:usize, len:usize)` で受け渡す(NUL終端不要、内部NUL禁止)。
|
||||||
- 配列/バイト列は `(ptr:i32, len:i32[, cap:i32])` とし、v0では `(ptr,len)` を基本とする。
|
- 配列/バイト列は `(ptr:usize, len:usize)` とする。
|
||||||
- 数値は WASM/LLVM と親和性の高い素のプリミティブ(i32/i64/f32/f64)。
|
- 数値は WASM/LLVM と親和性の高い素のプリミティブ(i32/i64/f32/f64)。
|
||||||
- 真偽値は `i32` で 0=false, 1=true。
|
- 真偽値は `i32` で 0=false, 1=true。
|
||||||
- ポインタは `i32`(WASM MVP)を基本。ネイティブAOTではプラットフォーム幅に合わせる(将来)。
|
- ポインタは `usize`(WASM MVPは32bit、ネイティブx86-64は64bit)。
|
||||||
- エンディアンはリトルエンディアン(WASM/一般的なネイティブと一致)。
|
- エンディアンはリトルエンディアン(WASM/一般的なネイティブと一致)。
|
||||||
- 呼出規約は位置パラメータのみ(可変長/キーワードは範囲外)。
|
- 呼出規約は単一エントリーポイント `nyash_plugin_invoke` + BID-1 TLV形式。
|
||||||
- 戻り値は単一スカラ(void含む)。複合は out-param で表現(将来拡張)。
|
- 戻り値はBID-1 TLV形式(2回呼び出しパターンでサイズ取得)。
|
||||||
- メモリは `memory` をエクスポート(WASM)。`TextDecoder('utf-8')` 等で復元(Host側責務)。
|
- メモリは `memory` をエクスポート(WASM)。ホスト側で管理。
|
||||||
- 効果(effect)は BID に必須。pure は再順序化可、mut/io は順序保持。
|
- 効果(effect)は BID に必須。pure は再順序化可、mut/io は順序保持。
|
||||||
- 同期のみ(非同期は将来拡張)。
|
- 同期のみ(非同期は将来拡張)。
|
||||||
|
- スレッド前提:シングルスレッド(Phase 1)。
|
||||||
|
|
||||||
型と表現(v0)
|
メモリ管理戦略
|
||||||
|
- 2回呼び出しパターン:
|
||||||
|
1. result=NULLでサイズ取得
|
||||||
|
2. ホストがallocateして結果取得
|
||||||
|
- 文字列エンコーディング:UTF-8必須、内部NUL禁止
|
||||||
|
- ハンドル再利用対策:generation追加で ABA問題回避(将来)
|
||||||
|
|
||||||
|
型と表現(BID-1)
|
||||||
- `i32`: 32bit 符号付き整数
|
- `i32`: 32bit 符号付き整数
|
||||||
- `i64`: 64bit 符号付き整数(WASMではJSブリッジ注意。Host側はBigInt等)
|
- `i64`: 64bit 符号付き整数(WASMではJSブリッジ注意。Host側はBigInt等)
|
||||||
- `f32/f64`: IEEE 754
|
- `f32/f64`: IEEE 754
|
||||||
- `bool`: i32(0/1)
|
- `bool`: i32(0/1)
|
||||||
- `string`: UTF-8 `(ptr:i32, len:i32)`
|
- `string`: UTF-8 `(ptr:usize, len:usize)`
|
||||||
- `array<T>`: `(ptr:i32, len:i32[, cap:i32])`(v0は `(ptr,len)` を優先)
|
- `bytes`: バイナリデータ `(ptr:usize, len:usize)`
|
||||||
- `boxref`: Opaque(数値ハンドル or ポインタ)。v0では数値 i32 を推奨。
|
- `array<T>`: `(ptr:usize, len:usize)`
|
||||||
|
- `handle`: Box参照 `{type_id:u32, instance_id:u32}` または packed u64
|
||||||
|
- `void`: 戻り値なし
|
||||||
|
|
||||||
|
BidType Rust実装
|
||||||
|
```rust
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum BidType {
|
||||||
|
// プリミティブ(FFI境界で値渡し)
|
||||||
|
Bool, I32, I64, F32, F64,
|
||||||
|
String, Bytes,
|
||||||
|
|
||||||
|
// Handle設計
|
||||||
|
Handle { type_id: u32, instance_id: u32 },
|
||||||
|
|
||||||
|
// メタ型
|
||||||
|
Void,
|
||||||
|
|
||||||
|
// Phase 2予約
|
||||||
|
Option(Box<BidType>),
|
||||||
|
Result(Box<BidType>, Box<BidType>),
|
||||||
|
Array(Box<BidType>),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
アラインメント/境界
|
アラインメント/境界
|
||||||
- `ptr` は 4byte アライン推奨(必須ではないが実装が簡潔)。
|
- `ptr` は 8byte アライン必須(構造体の効率的アクセス)。
|
||||||
- 範囲外アクセスは未定義ではなく「Hostが防ぐ/検証する」方針(将来、Verifier/境界チェック生成)。
|
- 範囲外アクセスは未定義ではなく「Hostが防ぐ/検証する」方針(将来、Verifier/境界チェック生成)。
|
||||||
|
- プラットフォーム依存:
|
||||||
|
- Linux x86-64: 8バイト境界
|
||||||
|
- WASM MVP: 4バイト境界(互換性のため)
|
||||||
|
|
||||||
命名規約
|
命名規約
|
||||||
- `env.console.log`, `env.canvas.fillRect` のように `<namespace>.<iface>.<method>`。
|
- `env.console.log`, `env.canvas.fillRect` のように `<namespace>.<iface>.<method>`。
|
||||||
- WASM import 名は `env.console_log` 等の平坦化でも可(生成側で一貫)。
|
- WASM import 名は `env.console_log` 等の平坦化でも可(生成側で一貫)。
|
||||||
|
- プラグイン関数名: `nyash_plugin_*` プレフィックス必須。
|
||||||
|
|
||||||
エラー/例外
|
エラー/例外
|
||||||
- v0は例外なし。失敗は整数ステータス or 明示エラーコールバックに委譲(将来)。
|
- BID-1標準エラーコード使用(NYB_*)。
|
||||||
|
- 失敗は整数ステータスで返却。
|
||||||
|
- 例外/シグナルは範囲外。
|
||||||
|
|
||||||
セキュリティ/権限(将来)
|
セキュリティ/権限(将来)
|
||||||
- BID に必要権限(console/canvas/storage/net…)を記述。HostはAllowlistで制御(Phase 9.9)。
|
- BID に必要権限(console/canvas/storage/net…)を記述。HostはAllowlistで制御(Phase 9.9)。
|
||||||
|
|
||||||
|
実装上の注意点
|
||||||
|
- ハンドル再利用/ABA: generation追加で回避
|
||||||
|
- スレッド前提: シングルスレッド前提を明記
|
||||||
|
- メソッドID衝突: ビルド時固定で回避
|
||||||
|
- エラー伝播: トランスポート/ドメインエラー分離
|
||||||
|
- 文字列エンコード: UTF-8必須、内部NUL禁止
|
||||||
|
|
||||||
============================================================
|
============================================================
|
||||||
BIDサンプル(YAML, 日本語)
|
BIDサンプル(YAML, 日本語)
|
||||||
============================================================
|
============================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user