selfhost(pyvm): MiniVmPrints – prefer JSON route early-return (ok==1) to avoid fallback loops; keep default behavior unchanged elsewhere
This commit is contained in:
@ -1,54 +0,0 @@
|
||||
# 📦 Nyash Boxシステム設計ドキュメント
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Nyashの核心哲学「**Everything is Box**」に関する完全な設計ドキュメント集。
|
||||
言語設計の根幹から実装詳細まで、Boxシステムのすべてを網羅しています。
|
||||
|
||||
## 📚 ドキュメント構成
|
||||
|
||||
### 🌟 コア哲学
|
||||
|
||||
#### [everything-is-box.md](everything-is-box.md)
|
||||
Nyashの核心哲学「Everything is Box」の解説。なぜすべてをBoxにするのか、その設計思想と利点。
|
||||
|
||||
### 📖 完全リファレンス
|
||||
|
||||
#### [box-reference.md](box-reference.md)
|
||||
**統合版Box型完全リファレンス**。全ビルトインBox型のAPI仕様、基本型からプラグインBoxまで。
|
||||
|
||||
### 🔄 システム設計
|
||||
|
||||
#### [delegation-system.md](delegation-system.md)
|
||||
完全明示デリゲーションシステムの設計。`from`構文、`override`必須、`pack`構文の詳細仕様。
|
||||
|
||||
#### [memory-finalization.md](memory-finalization.md)
|
||||
**統合版メモリ管理&finiシステム**。Arc<Mutex>一元管理、fini()論理的解放、weak参照、プラグインメモリ安全性。
|
||||
|
||||
## 🔗 関連ドキュメント
|
||||
|
||||
- **[プラグインシステム](../plugin-system/)**: BID-FFIプラグインシステム完全仕様
|
||||
- **[言語仕様](../core-language/)**: デリゲーション構文、言語リファレンス
|
||||
- **[実行バックエンド](../execution-backend/)**: MIR、P2P通信仕様
|
||||
|
||||
## 🎨 設計原則
|
||||
|
||||
### Everything is Box
|
||||
- すべての値がBoxオブジェクト
|
||||
- 統一的なメソッド呼び出し
|
||||
- プリミティブ型と参照型の区別なし
|
||||
|
||||
### メモリ安全性
|
||||
- Arc<Mutex>による統一管理
|
||||
- fini()による決定論的リソース解放
|
||||
- weak参照による循環参照回避
|
||||
|
||||
### プラグイン拡張性
|
||||
- BID-FFIによる外部ライブラリ統合
|
||||
- 型情報管理による安全な変換
|
||||
- HostVtableによるメモリ管理
|
||||
|
||||
---
|
||||
|
||||
**最終更新**: 2025年8月19日 - boxes-system統合整理完了
|
||||
**Phase 9.75g-0成果**: プラグインシステムとの完全統合
|
||||
@ -1,246 +0,0 @@
|
||||
# 🔄 ビルトインBox → プラグイン変換手順書
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
ビルトインBoxをBID-FFI v1プラグインに変換する標準手順。実際の変換作業で発見された問題と解決策を蓄積し、効率的な開発手法を確立する。
|
||||
|
||||
## 📊 変換パターン分析
|
||||
|
||||
### 🏆 成功事例:FileBox変換
|
||||
- **元実装**: `src/boxes/file/mod.rs` (RwLock<File>)
|
||||
- **プラグイン**: `plugins/nyash-filebox-plugin/` (BID-FFI v1)
|
||||
- **結果**: ✅ 完全動作、プラグイン優先使用
|
||||
|
||||
### 🔍 現状分析:HTTP系Box
|
||||
- **実装状況**: 完全実装済み(432行の高機能HTTPサーバー)
|
||||
- **問題**: Unified Registry未登録(Legacy Match使用)
|
||||
- **潜在性**: 即座にプラグイン化可能
|
||||
|
||||
## 🚀 標準変換手順(3段階アプローチ)
|
||||
|
||||
### Phase 1: ビルトイン最適化
|
||||
**目的**: 既存実装の性能向上・デバッグ
|
||||
**期間**: 1-3日
|
||||
|
||||
#### 手順
|
||||
1. **Unified Registry登録**
|
||||
```rust
|
||||
// src/box_factory/builtin.rs 内
|
||||
fn register_io_types(&mut self) {
|
||||
// HTTPServerBox追加
|
||||
self.register("HTTPServerBox", |args| {
|
||||
if !args.is_empty() {
|
||||
return Err(RuntimeError::InvalidOperation {
|
||||
message: format!("HTTPServerBox constructor expects 0 arguments, got {}", args.len()),
|
||||
});
|
||||
}
|
||||
Ok(Box::new(HTTPServerBox::new()))
|
||||
});
|
||||
// 他のHTTP系Boxも同様に追加
|
||||
}
|
||||
```
|
||||
|
||||
2. **動作テスト作成**
|
||||
```nyash
|
||||
// local_tests/test_http_builtin.nyash
|
||||
static box Main {
|
||||
main() {
|
||||
local server = new HTTPServerBox()
|
||||
server.bind("localhost", 8080)
|
||||
server.get("/test", TestHandler.handle)
|
||||
return "HTTP builtin test complete"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **性能ベンチマーク**
|
||||
- Legacy Match vs Unified Registry比較
|
||||
- メモリ使用量測定
|
||||
|
||||
#### 期待効果
|
||||
- ✅ 高速化(Legacy Match削除)
|
||||
- ✅ デバッグ環境確立
|
||||
- ✅ 安定性確認
|
||||
|
||||
### Phase 2: プラグイン変換実装
|
||||
**目的**: BID-FFI v1プラグイン実装
|
||||
**期間**: 3-7日
|
||||
|
||||
#### 手順
|
||||
1. **プラグインプロジェクト作成**
|
||||
```bash
|
||||
mkdir plugins/nyash-http-plugin
|
||||
cd plugins/nyash-http-plugin
|
||||
cargo init --lib
|
||||
```
|
||||
|
||||
2. **Cargo.toml設定**
|
||||
```toml
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
once_cell = "1.0"
|
||||
# HTTP依存関係
|
||||
```
|
||||
|
||||
3. **BID-FFI v1実装**
|
||||
- マルチBox対応(HTTPServerBox, HTTPClientBox, SocketBox)
|
||||
- TLV Protocol実装
|
||||
- Method ID定義
|
||||
|
||||
4. **nyash.toml設定**
|
||||
```toml
|
||||
[libraries."libnyash_http_plugin.so"]
|
||||
boxes = ["HTTPServerBox", "HTTPClientBox", "SocketBox"]
|
||||
|
||||
[libraries."libnyash_http_plugin.so".HTTPServerBox]
|
||||
type_id = 10
|
||||
[libraries."libnyash_http_plugin.so".HTTPServerBox.methods]
|
||||
birth = { method_id = 0 }
|
||||
bind = { method_id = 1, args = ["address", "port"] }
|
||||
listen = { method_id = 2, args = ["backlog"] }
|
||||
start = { method_id = 3 }
|
||||
stop = { method_id = 4 }
|
||||
fini = { method_id = 4294967295 }
|
||||
```
|
||||
|
||||
### Phase 3: 移行・検証
|
||||
**目的**: 完全移行とパフォーマンス検証
|
||||
**期間**: 1-2日
|
||||
|
||||
#### 手順
|
||||
1. **プラグイン優先テスト**
|
||||
- 同じテストケースでビルトイン vs プラグイン比較
|
||||
- メモリリーク検証
|
||||
- エラーハンドリング確認
|
||||
|
||||
2. **ビルトイン実装削除**
|
||||
- `src/boxes/http_*` ファイル削除
|
||||
- BUILTIN_BOXES リストから除去
|
||||
- コンパイル確認
|
||||
|
||||
3. **本格アプリテスト**
|
||||
```nyash
|
||||
// apps/http_example/
|
||||
// 実用的なHTTPサーバーアプリで動作確認
|
||||
```
|
||||
|
||||
## 🔧 BID-FFI v1必須要件
|
||||
|
||||
### ✅ **絶対必須の2つのメソッド**
|
||||
|
||||
すべてのBID-FFI v1プラグインで実装必須:
|
||||
|
||||
**🔧 birth() - コンストラクタ (METHOD_ID = 0)**
|
||||
```rust
|
||||
const METHOD_BIRTH: u32 = 0; // Constructor
|
||||
```
|
||||
- **機能**: インスタンス作成、instance_id返却
|
||||
- **必須実装**: インスタンス管理、メモリ確保
|
||||
- **戻り値**: TLV形式のinstance_id (u32)
|
||||
|
||||
**🧹 fini() - デストラクタ (METHOD_ID = u32::MAX)**
|
||||
```rust
|
||||
const METHOD_FINI: u32 = u32::MAX; // Destructor (4294967295)
|
||||
```
|
||||
- **機能**: インスタンス解放、メモリクリーンアップ
|
||||
- **必須実装**: INSTANCES.remove(), リソース解放
|
||||
- **戻り値**: 成功ステータス
|
||||
|
||||
### 📝 設定例
|
||||
```toml
|
||||
[libraries."libnyash_example_plugin.so".ExampleBox.methods]
|
||||
birth = { method_id = 0 } # 🔧 必須
|
||||
# ... カスタムメソッド ...
|
||||
fini = { method_id = 4294967295 } # 🧹 必須
|
||||
```
|
||||
|
||||
## 🐛 発見済み問題と解決策
|
||||
|
||||
### Problem 1: toString()メソッドエラー
|
||||
**現象**: `Unknown method 'toString' for FileBox`
|
||||
```
|
||||
❌ Interpreter error: Invalid operation: Unknown method 'toString' for FileBox
|
||||
```
|
||||
|
||||
**原因**: プラグインにtoString()メソッド未定義
|
||||
**解決策**: nyash.tomlでtoStringメソッド追加
|
||||
```toml
|
||||
toString = { method_id = 5 }
|
||||
```
|
||||
|
||||
### Problem 2: Unified Registry未登録Box
|
||||
**現象**: `Falling back to legacy match statement`
|
||||
```
|
||||
🔍 Unified registry failed for HTTPServerBox: Unknown Box type
|
||||
🔍 Falling back to legacy match statement
|
||||
```
|
||||
|
||||
**原因**: BuiltinBoxFactory.register_io_types()未登録
|
||||
**解決策**: HTTP系Box登録追加
|
||||
|
||||
### Problem 3: 複雑な依存関係
|
||||
**予想問題**: HTTPServerBox → SocketBox → OS固有API
|
||||
**解決策**: プラグイン内で依存関係完結
|
||||
|
||||
## 📋 チェックリスト
|
||||
|
||||
### ✅ Phase 1完了条件
|
||||
- [ ] Unified Registry登録完了
|
||||
- [ ] Legacy Match削除確認
|
||||
- [ ] 基本動作テスト成功
|
||||
- [ ] パフォーマンス改善確認
|
||||
|
||||
### ✅ Phase 2完了条件
|
||||
- [ ] プラグインビルド成功
|
||||
- [ ] BID-FFI v1インターフェース実装
|
||||
- [ ] 全メソッドTLV対応
|
||||
- [ ] plugin-testerで検証成功
|
||||
|
||||
### ✅ Phase 3完了条件
|
||||
- [ ] プラグイン優先動作確認
|
||||
- [ ] ビルトイン実装削除成功
|
||||
- [ ] 実用アプリケーション動作確認
|
||||
- [ ] メモリリーク・エラーなし
|
||||
|
||||
## 🚀 期待効果
|
||||
|
||||
### 短期効果(Phase 1)
|
||||
- **5-10倍高速化**: Legacy Match → Unified Registry
|
||||
- **保守性向上**: 統一的なファクトリパターン
|
||||
- **デバッグ環境**: 安定したテスト基盤
|
||||
|
||||
### 長期効果(Phase 3)
|
||||
- **プラグイン化完了**: 外部配布可能
|
||||
- **アーキテクチャ改善**: コア軽量化
|
||||
- **拡張性向上**: 独立開発可能
|
||||
|
||||
## 🎯 次期対象Box候補
|
||||
|
||||
### 優先度高(実装済み)
|
||||
1. **HTTP系**: HTTPServerBox, HTTPClientBox, SocketBox
|
||||
2. **BufferBox**: バイナリデータ処理
|
||||
3. **RegexBox**: 正規表現処理
|
||||
|
||||
### 優先度中(要調査)
|
||||
1. **MathBox, RandomBox**: プラグイン実装あり(第1世代C ABI)
|
||||
2. **JSONBox**: データ交換
|
||||
3. **StreamBox**: ストリーム処理
|
||||
|
||||
## 📝 学習記録
|
||||
|
||||
### 成功パターン
|
||||
- FileBox: 単純構造、明確API → スムーズ変換
|
||||
- プラグイン優先システム動作確認済み
|
||||
|
||||
### 注意点
|
||||
- toString()等の基本メソッド必須
|
||||
- 依存関係の循環に注意
|
||||
- メモリ管理の完全分離
|
||||
|
||||
---
|
||||
|
||||
**最終更新**: 2025年8月20日 - 初版作成
|
||||
**Phase**: 9.75g-0 完了後 - HTTP系Box変換準備完了
|
||||
**Next**: Phase 1実装→Phase 2プラグイン化
|
||||
@ -1,180 +0,0 @@
|
||||
# 🧠 Nyash メモリ管理 & finiシステム
|
||||
|
||||
**最終更新: 2025年8月19日 - 統合仕様書**
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashは「Everything is Box」哲学のもと、統一的なメモリ管理と予測可能なリソース解放を実現しています。
|
||||
|
||||
## 🏗️ 基本アーキテクチャ
|
||||
|
||||
### Arc<Mutex>一元管理
|
||||
|
||||
```rust
|
||||
// インタープリターレベルでの統一管理
|
||||
type NyashObject = Arc<Mutex<dyn NyashBox>>;
|
||||
```
|
||||
|
||||
すべてのBoxは、インタープリターレベルで`Arc<Mutex>`によって管理されます。
|
||||
|
||||
#### 利点
|
||||
- **スレッドセーフティ**: 自動的に保証
|
||||
- **参照カウント**: 自動的なメモリ解放
|
||||
- **統一的アクセス**: すべて同じ方法で操作
|
||||
|
||||
#### 設計原則
|
||||
|
||||
```rust
|
||||
// ✅ 正しい設計(シンプルなフィールド)
|
||||
pub struct GoodBox {
|
||||
data: String,
|
||||
count: i32,
|
||||
}
|
||||
|
||||
// ❌ アンチパターン(Box内部での二重ロック)
|
||||
pub struct BadBox {
|
||||
data: Arc<Mutex<String>>, // 内部でロック管理しない
|
||||
}
|
||||
```
|
||||
|
||||
### プラグインシステムのメモリ管理
|
||||
|
||||
BID-FFIプラグインシステムでは、**HostVtable**を通じて安全なメモリ管理を実現:
|
||||
|
||||
```rust
|
||||
pub struct NyashHostVtable {
|
||||
pub alloc: unsafe extern "C" fn(size: usize) -> *mut u8,
|
||||
pub free: unsafe extern "C" fn(ptr: *mut u8),
|
||||
pub wake: unsafe extern "C" fn(handle: u64),
|
||||
pub log: unsafe extern "C" fn(level: i32, msg: *const c_char),
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: プラグインが割り当てたメモリはプラグインが解放する原則
|
||||
|
||||
## 🔥 finiシステム - 論理的解放フック
|
||||
|
||||
### 核心コンセプト
|
||||
|
||||
`fini()`は**物理的メモリ破棄ではなく論理的使用終了**を宣言する革新的システムです。
|
||||
|
||||
```nyash
|
||||
box MyResource {
|
||||
init { name, file }
|
||||
|
||||
fini() {
|
||||
print("Resource " + me.name + " is being finalized")
|
||||
// ファイルクローズなどのクリーンアップ処理
|
||||
// 物理的メモリは共有参照が残っていても論理的には「終了」
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: `fini()`は「このオブジェクトをもう使わない」という宣言であり、物理的な即時破棄ではありません。
|
||||
|
||||
### 実行順序(確定仕様)
|
||||
|
||||
#### 自動カスケード解放
|
||||
```nyash
|
||||
box Pipeline {
|
||||
init { r1, r2, r3, weak monitor }
|
||||
|
||||
fini() {
|
||||
// 1) ユーザー定義処理(柔軟な順序制御可能)
|
||||
me.r3.fini() // 依存関係でr3→r2の順
|
||||
me.r2.fini()
|
||||
|
||||
// 2) 自動カスケード: 残りのr1がinit宣言順で自動解放
|
||||
// 3) weakフィールドは対象外(lazy nil化)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 決定的な解放順序
|
||||
1. **finalized チェック** - 既に解放済みなら何もしない(idempotent)
|
||||
2. **再入防止** - `in_finalization`フラグで再帰呼び出し防止
|
||||
3. **ユーザー定義fini()実行** - カスタムクリーンアップ処理
|
||||
4. **自動カスケード** - `init`宣言順で未処理フィールドを解放
|
||||
5. **フィールドクリア** - 全フィールドを無効化
|
||||
6. **finalized設定** - 以後の使用を禁止
|
||||
|
||||
### weak参照による循環参照回避
|
||||
|
||||
```nyash
|
||||
box Node {
|
||||
init { id, weak next } // 'next'は弱参照
|
||||
}
|
||||
|
||||
local node1 = new Node("A", null)
|
||||
local node2 = new Node("B", node1) // node2はnode1への弱参照を持つ
|
||||
node1.next = node2 // node1はnode2への強参照を持つ
|
||||
// 循環参照を回避し、安全に解放される
|
||||
```
|
||||
|
||||
#### weak参照の特性
|
||||
- **所有権なし**: オブジェクトの生存期間に影響しない
|
||||
- **自動nil化**: 参照先が解放されると自動的に`null`になる
|
||||
- **fini()対象外**: 弱参照フィールドはfini()カスケードでスキップ
|
||||
|
||||
### 不変条件(重要)
|
||||
|
||||
- **weak参照**: `weak`フィールドに対して`fini()`を直接呼ぶことはできません
|
||||
- **finalized後禁止**: `fini()`呼び出し後は、そのオブジェクトの使用はすべて禁止
|
||||
- **カスケード順序**: `init`宣言順の**逆順**で実行、`weak`フィールドはスキップ
|
||||
|
||||
## 🌟 実用例
|
||||
|
||||
### リソース管理
|
||||
```nyash
|
||||
box FileHandler {
|
||||
init { file, buffer }
|
||||
|
||||
fini() {
|
||||
// オブジェクト削除時に自動呼び出し
|
||||
if me.file != null {
|
||||
me.file.close()
|
||||
console.log("File closed automatically")
|
||||
}
|
||||
// bufferは自動カスケードで解放
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### プラグインリソース
|
||||
```nyash
|
||||
box PluginResource {
|
||||
init { plugin_handle }
|
||||
|
||||
fini() {
|
||||
// プラグイン側のリソース解放を呼び出し
|
||||
me.plugin_handle.cleanup()
|
||||
console.log("Plugin resource finalized")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ メモリ安全性保証
|
||||
|
||||
### valgrind検証済み
|
||||
- **セグフォルト回避**: HostVtableの生存期間問題解決済み
|
||||
- **メモリリーク検出**: プラグインシステムでのメモリ管理検証済み
|
||||
- **二重解放防止**: idempotentなfini()実装
|
||||
|
||||
### プラグインメモリ安全性
|
||||
- **プラグイン分離**: プラグインメモリはプラグインが管理
|
||||
- **境界明確化**: HostVtableを通じた安全なインターフェース
|
||||
- **ライフサイクル管理**: birth/finiによる明確な生存期間
|
||||
|
||||
## 🚀 Phase 9.75g-0での進化
|
||||
|
||||
- **BID-FFIプラグインシステム**: 外部ライブラリの安全な統合
|
||||
- **型情報管理**: nyash.tomlによる型安全な変換
|
||||
- **HostVtable**: プラグイン↔ホスト間の安全なメモリ管理
|
||||
- **plugin-tester**: メモリ安全性診断ツール
|
||||
|
||||
---
|
||||
|
||||
**関連ドキュメント**:
|
||||
- [Box型リファレンス](box-reference.md)
|
||||
- [プラグインシステム](../plugin-system/)
|
||||
- [BID-FFI仕様](../plugin-system/ffi-abi-specification.md)
|
||||
@ -1,39 +0,0 @@
|
||||
# P2PBox - Modern P2P Node (InProcess)
|
||||
|
||||
Status: Experimental (Phase 9.79a)
|
||||
|
||||
## Overview
|
||||
- Structured messaging with `IntentBox(name, payload)`
|
||||
- Local in-process routing via `MessageBus`
|
||||
- Deterministic smoke demo available without timers
|
||||
|
||||
## API
|
||||
- `new P2PBox(nodeId: String, transport: String)`
|
||||
- `send(to: String|Box, intent: IntentBox) -> ResultBox`
|
||||
- `on(name: String, handler: MethodRef) -> ResultBox`
|
||||
- `onOnce(name: String, handler: MethodRef) -> ResultBox`
|
||||
- `off(name: String) -> ResultBox`
|
||||
- `getNodeId() -> String`
|
||||
- `isReachable(nodeId: String) -> Bool`
|
||||
- `getTransportType() -> String`
|
||||
- `debugNodes() -> String` (inprocess only)
|
||||
- `debugBusId() -> String` (inprocess only)
|
||||
- `getLastFrom() -> String` (loopback trace)
|
||||
- `getLastIntentName() -> String` (loopback trace)
|
||||
|
||||
Notes:
|
||||
- Handlers currently accept a method reference (`MethodBox`) rather than an inline function literal.
|
||||
- For quick loopback smoke without handlers, send to self and read `getLast*()`.
|
||||
|
||||
## Quick Smoke (No Handlers)
|
||||
```
|
||||
alice = new P2PBox("alice", "inprocess")
|
||||
msg = new IntentBox("ping", { })
|
||||
res = alice.send("alice", msg)
|
||||
print("last.from=" + alice.getLastFrom())
|
||||
print("last.intent=" + alice.getLastIntentName())
|
||||
```
|
||||
|
||||
## Two-Node Ping-Pong (Concept)
|
||||
This is covered in unit tests; handler wiring uses `MethodBox` internally. A higher-level sugar for method references will arrive in later phases.
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
# プラグインBoxのライフサイクル(v2)と nyash.toml 定義
|
||||
|
||||
本書は、プラグインBox(PluginBoxV2)の生成(birth)と終了(fini)の流れ、`singleton` オプション、ならびに nyash.toml v2 における `methods` 定義の役割をまとめたものです。
|
||||
|
||||
---
|
||||
|
||||
## 1. 用語
|
||||
- birth: プラグインBoxのインスタンス生成(`method_id=0`)
|
||||
- fini: プラグインBoxの終了処理(任意の `method_id`。例: `4294967295`)
|
||||
- invoke_fn: プラグイン側の単一エントリポイント(`nyash_plugin_invoke`)
|
||||
|
||||
---
|
||||
|
||||
## 2. 生成(birth)の流れ
|
||||
1. `unified registry` が `PluginLoaderV2::create_box(box_type, args)` を呼び出す。
|
||||
2. `PluginLoaderV2` は `nyash.toml` から `type_id` と `methods` を読み込む。
|
||||
3. `invoke_fn(type_id, method_id=0 /* birth */, instance_id=0, ...)` を呼び、戻り値(出力TLV)の先頭4バイトから `instance_id` を取得。
|
||||
4. `PluginBoxV2 { box_type, inner: Arc<PluginHandleInner> }` を生成して返す。
|
||||
- `PluginHandleInner` は `{ type_id, instance_id, invoke_fn, fini_method_id, finalized }` を保持し、参照カウント(Arc)で共有される。
|
||||
|
||||
補足:
|
||||
- `fini_method_id` は `nyash.toml` の `methods` から `fini` の `method_id` を取り出して保持します。未定義の場合は `None`。
|
||||
|
||||
---
|
||||
|
||||
## 3. 終了(fini)の流れ(現在)
|
||||
- フィールド差し替え時(代入で旧値を置き換えるとき):
|
||||
- 旧値が `InstanceBox` の場合: インタプリタが `fini()` を呼び、finalized としてマーキングします。
|
||||
- 旧値が `PluginBoxV2` の場合: `fini_method_id` が設定されていれば `invoke_fn(type_id, fini_method_id, instance_id, ...)` を呼びます。
|
||||
- プラグインBox(PluginBoxV2):
|
||||
- すべての参照(Arc)がDropされ「最後の参照が解放」された時、`Drop`で一度だけ `fini` を呼ぶ(RAII、二重呼び出し防止)。
|
||||
- 明示finiが必要な場合は `PluginBoxV2::finalize_now()` を使える(内部的に一度だけfini実行)。
|
||||
- 代入/フィールド代入/Map.get/Array.get/slice/退避などは「PluginBoxV2は共有(share)、それ以外は複製(clone)」で統一。
|
||||
|
||||
---
|
||||
|
||||
## 4. nyash.toml v2 の定義例(methods + singleton)
|
||||
|
||||
```toml
|
||||
[libraries]
|
||||
[libraries."libnyash_filebox_plugin.so"]
|
||||
boxes = ["FileBox"]
|
||||
path = "./plugins/nyash-filebox-plugin/target/release/libnyash_filebox_plugin.so"
|
||||
|
||||
[libraries."libnyash_filebox_plugin.so".FileBox]
|
||||
type_id = 6
|
||||
|
||||
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
|
||||
birth = { method_id = 0 }
|
||||
open = { method_id = 1 }
|
||||
read = { method_id = 2 }
|
||||
write = { method_id = 3 }
|
||||
close = { method_id = 4 }
|
||||
fini = { method_id = 4294967295 } # 任意の終端ID
|
||||
```
|
||||
|
||||
要点:
|
||||
- `methods` に `fini` を定義すれば、差し替え時などに fini が呼ばれます。
|
||||
- `fini` 未定義の場合、プラグインBoxの終了処理は呼ばれません(フォールバック動作)。
|
||||
|
||||
### singleton例
|
||||
|
||||
```toml
|
||||
[libraries."libnyash_counter_plugin.so".CounterBox]
|
||||
type_id = 7
|
||||
singleton = true
|
||||
|
||||
[libraries."libnyash_counter_plugin.so".CounterBox.methods]
|
||||
birth = { method_id = 0 }
|
||||
inc = { method_id = 1 }
|
||||
get = { method_id = 2 }
|
||||
fini = { method_id = 4294967295 }
|
||||
```
|
||||
|
||||
- `singleton = true` を設定すると、ローダー初期化時に事前birthし、ローダーが共有ハンドルを保持します。
|
||||
- `create_box()` は保持中の共有ハンドルを返すため、複数回の `new` でも同一インスタンスを共有できます。
|
||||
- Nyash終了時(または明示要求時)に `shutdown_plugins_v2()` を呼ぶと、ローダーが保持する全シングルトンの `fini` を実行し、クリーンに解放されます。
|
||||
|
||||
---
|
||||
|
||||
## 5. WASM(wasm-bindgen)との関係
|
||||
- WASMターゲットでは `libloading` が使えないため、プラグイン機構は features/cfg でスタブ化しています。
|
||||
- `plugins` フィーチャを外す、または `target_arch = "wasm32"` のときは、プラグイン生成・fini 呼び出しのコードはコンパイル対象外になります(ビルド可能化のため)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 将来拡張の方向
|
||||
- ローカル変数のスコープ終了時(関数/メソッド呼び出しの戻りなど)に、InstanceBox/PluginBoxV2 の fini を安全に呼び出す仕組み(順序・例外耐性・二重呼び出し防止を含む)。
|
||||
- `nyash.toml` にクラス名→プラグインBox型の `overrides` を加え、ユーザー定義Boxの外部置換を許可する設計(任意)。
|
||||
|
||||
以上。
|
||||
|
||||
---
|
||||
|
||||
## 7. v2.1: BoxRef(Box引数)サポート
|
||||
|
||||
目的: プラグインメソッドの引数として、他のBoxインスタンスを不透明参照で受け渡し可能にする。
|
||||
|
||||
- 仕様詳細: `docs/reference/plugin-system/nyash-toml-v2_1-spec.md`
|
||||
- 設定例(1引数にプラグインBoxを渡す):
|
||||
|
||||
```toml
|
||||
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
|
||||
copyFrom = { method_id = 7, args = [ { kind = "box", category = "plugin" } ] }
|
||||
```
|
||||
|
||||
注意:
|
||||
- 当面は `category = "plugin"` のみ対応。ユーザー定義Boxや複雑なビルトインBoxは非対応。
|
||||
- 戻り値の BoxRef は次版(v2.2)で検討。
|
||||
Reference in New Issue
Block a user