selfhost(pyvm): MiniVmPrints – prefer JSON route early-return (ok==1) to avoid fallback loops; keep default behavior unchanged elsewhere

This commit is contained in:
Selfhosting Dev
2025-09-22 07:54:25 +09:00
parent 27568eb4a6
commit 8e4cadd349
348 changed files with 9981 additions and 30074 deletions

View File

@ -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成果**: プラグインシステムとの完全統合

View File

@ -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プラグイン化

View File

@ -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)

View File

@ -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.

View File

@ -1,109 +0,0 @@
# プラグインBoxのライフサイクルv2と nyash.toml 定義
本書は、プラグインBoxPluginBoxV2の生成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, ...)` を呼びます。
- プラグインBoxPluginBoxV2:
- すべての参照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. WASMwasm-bindgenとの関係
- WASMターゲットでは `libloading` が使えないため、プラグイン機構は features/cfg でスタブ化しています。
- `plugins` フィーチャを外す、または `target_arch = "wasm32"` のときは、プラグイン生成・fini 呼び出しのコードはコンパイル対象外になります(ビルド可能化のため)。
---
## 6. 将来拡張の方向
- ローカル変数のスコープ終了時(関数/メソッド呼び出しの戻りなどに、InstanceBox/PluginBoxV2 の fini を安全に呼び出す仕組み(順序・例外耐性・二重呼び出し防止を含む)。
- `nyash.toml` にクラス名→プラグインBox型の `overrides` を加え、ユーザー定義Boxの外部置換を許可する設計任意
以上。
---
## 7. v2.1: BoxRefBox引数サポート
目的: プラグインメソッドの引数として、他の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)で検討。