diff --git a/docs/CURRENT_TASK.md b/docs/CURRENT_TASK.md index 87f71de5..d5f3da0f 100644 --- a/docs/CURRENT_TASK.md +++ b/docs/CURRENT_TASK.md @@ -6,15 +6,23 @@ **戦略**: 型定義は全部最初に、実装は段階的に(unimplemented!活用) **期間**: 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) -- [bid_ffi_ai_final_review_2025-08-17.md](../予定/native-plan/issues/bid_ffi_ai_final_review_2025-08-17.md) +- [phase_9_75g_0_chatgpt_enhanced_final.md](../予定/native-plan/issues/phase_9_75g_0_chatgpt_enhanced_final.md) ← **ChatGPT最終案採用!** +- [ffi-abi-specification.md](../説明書/reference/box-design/ffi-abi-specification.md) ← **BID-1仕様に更新完了!** -### 🎯 今週の実装計画 -- **Day 1**: 全型定義(BidType, Transport, Effect, Error) -- **Day 2**: プラグインローダー(dlopen/dlsym) -- **Day 3**: 文字列処理(UTF-8, 所有権) -- **Day 4**: FileBox最小実装 -- **Day 5**: エラー処理とOption/Result +### 🌟 **Day 1 進捗** (2025-08-17) +- ✅ ChatGPT先生の最終レビュー完了 +- ✅ ffi-abi-specification.mdをBID-1 Enhanced Editionに更新 +- ✅ Handle設計(type_id + instance_id)確定 +- ✅ BID-1 TLVフォーマット仕様確定 +- ✅ プラグイン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・仕上げ ### 🔑 技術的決定事項 diff --git a/docs/予定/native-plan/issues/phase_9_75g_0_chatgpt_enhanced_final.md b/docs/予定/native-plan/issues/phase_9_75g_0_chatgpt_enhanced_final.md new file mode 100644 index 00000000..8d1a61d7 --- /dev/null +++ b/docs/予定/native-plan/issues/phase_9_75g_0_chatgpt_enhanced_final.md @@ -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), // TLVタグ=21 + Result(Box, Box), // TLVタグ=20 + Array(Box), // 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 +#define BID_TAG_OPTION 21 // Option +#define BID_TAG_ARRAY 22 // Array +``` + +### 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 +#include + +// 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 \ No newline at end of file diff --git a/docs/説明書/reference/box-design/ffi-abi-specification.md b/docs/説明書/reference/box-design/ffi-abi-specification.md index b2570581..10d59ee3 100644 --- a/docs/説明書/reference/box-design/ffi-abi-specification.md +++ b/docs/説明書/reference/box-design/ffi-abi-specification.md @@ -1,56 +1,153 @@ -# Box FFI/ABI v0 (Draft) +# Box FFI/ABI v0 (BID-1 Enhanced Edition) Purpose - 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). +- Support Everything is Box philosophy with efficient Handle design. Design Goals - 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. - 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 - i32, i64, f32, f64, bool (0|1) -- string: UTF-8 in linear memory as (ptr: i32, len: i32) -- boxref: opaque 32-bit handle or pointer (backend-dependent) -- array(T): (ptr: i32, len: i32, [cap: i32 optional]) -- void, null (represented as 0 for pointer-like values) +- string: UTF-8 in linear memory as (ptr: usize, len: usize) +- bytes: Binary data as (ptr: usize, len: usize) +- handle: Efficient Box handle as {type_id: u32, instance_id: u32} or packed u64 +- array(T): (ptr: usize, len: usize) +- void (no return value) 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). - Box layout examples for built-ins (for backends that materialize Boxes in memory): - 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 -- Interface namespace: `env.console`, `env.canvas`, etc. -- Method: `log`, `fillRect`, `fillText`. -- Fully-qualified name: `env.console.log`, `env.canvas.fillRect`. +- Interface namespace: `env.console`, `env.canvas`, `nyash.file`, etc. +- Method: `log`, `fillRect`, `fillText`, `open`, `read`, `write`, `close`. +- Fully-qualified name: `env.console.log`, `env.canvas.fillRect`, `nyash.file.open`. -Calling Convention (v0) -- Positional parameters, no varargs. -- Strings/arrays passed as (ptr,len) pairs. -- Return values: - - Single scalar (i32/i64/f32/f64/bool) or void. - - Box/complex returns are out-of-scope for v0; use out-params if necessary. +Calling Convention (BID-1) +- Single entry point: `nyash_plugin_invoke` +- Arguments passed as BID-1 TLV format +- Return values in BID-1 TLV format +- Two-call pattern for dynamic results: + 1. First call with null result buffer to get size + 2. Second call with allocated buffer to get data -Error Model (v0) -- Prefer total functions for v0 demos. -- If needed, return i32 status (0=ok, nonzero=error) and use out-params. -- Exceptions/signals are out-of-scope. +Error Model (BID-1) +- Standardized error codes: + - NYB_SUCCESS (0): Operation successful + - 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 - Each BID method declares one of: pure | mut | io | control. - Optimizer/verifier rules: - - pure: reordering permitted + - pure: reordering permitted, memoization possible - 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 +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 +#define BID_TAG_OPTION 21 // Option +#define BID_TAG_ARRAY 22 // Array +``` + +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 ```yaml -version: 0 +version: 1 # BID-1 format interfaces: - name: env.console box: Console @@ -84,6 +181,127 @@ interfaces: - {string: color} returns: void 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 +#include + +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) @@ -94,6 +312,7 @@ WASM Mapping (RuntimeImports) - Host responsibilities: - Resolve strings from memory via `(ptr,len)` using TextDecoder('utf-8') - Map to DOM/Canvas/Console as appropriate + - For plugins: use dlopen/dlsym to load and invoke nyash_plugin_* functions WASM Mapping Rules (v0) - 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)` ============================================================ -ABIの確定事項(v0, 日本語) +ABIの確定事項(BID-1, 日本語) ============================================================ -基本方針(v0) -- 文字列は UTF-8 の `(ptr:i32, len:i32)` で受け渡す(NUL終端不要)。 -- 配列/バイト列は `(ptr:i32, len:i32[, cap:i32])` とし、v0では `(ptr,len)` を基本とする。 +基本方針(BID-1) +- 文字列は UTF-8 の `(ptr:usize, len:usize)` で受け渡す(NUL終端不要、内部NUL禁止)。 +- 配列/バイト列は `(ptr:usize, len:usize)` とする。 - 数値は WASM/LLVM と親和性の高い素のプリミティブ(i32/i64/f32/f64)。 - 真偽値は `i32` で 0=false, 1=true。 -- ポインタは `i32`(WASM MVP)を基本。ネイティブAOTではプラットフォーム幅に合わせる(将来)。 +- ポインタは `usize`(WASM MVPは32bit、ネイティブx86-64は64bit)。 - エンディアンはリトルエンディアン(WASM/一般的なネイティブと一致)。 -- 呼出規約は位置パラメータのみ(可変長/キーワードは範囲外)。 -- 戻り値は単一スカラ(void含む)。複合は out-param で表現(将来拡張)。 -- メモリは `memory` をエクスポート(WASM)。`TextDecoder('utf-8')` 等で復元(Host側責務)。 +- 呼出規約は単一エントリーポイント `nyash_plugin_invoke` + BID-1 TLV形式。 +- 戻り値はBID-1 TLV形式(2回呼び出しパターンでサイズ取得)。 +- メモリは `memory` をエクスポート(WASM)。ホスト側で管理。 - 効果(effect)は BID に必須。pure は再順序化可、mut/io は順序保持。 - 同期のみ(非同期は将来拡張)。 +- スレッド前提:シングルスレッド(Phase 1)。 -型と表現(v0) +メモリ管理戦略 +- 2回呼び出しパターン: + 1. result=NULLでサイズ取得 + 2. ホストがallocateして結果取得 +- 文字列エンコーディング:UTF-8必須、内部NUL禁止 +- ハンドル再利用対策:generation追加で ABA問題回避(将来) + +型と表現(BID-1) - `i32`: 32bit 符号付き整数 - `i64`: 64bit 符号付き整数(WASMではJSブリッジ注意。Host側はBigInt等) - `f32/f64`: IEEE 754 - `bool`: i32(0/1) -- `string`: UTF-8 `(ptr:i32, len:i32)` -- `array`: `(ptr:i32, len:i32[, cap:i32])`(v0は `(ptr,len)` を優先) -- `boxref`: Opaque(数値ハンドル or ポインタ)。v0では数値 i32 を推奨。 +- `string`: UTF-8 `(ptr:usize, len:usize)` +- `bytes`: バイナリデータ `(ptr:usize, len:usize)` +- `array`: `(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), + Result(Box, Box), + Array(Box), +} +``` アラインメント/境界 -- `ptr` は 4byte アライン推奨(必須ではないが実装が簡潔)。 +- `ptr` は 8byte アライン必須(構造体の効率的アクセス)。 - 範囲外アクセスは未定義ではなく「Hostが防ぐ/検証する」方針(将来、Verifier/境界チェック生成)。 +- プラットフォーム依存: + - Linux x86-64: 8バイト境界 + - WASM MVP: 4バイト境界(互換性のため) 命名規約 - `env.console.log`, `env.canvas.fillRect` のように `..`。 - WASM import 名は `env.console_log` 等の平坦化でも可(生成側で一貫)。 +- プラグイン関数名: `nyash_plugin_*` プレフィックス必須。 エラー/例外 -- v0は例外なし。失敗は整数ステータス or 明示エラーコールバックに委譲(将来)。 +- BID-1標準エラーコード使用(NYB_*)。 +- 失敗は整数ステータスで返却。 +- 例外/シグナルは範囲外。 セキュリティ/権限(将来) - BID に必要権限(console/canvas/storage/net…)を記述。HostはAllowlistで制御(Phase 9.9)。 +実装上の注意点 +- ハンドル再利用/ABA: generation追加で回避 +- スレッド前提: シングルスレッド前提を明記 +- メソッドID衝突: ビルド時固定で回避 +- エラー伝播: トランスポート/ドメインエラー分離 +- 文字列エンコード: UTF-8必須、内部NUL禁止 + ============================================================ BIDサンプル(YAML, 日本語) ============================================================