# Dynamic Plugin Flow (VM × Registry × PluginLoader v2)

最終更新: 2025-08-23

目的
- Nyash 実行時に、MIR→VM→Registry→Plugin の呼び出しがどう流れるかを図解・手順で把握する。
- TLVエンコード、ResultBoxの扱い、Handleのライフサイクル、nyash.tomlとの連携を1枚で理解する。

## ハイレベル流れ（シーケンス）

```
Nyash Source ──▶ MIR (Builder)
                  │  (BoxCall/NewBox/…)
                  ▼
               VM Executor
                  │  (BoxCall dispatch)
                  ├─ InstanceBox → Lowered MIR 関数呼び出し
                  ├─ BuiltinBox  → VM内ディスパッチ
                  └─ PluginBoxV2 → PluginLoader v2
                                  │  (nyash.toml を参照)
                                  ▼
                           Invoke (TLV)
                                  │
                                  ▼
                           Plugin (lib*.so)
                                  │  (戻り値をTLVで返却)
                                  ▼
                           Loader でデコード
                                  │  (returns_result/Handle/型)
                                  ▼
                           NyashBox (ResultBox/PluginBoxV2/基本型)
                                  │
                                  ▼
                              VM に復帰
```

## 主要構成要素
- MIR: `MirInstruction::{BoxCall, NewBox, …}` で外部呼び出し箇所を明示。
- VM: `src/backend/vm.rs`
  - InstanceBoxは `{Class}.{method}/{argc}` のLowered関数へ呼び出し
  - BuiltinはVM内の簡易ディスパッチ
  - PluginBoxV2は Loader v2 へ委譲
- Registry/Runtime: `NyashRuntime` + `box_registry` + `plugin_loader_v2`
  - `nyash.toml` の `libraries.*` を読み込み、Box名→ライブラリ名、type_id、method_id等を集約

## NewBox（生成）
1) MIRの `NewBox { box_type, args }`
2) VM: `runtime.box_registry` に `box_type` を問い合わせ
3) PluginBoxの場合、Loader v2が `birth(method_id=0)` を TLV で呼び出し
4) Pluginは `type_id` と新規 `instance_id` を返却 → Loader は `PluginBoxV2` を構築
5) VMは `ScopeTracker` に登録（スコープ終了で `fini` を呼ぶ）

## BoxCall（メソッド呼び出し）
- InstanceBox: Lowered関数 `{Class}.{method}/{argc}` を MIR/VM内で実行
- Builtin: VM内の `call_box_method` で対応（StringBox.length 等）
- PluginBoxV2: Loader v2 の `invoke_instance_method` で TLV を組み立てて呼び出し

## TLV（Type-Length-Value）
- ヘッダ: `u16 ver=1`, `u16 argc`
- 各引数: `u8 tag`, `u8 reserved`, `u16 size`, `payload`
- 主な tag:
  - 2 = i32 (size=4)
  - 6 = string, 7 = bytes
  - 8 = Handle(BoxRef) → payload = `u32 type_id || u32 instance_id`
  - 9 = void (size=0)

## 戻り値のマッピング（重要）
- `returns_result=false`
  - tag=8 → PluginBoxV2（Handle）
  - tag=2 → IntegerBox、tag=6/7 → StringBox、tag=9 → void
- `returns_result=true`（ResultBoxで包む）
  - tag=8/2 → `Result.Ok(value)`
  - tag=6/7 → `Result.Err(ErrorBox(message))`（Netプラグインなどがエラー文字列を返却）
  - tag=9 → `Result.Ok(void)`

補足
- VM内で ResultBox の `isOk/getValue/getError` をディスパッチ済み
- `toString()` フォールバックにより任意の Box を安全に文字列化可能

## Handle（BoxRef）のライフサイクル
- Loaderは `(type_id, instance_id)` を `PluginBoxV2` としてラップ
- `share_box()` は同一インスタンス共有、`clone_box()` はプラグインの birth を呼ぶ（設計意図による）
- `fini` は `ScopeTracker` または Drop で保証（プラグインの `fini_method_id` を参照）

## 具体例（HttpClientBox.get）
1) Nyash: `r = cli.get(url)`
2) MIR: `BoxCall`（returns_result=true）
3) VM→Loader: TLV（url = tag=6）
4) Loader→Plugin: `invoke(type_id=HttpClient, method_id=get)`
5) Plugin:
   - 接続成功: `Handle(HttpResponse)` を返す → Loaderは `Result.Ok(PluginBoxV2)`
   - 接続失敗: `String("connect failed …")` を返す → Loaderは `Result.Err(ErrorBox)`
6) Nyash: `if r.isOk() { resp = r.getValue() … } else { print(r.getError().toString()) }`

## nyash.toml 連携
- 例: `libraries."libnyash_net_plugin.so".HttpClientBox.methods.get = { method_id = 1, args=["url"], returns_result = true }`
- Loaderは `method_id` と `returns_result` を参照し、TLVと戻り値のラップ方針を決定
- 型宣言（args/kind）により、引数のTLVタグ検証を実施（不一致は InvalidArgs）

## デバッグTips
- `NYASH_DEBUG_PLUGIN=1`: VM→Plugin の TLV ヘッダと先頭64バイトをプレビュー
- `NYASH_NET_LOG=1 NYASH_NET_LOG_FILE=net_plugin.log`: Netプラグイン内部ログ
- `--dump-mir --mir-verbose`: if/phi/return などのMIRを確認
- `--vm-stats --vm-stats-json`: 命令使用のJSONを取得（hot pathの裏取りに）

## 将来の整合・改善
- nyash.toml に ok側の戻り型（例: `ok_returns = "HttpResponseBox"`）を追加 → Loader判定の厳密化
- Verifier強化: use-before-def across merge の検出（phi誤用を早期に発見）
- BoxCall fast-path の最適化（hot path最優先）

関連
- `docs/reference/plugin-system/net-plugin.md`
- `docs/reference/architecture/mir-to-vm-mapping.md`
- `docs/reference/architecture/mir-26-instruction-diet.md`

See also
- `docs/guides/examples/http_result_patterns.md` - HTTPのResult挙動（unreachable/404/500）のE2E例
- `docs/reference/architecture/vm.md` - VM統計とプラグイン周りの既知制約
