feat: Enhance VM with dynamic type conversion and comprehensive method support

- Add dynamic bool conversion for BoxRef(BoolBox)→bool and BoxRef(VoidBox)→false
- Implement String concatenation with Bool and BoxRef types via toString()
- Add Void/Bool comparison support (Eq/Ne only) to prevent VM crashes
- Implement comprehensive ArrayBox methods in VM:
  - push/pop/length/get/set/remove
  - contains/indexOf/clear/join/sort/reverse/slice
- Implement comprehensive MapBox methods in VM:
  - set/get/has/delete/keys/values/size/clear
- Add SocketBox timeout methods (acceptTimeout/recvTimeout)
- Update VM documentation with all new operations

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-23 18:37:38 +09:00
parent 7c018104a0
commit ff14d489d3
4 changed files with 276 additions and 2 deletions

View File

@ -35,3 +35,46 @@ NYASH_VM_STATS=1 NYASH_VM_STATS_JSON=1 ./target/debug/nyash --backend vm program
```
出力は `total`(総命令数), `elapsed_ms`(経過時間), `counts`(命令種別→回数), `top20`上位20種を含みます。
## 既知の制約とTipsVM×プラグイン
- NetプラグインHTTP
- unreachable接続不可/タイムアウト)は `Result.Err(ErrorBox)`
- HTTP 404/500 は `Result.Ok(Response)`(アプリ側で `response.status` を確認)。
- デバッグ: `NYASH_NET_LOG=1 NYASH_NET_LOG_FILE=net_plugin.log`
- FileBox
- `close()``Ok(Void)``match Ok(_)` で受けるか、戻り値を無視してよい。
- HandleBoxRef戻り
- TLV tag=8type_id:u32, instance_id:u32。Loaderが返り値typeに対応する `fini_method_id` を設定し `PluginBoxV2` を構築。
- `scope_tracker` がスコープ終了時に `fini()` を呼ぶ(メモリ安全)。
- 大きいボディ/多ヘッダー/タイムアウト
- 逐次拡張中。異常時の挙動は上記Result規約に従う。実行ログと `--vm-stats` を併用して診断。
- SocketBoxVM
- 基本API: `bind/listen/accept/connect/read/write/close/isServer/isConnected`
- タイムアウト: `acceptTimeout(ms)` は接続なしで `void``recvTimeout(ms)` は空文字を返す
- 簡易E2E: `local_tests/socket_timeout_server.nyash``socket_timeout_client.nyash`
- Void 比較の扱いVM
- `Void` は値を持たないため、`Eq/Ne` のみ有効。`Void == Void` は真、それ以外の型との `==` は偽(`!=` は真)。
- 順序比較(`<, <=, >, >=`)は `TypeError`
## E2E 実行例HTTPのResult挙動
代表ケースを `tools/run_vm_stats.sh` で実行できます。`--vm-stats-json` により命令プロファイルも取得可能です。
```bash
# 別ターミナルでサーバ起動
./target/release/nyash local_tests/http_server_statuses.nyash
# クライアント(別ターミナル)
tools/run_vm_stats.sh local_tests/vm_stats_http_ok.nyash vm_stats_ok.json
tools/run_vm_stats.sh local_tests/vm_stats_http_404.nyash vm_stats_404.json
tools/run_vm_stats.sh local_tests/vm_stats_http_500.nyash vm_stats_500.json
# 到達不能(サーバ不要)
tools/run_vm_stats.sh local_tests/vm_stats_http_err.nyash vm_stats_err.json
```
期待されるResultモデル
- unreachable接続不可/タイムアウト): `Result.Err(ErrorBox)`
- 404/500 等のHTTPエラー: `Result.Ok(Response)`(アプリ側で `response.status` を評価)
詳細: `docs/reference/architecture/mir-to-vm-mapping.md``docs/examples/http_result_patterns.md` を参照。

View File

@ -15,7 +15,10 @@
- UnaryOp: Partial
- `Neg`(int), `Not`(bool) のみ。`BitNot` は TODO。
- Compare: Partial
- Integer/ String の Eq/Ne/Lt/Le/Gt/Ge 対応。その他型は TypeError
- Integer/ String の Eq/Ne/Lt/Le/Gt/Ge 対応。Bool は Eq/Ne のみ
- Void は値を持たないため、比較は Eq/Ne のみ定義。
- `Void == Void` は true、`Void != Void` は false
- `Void == X` は false、`Void != X` は true順序比較は TypeError
- Load / Store: Implemented
- 現状はVM内の値スロット操作簡易
- Copy: Implemented
@ -23,6 +26,10 @@
## 制御フロー
- Branch / Jump / Return: Implemented
- Branchの条件は `Bool` を期待。以下の動的変換を許容:
- `Integer` → 非ゼロは true
- `BoxRef(BoolBox)` → 中身のbool
- `BoxRef(VoidBox)` → falsenullish false
- Phi: Implemented
- `LoopExecutor` による選択実装前BB情報を利用
@ -75,6 +82,27 @@
---
## Result / Err / HandleBoxRef 取り扱い(重要)
目的: プラグイン呼び出しBoxCall→PluginLoaderV2およびVM内の戻り値で、ResultとBoxRefHandleを正しく扱うための合意事項。
- HTTP系Netプラグインの約束
- unreachable接続不可/タイムアウト等): `Result.Err(ErrorBox)` にマップする。
- HTTP 404/500 等のステータス異常: `Result.Ok(Response)` として返す(アプリ層で扱う)。
- FileBox等のVoid戻り
- `close()` のような副作用のみのメソッドは `Ok(Void)` を返す。VMではVoidの実体は持たない。
- HandleBoxRef戻り値
- プラグインは TLV tag=8Handle`type_id:u32, instance_id:u32` を返す。
- Loader は返り値の `type_id` に対応する正しい `fini_method_id` を設定し、`PluginBoxV2` を生成してVMへ返す。
- 注意: 生成元のBoxと返り値のBoxの型が異なるケースがあるため、「呼び出し元のfini値を流用しない」。必ず返り値 `type_id` を基に解決する。
- Resultの整合
- VMは `Result<T, ErrorBox>` をネイティブ表現し、`match` 等で分岐可能。
- `Ok(Void)``match Ok(_)` と等価に扱えるVoidは値を持たない
参考: TLV/Loader仕様は `docs/reference/plugin-system/ffi-abi-specification.md``plugin-tester.md` を参照。
---
## 既知の課題(抜粋)
- BinOp/UnaryOp/Compare の型拡張浮動小数・Bool/Box等
- ArrayGet/ArraySet の実装。
@ -83,6 +111,11 @@
- WeakRef/Barrier の実体化(必要性評価の上、命令ダイエット候補)。
- PluginBoxV2 のVM側統合強化引数/戻り値のTLV全型対応、Handle戻り値→BoxRef化
Verifier検証に関する追加事項方針
- use-before-def across merge の強化: merge後にphiが未使用/未定義を選択するパスを禁止。
- if-merge の戻り: retはphiのdstを返す実装済み
- TypeOpTypeCheck/Castと命令の整合: Verifierで型注釈に基づく不一致を検出。
## VM統計計測
- `--vm-stats` / `--vm-stats-json` で命令ごとの使用回数と時間(ms)を出力。
- ホット命令抽出によりダイエット候補を定量化。
@ -119,6 +152,11 @@
- Const/NewBoxが次点。定数・生成の最適化定数畳み込み軽量生成・シェアリングが効果的。
- 異常系は早期収束で命令半減。if/phi修正は実戦で有効Branch/Jump/Phiが顕在化
補足HTTP 404/500の比較
- 404"Not Found"、500"Internal Server Error"ともに同一プロファイル合計55命令
- 内訳例: BoxCall: 23 / Const: 16 / NewBox: 12 / BinOp: 2 / Return: 1 / Safepoint: 1
- ステータス差はアプリ層で完結し、VM命令の分布には有意差なし設計の意図どおり
## 26命令ダイエット検討のたたき台
方針: 「命令の意味は保ちつつ集約」。代表案:
- 維持: Const / Copy / Load / Store / BinOp / UnaryOp / Compare / Jump / Branch / Phi / Return / Call / BoxCall / NewBox / ArrayGet / ArraySet