- Fixed deadlock in FileBox plugin copyFrom implementation (single lock) - Added TLV Handle (tag=8) parsing in calls.rs for returned BoxRefs - Improved plugin loader with config path consistency and detailed logging - Fixed loader routing for proper Handle type_id/fini_method_id resolution - Added detailed logging for TLV encoding/decoding in plugin_loader_v2 Test docs/examples/plugin_boxref_return.nyash now works correctly: - cloneSelf() returns FileBox Handle properly - copyFrom(Box) accepts plugin Box arguments - Both FileBox instances close and fini correctly 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
4.7 KiB
4.7 KiB
Gemini先生によるNyashプラグインシステム深層分析 (2025-08-17)
概要
Nyashプログラミング言語のプラグインシステム設計について、時間無制限で深い分析を実施。「Everything is a Box」哲学を維持しながら、透過的な置き換えと高いメンテナンス性を実現する具体的な実装提案。
1. 透過的な置き換えの最良実装方法
提案:Boxファクトリレジストリ + 設定ファイルによるオーバーライド
アーキテクチャ:
// src/runtime/box_registry.rs
enum BoxFactory {
Builtin(fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>),
Plugin(PluginFactory),
}
struct PluginFactory {
plugin_id: PluginId,
function_name: String, // 例: "filebox_open"
}
設定ファイル(nyash.toml):
[plugins]
enable = ["nyash-file-plugin"]
[overrides]
"FileBox" = "nyash-file-plugin" # FileBoxをプラグイン版で置き換え
実行時フロー:
- ランタイム起動時、全ビルトインBoxをレジストリに登録
- nyash.tomlを読み込み、overridesに従ってレジストリを更新
new FileBox()実行時、レジストリから適切なファクトリを検索・実行
パフォーマンス: HashMap検索1回のみ、その後は通常のdyn NyashBoxディスパッチ
2. 署名DSLの設計の妥当性
分析::: (静的) と # (インスタンス) の記法は優秀
拡張提案:
apis:
# オーバーロード対応
- sig: "FileBox::open(path: string) -> FileBox"
- sig: "FileBox::open(path: string, mode: string) -> FileBox"
# Result型対応
- sig: "FileBox::open(path: string) -> Result<FileBox, FileError>"
# 複数の戻り値型
- sig: "FileBox#read() -> string"
- sig: "FileBox#read(size: int) -> bytes"
将来性:
- 現時点:具象型で固定
- 将来:
Array<T>のようなジェネリクス構文を後方互換性を保ちつつ追加
3. Everything is a Box哲学との整合性
提案:FFI境界の標準化されたBoxプロキシ
// src/runtime/plugin_box.rs
pub struct PluginBox {
base: BoxBase,
plugin_id: PluginId,
instance_handle: u64, // プラグイン内のインスタンスハンドル
}
impl NyashBox for PluginBox {
fn clone_box(&self) -> Box<dyn NyashBox> {
// FFI呼び出しでプラグインにcloneを依頼
let new_handle = ffi_call(self.plugin_id, "clone", self.instance_handle);
Box::new(PluginBox { ..., instance_handle: new_handle })
}
// 全てのNyashBoxメソッドをFFI経由で実装
}
保証される点:
- 統一インターフェース:dyn NyashBoxのみを扱う
- メモリ管理:Drop時にプラグイン側に破棄を通知
- 哲学の維持:内部実装(ネイティブ/FFI)は完全に隠蔽
4. 実装の複雑さとメンテナンス性のバランス
提案:多層抽象化とツールによる自動化
3層アーキテクチャ:
-
低レベルFFI (C-ABI)
#[repr(C)]構造体とextern "C"関数- libloadingクレートで動的ライブラリロード
-
中レベルAPI (安全なラッパー)
- nullチェック、文字列変換、エラー処理
- unsafeコードを隔離
-
高レベルAPI (署名DSLとコード生成)
- plugin.yaml → FFIコード自動生成
- cargo-nyash-pluginサブコマンド
ロードマップ:
- フェーズ1:FileBoxで手動実装、アーキテクチャ確立
- フェーズ2:コード生成ツール開発、プラグイン開発の自動化
5. 他言語の成功例との比較
Node.js (N-API):
- 安定したABI → Nyashも同様にC-ABIベースで実装
- バージョン管理と前方互換性を重視
Python (C拡張):
- 課題:手作業多い、参照カウント管理が煩雑
- Nyashの解決:コード生成とRAIIによる自動メモリ管理
WebAssembly Component Model:
- 言語非依存インターフェースの未来形
- 将来的にNyashプラグインをWASMで記述する可能性
実装計画(具体的ステップ)
- nyash.toml仕様策定とパーサー実装
- Boxファクトリレジストリ実装
- FileBoxプラグイン手動実装
- nyash_plugin_init
- filebox_open
- filebox_read/write/close
- filebox_drop
- PluginBoxプロキシ実装
- libloadingで動的ロード実装
- プラグイン版FileBoxテスト追加
結論
この設計は、Nyashの核心哲学を尊重しつつ、スケーラビリティ、安全性、開発者体験の向上を実現する。FileBoxの置き換えから始め、エコシステム全体へ展開していくのが最良の道筋。