feat(phase-9.75g-0): Implement BID-FFI Day 3 - Box type integration

- Implement BID Box Bridge interface for Nyash Box <-> BID Handle conversion
- Add StringBox BID bridge implementation with handle/TLV support
- Add IntegerBox BID bridge implementation with handle/TLV support
- Implement BoxRegistry for managing Box instances and handles
- Add comprehensive tests for StringBox/IntegerBox BID round-trip
- Extract helper functions for string/integer value extraction

Everything is Box philosophy shines through unified BID integration! 🎉

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-17 19:54:57 +09:00
parent 53f20464b6
commit a5ff3ecafe
9 changed files with 1118 additions and 0 deletions

View File

@ -0,0 +1,91 @@
Nyash BID-FFI実装の型定義ファースト戦略について、特に非同期型の設計に関してレビューをお願いします。
【現在の設計】
phase_9_75g_0_revised_type_first_approach.mdより抜粋
```rust
pub enum BidType {
// 基本型
Bool, I32, I64, F32, F64, String, Bytes,
// 複合型
Array(Box<BidType>), Map(Box<BidType>, Box<BidType>),
Option(Box<BidType>), Result(Box<BidType>, Box<BidType>),
// === 問題のある部分 ===
Future(Box<BidType>), // 非同期結果
Stream(Box<BidType>), // ストリーム
}
```
【懸念点】
1. **Future/StreamはBidTypeに含めるべきか**
- FFI境界でFutureそのものは渡せない
- C ABIは基本的に同期的
- 非同期は実装の詳細であって値の型ではない?
2. **現在のConnection trait設計**
```rust
trait Connection {
fn invoke(&self, ...) -> Result<BidValue, BidError>;
fn invoke_async(&self, ...) -> Result<FutureHandle, BidError>;
fn stream(&self, ...) -> Result<StreamHandle, BidError>;
}
```
【代替案の検討】
案A: メソッドのシェイプで表現
```rust
pub enum MethodShape {
Sync, // 通常の同期呼び出し
Async, // Future<T>を返す
Stream, // Stream<T>を返す
}
pub struct Method {
pub shape: MethodShape, // ここで同期/非同期を区別
pub returns: BidType, // 実際の値の型Future抜き
}
```
案B: ハンドル型として扱う
```rust
pub enum BidType {
// Future/Stream削除
Handle(String), // "FutureHandle", "StreamHandle"等
}
```
案C: 型階層を分ける
```rust
pub enum BidType { /* 値型のみ */ }
pub enum BidAsyncType {
Future(BidType),
Stream(BidType),
}
```
【質問】
1. **型システム設計**
- Future/StreamをBidTypeに含めるのは適切か
- FFI境界での非同期処理の正しい表現方法は
- 値型と実行モデルを混在させることの是非は?
2. **実装戦略**
- 型定義ファースト戦略(全型を最初に定義)は妥当か?
- unimplemented!()での段階的実装は適切か?
- ビルドエラー回避とAPI安定性のトレードオフは
3. **FFI境界での非同期**
- C ABI経由での非同期処理の標準的な方法は
- ポーリング vs コールバック vs ハンドル方式?
- WASM Component Modelではどう扱われている
4. **将来の拡張性**
- gRPC/RESTでの非同期は別の話
- TransportTypeごとに非同期モデルが異なる場合の抽象化は
- Rust async/awaitとの統合方法は
実装者Rust中級者が混乱しない、シンプルで拡張可能な設計を教えてください。特に「Future/StreamはBidTypeに含めるべきか」の判断をお願いします。

View File

@ -0,0 +1,125 @@
Nyash「箱理論」に基づくBID-FFI設計の最終レビューをお願いします。
【Nyashの箱理論Everything is Box
Nyashプログラミング言語は「Everything is Box」哲学を採用しており、すべてのデータと機能がBoxとして統一されています。
既存のBox型:
- StringBox, IntegerBox, BoolBox基本型
- ArrayBox, MapBoxコレクション
- FutureBox非同期処理
- P2PBoxネットワーク
- FileBox将来プラグインで提供予定
【設計の変遷】
1. 最初の設計: 野心的すぎて複雑gRPC/REST/P2P等全部
2. ChatGPT提案: 一般的で正しいが、既存FutureBoxと二重実装になる
3. 最終設計: 箱理論準拠の最低設計
【最終設計案】
```rust
// 1. 型システム:プリミティブ + Handle統一
pub enum BidType {
// プリミティブFFI境界で直接渡せる
Bool, I32, I64, F32, F64, String, Bytes,
// Everything is Box: すべてのBoxは統一Handle
Handle(String), // "StringBox:123", "FileBox:456", "FutureBox:789"
// メタ型
Void,
// Phase 2以降定義だけ
Option(Box<BidType>),
Result(Box<BidType>, Box<BidType>),
Array(Box<BidType>),
}
// 2. 既存Boxとの対応
/*
Handle("StringBox:123") → 既存StringBox インスタンス
Handle("FileBox:456") → プラグインFileBox
Handle("FutureBox:789") → 既存FutureBox非同期
Handle("P2PBox:101") → 既存P2PBox
*/
// 3. 統一エントリーポイント
extern "C" fn nyash_plugin_invoke(
box_type_id: u32, // StringBox=1, FileBox=6等
method_id: u32, // open=1, read=2等
instance_id: u32, // Handle解析用
args_ptr: *const u8,
args_len: usize,
result_ptr: *mut u8,
result_len: *mut usize,
) -> i32
// 4. Boxヘッダー統一
#[repr(C, align(8))]
pub struct BoxHeader {
magic: u32, // "NYBX"
version: u16,
type_id: u32, // BoxTypeId
instance_id: u32, // インスタンス識別子
ref_count: u32, // 非atomicシングルスレッド中心
flags: u32, // 拡張用
}
// 5. 既存Box統合
pub struct NyashBoxRegistry {
instances: HashMap<u32, Arc<RwLock<dyn NyashBox>>>,
}
impl NyashBoxRegistry {
fn call_method(&self, type_id: u32, instance_id: u32, method_id: u32, args: &[u8])
-> Result<Vec<u8>, BidError> {
match type_id {
1 => self.call_stringbox_method(...), // 既存StringBox
6 => self.call_filebox_method(...), // プラグインFileBox
7 => self.call_futurebox_method(...), // 既存FutureBox活用
}
}
}
```
【設計原則】
1. **箱理論準拠**: すべてのBoxが同じ仕組みで扱える
2. **既存資産活用**: FutureBox等の既存実装を最大活用
3. **最低設計**: 動くものを最速で、複雑な機能は後回し
4. **二重実装回避**: 新しいBidFutureではなく既存FutureBox使用
5. **シングルスレッド中心**: Nyashの現実に合わせた設計
【具体的な利点】
- Nyashコード側は変更不要local file = new FileBox("test.txt")
- 既存StringBox, ArrayBox, FutureBoxと新しいプラグインFileBoxが同じ仕組み
- Handle("BoxType:id")による統一的なBox参照
- 非同期はFutureBoxで、新実装不要
【質問】
1. **箱理論の技術的妥当性**
- すべてをHandle統一する設計は適切か
- 既存BoxとプラグインBoxの統一的な扱いは可能か
- FFI境界でのBox参照としてHandle("Type:id")は適切か?
2. **最低設計のメリット・デメリット**
- プリミティブ + Handle のみの設計は十分か?
- 複雑な型Array, Map等を後回しにする判断は
- Phase 1で基本動作、Phase 2で拡張の戦略は妥当か
3. **既存資産活用の是非**
- 新しいBidFutureを作らずFutureBox活用は正解か
- 既存のStringBox等との統合アプローチは適切か
- 二重実装回避 vs 設計の純粋性のトレードオフは?
4. **実装現実性**
- 1週間でのPhase 1実装は現実的か
- 既存インタープリターとの統合難易度は?
- Linux x86-64限定での最初の実装は妥当か
5. **将来拡張性**
- この基盤で将来のgRPC/REST対応は可能か
- Transport抽象化への拡張パスは明確か
- P2PNyaMesh統合への道筋は適切か
「箱理論」という独特な哲学を持つNyashにとって、一般的なFFI設計とは異なる特殊なアプローチが必要だと考えています。この「最低設計から始めて段階的拡張」の戦略についての専門的見解をお願いします。