From 19cfe70df94bae28aca27b334a2b175e65115794 Mon Sep 17 00:00:00 2001 From: Moe Charm Date: Tue, 12 Aug 2025 04:02:19 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20refactor:=20P2PBox=E8=A4=87?= =?UTF-8?q?=E9=9B=91=E5=AE=9F=E8=A3=85=E3=82=92=E5=89=8A=E9=99=A4=E3=81=97?= =?UTF-8?q?=E6=AE=B5=E9=9A=8E=E7=9A=84=E5=AE=9F=E8=A3=85=E6=96=B9=E9=87=9D?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 複雑なP2PBox関連実装を削除: * Transport trait + MessageBus + MessageIntentBox + NewP2PBox * 依存関係が複雑で一度に追加すると失敗することを学習 - nyashバイナリのビルドを安定化: * 全てのimportエラーを修正 * cargo build --bin nyash が正常に動作 - CURRENT_TASK.mdに新しい段階的実装方針を記載: * Phase 1: FloatBox (依存なし) * Phase 2: ArrayBox改良 * Phase 3: 演算子システム改良 - 教訓: 一つずつ確実に実装し、テストファーストで進める 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 33 + CURRENT_TASK.md | 803 ++++--------------------- Cargo.toml | 3 - src/boxes/message_intent_box.rs | 134 ----- src/boxes/mod.rs | 6 +- src/boxes/new_p2p_box.rs | 171 ------ src/interpreter/expressions.rs | 24 +- src/interpreter/methods/p2p_methods.rs | 141 +---- src/interpreter/objects.rs | 60 -- src/lib.rs | 3 - src/message_bus.rs | 173 ------ src/transport_trait.rs | 80 --- src/transports/in_process_transport.rs | 134 ----- src/transports/mod.rs | 11 - test_new_p2p_box.rs | 119 ---- 15 files changed, 165 insertions(+), 1730 deletions(-) delete mode 100644 src/boxes/message_intent_box.rs delete mode 100644 src/boxes/new_p2p_box.rs delete mode 100644 src/message_bus.rs delete mode 100644 src/transport_trait.rs delete mode 100644 src/transports/in_process_transport.rs delete mode 100644 src/transports/mod.rs delete mode 100644 test_new_p2p_box.rs diff --git a/CLAUDE.md b/CLAUDE.md index 3dba6040..cd33fb57 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -195,6 +195,39 @@ app.setSize(800, 600) **実装状況**: 基本実装完了、GUI実行コンテキスト対応中 +## 📖 ドキュメントファースト開発(重要!) + +### 🚨 開発手順の鉄則 +**絶対にソースコードを直接読みに行かない!必ずこの順序で作業:** + +1. **📚 ドキュメント確認** - まず既存ドキュメントをチェック +2. **🔄 ドキュメント更新** - 古い/不足している場合は更新 +3. **💻 ソース確認** - それでも解決しない場合のみソースコード参照 + +### 🎯 最重要ドキュメント(2つの核心) + +#### 🔤 言語仕様 +- **[構文早見表](docs/quick-reference/syntax-cheatsheet.md)** - 基本構文・よくある間違い +- **[完全リファレンス](docs/reference/)** - 言語仕様詳細 +- **[予約語一覧](docs/reference/keywords.md)** - from, override, pack等 + +#### 📦 主要BOXのAPI +- **[ビルトイン型](docs/reference/built-in-boxes.md)** - 全Box型API仕様 +- **P2PBox & IntentBox** - docs/reference/built-in-boxes.md内 +- **StringBox, IntegerBox, ConsoleBox** - 基本Box API +- **EguiBox, DebugBox, MathBox** - 特殊Box API + +### ⚡ API確認の実践例 +```bash +# ❌ 悪い例:いきなりソース読む +Read src/boxes/p2p_box.rs # 直接ソース参照 + +# ✅ 良い例:ドキュメント優先 +Read docs/reference/built-in-boxes.md # まずドキュメント +# → 古い/不足 → ドキュメント更新 +# → それでも不明 → ソース確認 +``` + ## 🔧 開発サポート ### 🤖 AI相談 diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 58a3c52b..62297fd4 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -1,677 +1,130 @@ -# 🎯 現在のタスク (2025-08-11 P2PBox設計完成!) - -## 🚀 2025-08-11 P2PBox完璧設計達成 - -### 💡 **ChatGPT大会議成果** -**禿げるほど考えた末の完璧なアーキテクチャ決定!** - -#### **核心設計思想** -- **Bus = ローカルOS**: 常に保持、配送・購読・監視のハブ -- **Transport = NIC**: 通信手段選択、InProcess/WebSocket/WebRTC切り替え -- **IntentBox**: メッセージ専用Box(Transportと分離) - -#### **完全実装仕様(コンテキスト圧縮復元)** - -**🎯 IntentBox詳細設計(Nyash同期・シンプル版)** -```rust -// ✅ 最初の実装はシンプル同期版 -pub struct IntentBox { - pub intent: String, // Intent種類("chat.message", "file.transfer"等) - pub payload: HashMap>, // Nyashネイティブ・同期 -} - -impl IntentBox { - pub fn new(intent: &str) -> Self; - pub fn set(&mut self, key: &str, value: Box); - pub fn get(&self, key: &str) -> Option<&Box>; -} - -// 🔄 将来拡張用(後回し) -// pub struct SendOpts { ack_required, timeout_ms } - async時に追加 -// pub struct IntentEnvelope { from, to, intent } - ネット対応時に追加 -``` - -**🎯 P2PBox詳細設計(Nyash同期・シンプル版)** -```rust -// ✅ 最初の実装はシンプル同期版 -pub struct P2PBox { - node_id: String, - transport: Box, - bus: Arc, // ← 常に保持!(ローカル配送・購読・監視用) -} - -impl P2PBox { - // シンプル同期コンストラクタ - pub fn new(node_id: &str, transport_kind: TransportKind) -> Self { - let bus = get_global_message_bus(); // シングルトン取得 - let transport = create_transport(transport_kind, node_id); // 簡単ファクトリ - - // 自ノード登録 - bus.register_node(node_id).unwrap(); - - Self { - node_id: node_id.to_string(), - transport, - bus - } - } - - // 購読メソッド - Busに登録 - pub fn on(&self, intent: &str, callback: Box) { - self.bus.on(&self.node_id, intent, callback).unwrap(); - } - - // 送信メソッド - 天才アルゴリズム内蔵(同期版) - pub fn send(&self, to: &str, intent_box: &IntentBox) -> Result<(), String> { - // 1) 宛先が同プロセス(Busが知っている)ならローカル配送 - if self.bus.has_node(to) { - let message = BusMessage { - from: self.node_id.clone(), - to: to.to_string(), - intent: intent_box.intent.clone(), - data: /* IntentBoxをNyashBoxに変換 */, - timestamp: std::time::SystemTime::now(), - }; - self.bus.route(message)?; // 爆速ローカル - return Ok(()); - } - - // 2) ローカルに居ない → Transportで外へ出す - self.transport.send(to, &intent_box.intent, /* data */) - } - - pub fn get_node_id(&self) -> &str { - &self.node_id - } -} - -// 🔄 将来拡張用(後回し) -// async fn send() - async対応時 -// TransportFactory::create() - 複雑なオプション対応時 -// on_receive()コールバック - ネット受信対応時 -``` - -**🎯 TransportKind & ファクトリ(Nyash同期・シンプル版)** -```rust -// ✅ 最初の実装はシンプル版 -#[derive(Debug, Clone)] -pub enum TransportKind { - InProcess, // プロセス内通信(最初に実装) - WebSocket, // WebSocket通信(将来実装) - WebRTC, // P2P直接通信(将来実装) -} - -// シンプルファクトリ関数 -pub fn create_transport(kind: TransportKind, node_id: &str) -> Box { - match kind { - TransportKind::InProcess => Box::new(InProcessTransport::new(node_id.to_string())), - TransportKind::WebSocket => todo!("WebSocket transport - 将来実装"), - TransportKind::WebRTC => todo!("WebRTC transport - 将来実装"), - } -} - -// 🔄 将来拡張用(後回し) -// pub struct TransportFactory; - 複雑なオプション対応時 -// pub struct TransportOpts; - オプション追加時 -``` - -**🎯 4つの核心(忘れてはいけないポイント)** -``` -1. P2PBoxは、トランスポートがネットでもBusを持ち続ける(ローカル配送・購読・監視用) -2. P2PBoxはIntentBoxを使って送る -3. 送信アルゴリズム:ローカルならBus、それ以外はTransport -4. 受信アルゴリズム:Transport→P2PBox→Bus でローカルハンドラに届く -``` - -**🎯 天才アルゴリズム実装(同期・シンプル版)** -```rust -// 送信:ローカル優先 → リモートフォールバック -if self.bus.has_node(to) { - self.bus.route(message)?; // ← 爆速ローカル(ゼロコピー級) - return Ok(()); -} else { - self.transport.send(to, intent, data)?; // ← Transport経由(同期) -} - -// 受信:将来実装時の流れ -// Transport.receive() → IntentBox → MessageBus.route() → LocalHandler -``` - -**🎯 使用例(Nyash同期・シンプル版)** -```rust -// 基本使用パターン(同期版) -let alice = P2PBox::new("alice", TransportKind::InProcess); -let bob = P2PBox::new("bob", TransportKind::InProcess); - -// 購読登録 -bob.on("chat.message", Box::new(|intent_box: &IntentBox| { - if let Some(text) = intent_box.get("text") { - println!("Received: {}", text.to_string_box().value); - } -})); - -// メッセージ送信 -let mut intent = IntentBox::new("chat.message"); -intent.set("text", Box::new(StringBox::new("Hello Bob!"))); -alice.send("bob", &intent).unwrap(); // ← 天才アルゴリズム自動判定(同期) -``` - -**🎯 実装順序(重要)** -``` -1. まず cargo build --lib でコンパイル確認 -2. IntentBox実装(HashMap + Nyashネイティブ) -3. TransportKind enum実装 -4. P2PBox本体実装(天才アルゴリズム内蔵) -5. テスト用Nyashコード作成・動作確認 -``` - -#### **勝利ポイント** -1. **統一API**: send()/on() でローカル・ネット同じ -2. **最速ローカル**: Bus直接配送でゼロコピー級 -3. **拡張自在**: TransportKind で通信手段切り替え -4. **デバッグ天国**: Bus でメッセージ全監視 -5. **NyaMesh実証済み**: Transport抽象化パターン - -### 🎯 **次の実装ステップ(詳細設計復元完了)** - -**基盤レイヤー(ほぼ完了)** -1. ✅ **Transport trait 定義** - NyaMesh参考実装完了 -2. ✅ **MessageBus シングルトン** - 基本実装済み、OnceLock使用 -3. 🔄 **InProcessTransport修正** - 新仕様対応が必要 - -**コアレイヤー(最優先実装)** -4. 🚨 **IntentBox実装** - HashMap>構造 -5. 🚨 **TransportKind enum** - create_transport()ファクトリ含む -6. 🚨 **P2PBox本体実装** - 天才アルゴリズム send()メソッド内蔵 - -**統合レイヤー(最終段階)** -7. **インタープリター統合** - new P2PBox(), new IntentBox()対応 -8. **テストスイート** - 基本動作確認 - -**🚨 現在の状況 - P2PBox天才アルゴリズム完全実装済み** -- ✅ Transport trait + MessageBus + NewP2PBox 完全実装済み -- ✅ 天才アルゴリズム動作:`if bus.has_node(to) { bus.route() } else { transport.send() }` -- 🔥 **重要ギャップ発見:MethodBox統合が未実装** - -**🚨 次の最優先タスク** -1. **テスト確認** - 現在のRustクロージャ版で基本動作確認 -2. **MethodBox統合追加** - Nyash側使用に必須! - -**🎯 MethodBox統合の詳細** -```rust -// 現在(Rust内部用) -pub fn on(&self, intent: &str, callback: Box) - -// 必要(Nyash統合用) -pub fn on(&self, intent: &str, method_box: MethodBox) -// ↓ method_box.invoke(args) でNyash関数呼び出し -``` - -**理由**: Nyash側で `alice.on("chat", |msg| { print(msg.text) })` を書く時、 -|msg| { } 部分はMethodBoxとして実装される。Rustクロージャでは受け取れない。 - -## 🔥 2025-08-11 本日の大成果 - -### 🎉 完了した革命的変更 - -#### 1. ✅ **`pack`構文革命完成** -- AI大会議(Gemini + GPT-5)で`pack`構文一致採用 -- パーサー・インタープリター完全実装 -- デリゲーション: `from Parent.pack()`動作確認 -- Box哲学の完全具現化:「箱に詰める」直感体験 - -#### 2. ✅ **デリゲーションメソッドチェック機能完成** -- validate_override_methods実装・有効化 -- 危険パターン検出(nonExistentMethod等) -- パース時早期エラー検出で安全性大幅向上 -- テストスイート完備(正常/異常ケース) - -#### 3. ✅ **CharmFlow教訓を活かした設計決定** -- 過去のプラグイン互換性破綻の実体験を踏まえた戦略決定 -- GPT-5専門家による深い技術分析 -- BoxBase + BoxCore戦略で互換性問題完全回避を確認 - -## 🚀 BoxBase + BoxCore革命実装開始! - -### 📋 **CharmFlow教訓を活かした大改革** -CharmFlowでプラグインバージョンが1つ上がっただけで全プラグイン使用不能になった実体験を活かし、Nyashでは統一インターフェースで互換性問題を根本解決します。 - -### 🎯 **GPT-5専門家分析結果** -- **互換性**: CharmFlow的破綻を完全回避可能 -- **コード削減**: 40-70%削減 + 美しさ大幅向上 -- **拡張性**: 将来のビルトインBox継承に最適 -- **デバッグ**: 段階的移行で安全性確保 - -### 📝 次期実装タスク(最優先) - -#### 1. **BoxBase + BoxCore統一基盤実装**(最優先・大変更) -```rust -// Phase 1: 統一ID生成システム -pub fn next_box_id() -> u64 { - static COUNTER: AtomicU64 = AtomicU64::new(1); - COUNTER.fetch_add(1, Ordering::Relaxed) -} - -// Phase 2: 共通基盤構造 -pub struct BoxBase { - id: u64, -} - -pub trait BoxCore: Send + Sync { - fn box_id(&self) -> u64; - fn fmt_box(&self, f: &mut fmt::Formatter) -> fmt::Result; -} - -// Phase 3: 統一トレイト -pub trait NyashBox: BoxCore + DynClone + Any { - fn type_name(&self) -> &'static str { - std::any::type_name::() - } - fn as_any(&self) -> &dyn Any { - self - } -} -``` - -**実装計画**: -1. **ID生成統一**: `unsafe` → `AtomicU64`で安全化 -2. **BoxBase構造体導入**: 全Box共通の基盤 -3. **BoxCoreトレイト**: 重複メソッドの統一 -4. **段階的移行**: StringBox → IntegerBox → 全Box -5. **テスト**: 各段階で互換性確認 - -#### 2. **ビルトインBox継承基盤準備**(高優先) -BoxBase基盤完成後、P2PBox継承機能を実装: -```nyash -// 実現目標 -box ChatNode from P2PBox { - pack(nodeId, world) { - from P2PBox.pack(nodeId, world) - me.chatHistory = new ArrayBox() - } - - override send(intent, data, target) { - me.chatHistory.push(createLogEntry(intent, data, target)) - from P2PBox.send(intent, data, target) - } -} -``` - -#### 3. **pack構文最適化**(中優先) -- `pack` > `init` > Box名優先順位の改善 -- エラーメッセージの向上 -- パフォーマンス最適化 - -## 🎉 2025-08-11 言語設計史上の大革命実装進行中! - -### 🌟 override + from 統一構文による明示的デリゲーション革命【実装中】 -**Nyash史上最大の言語設計転換点実装中!** 暗黙のオーバーライド問題を発見し、Gemini・ChatGPT両先生から圧倒的支持を得てoverride + from完全統一構文を実装中。世界初の完全明示デリゲーション言語を目指します! - -#### 🎯 2025-08-11 最新実装状況: -- ✅ **from Parent.method()** - ユーザー定義Box間で正常動作確認! -- ✅ **overrideキーワード** - パーサー実装完了、正常動作! -- ✅ **`box Child from Parent`構文** - 完全実装済み! -- ✅ **`init`構文決定** - AI大会議で合意形成! -- ❌ **Box宣言時のデリゲーションチェック** - 親メソッドとの重複チェック未実装 -- ❌ **ビルトインBoxデリゲーション** - P2PBox等が "Undefined class"(後回し) - -#### 🔥 2025-08-11 完全実装済み項目: -1. **暗黙オーバーライド問題の完全解決** ✅実装完了 - - HashMap::insertによる意図しない上書きバグを発見・修正 - - instance.rs add_method()でoverride必須チェック実装 - - 明示的overrideなしの重複メソッド→コンパイルエラー - -2. **フルスタック実装完成** ✅全層実装 - - トークナイザー: OVERRIDE, FROMトークン追加完了 - - AST: is_overrideフィールド、FromCall構造追加完了 - - パーサー: override構文、from Parent.method()解析完了 - - インタープリター: FromCall実行処理完成 - -3. **コンストラクタオーバーロード禁止** ✅実装完了 - - register_box_declaration()で複数コンストラクタ検出 - - "One Box, One Constructor"哲学の完全実現 - -2. **3AI大会議による圧倒的支持獲得** 🎊 - - Gemini先生:「全面的に賛成」「極めて重要な一歩」 - - ChatGPT先生:「強く整合」「実装工数3-5日」 - - 両先生から言語設計の専門的視点で絶賛評価 - -3. **override + from 完全統一構文の確立** 🚀 - ```nyash - // 世界初の完全明示デリゲーション - box MeshNode from P2PBox { // from構文に統一! - override send(intent, data, target) { // 置換宣言 - me.routing.log(target) - from P2PBox.send(intent, data, target) // 親実装明示呼び出し - } - } - - init(nodeId, world) { // initに統一決定! - from P2PBox.init(nodeId, world) // コンストラクタも統一 - me.routing = RoutingTable() - } - ``` - -4. **設計原則の確立** - - ❌ 暗黙オーバーライド完全禁止 - - ❌ コンストラクタオーバーロード禁止 - - ✅ override キーワード必須 - - ✅ from による明示的親呼び出し - - ✅ 多重デリゲーションでの曖昧性完全解消 - -5. **他言語との明確な差別化達成** - - Python MRO地獄の完全回避 - - Java/C# super問題の根本解決 - - 世界初の「完全明示デリゲーション言語」として確立 - -## 🎉 2025-08-10 の大成果まとめ - -### 🔥 Arc Revolution + AI大相談会 ダブル完全達成! -**Nyash史上最大の2つの革命完了!** 全16種類のBox型が統一パターンで実装され、さらに関数オーバーロード設計が3AI合意で決定されました。 - -#### 本日完了した作業: -1. **ArrayBoxの完全再実装** ⭐️最重要 - - Arcパターンで全メソッド統一 - - `&self`で動作(push, pop, get, set, join等) - - Box引数対応でNyashから完全使用可能 - -2. **既存Box修正完了** - - BufferBox: ArrayBoxとの連携修正、デバッグ出力削除 - - StringBox: 新ArrayBoxインポート修正 - - RandomBox: 新ArrayBoxインポート修正 - - RegexBox/JSONBox: 既に正しく実装済みを確認 - -3. **包括的テスト成功** ✅ - ```nyash - // 全Box型の動作確認完了! - ArrayBox: push/pop/get/set/join ✅ - BufferBox: write/readAll/length ✅ - JSONBox: parse/stringify/get/set/keys ✅ - RegexBox: test/find/findAll/replace/split ✅ - StreamBox: write/read/position/reset ✅ - RandomBox: random/randInt/choice/shuffle ✅ - ``` - -4. **技術的成果** - - 完全なスレッドセーフティ実現 - - 統一されたAPI(全て`&self`メソッド) - - メモリ安全性とRust所有権システムの完全統合 - -5. **🤖 AI大相談会による関数オーバーロード設計決定** ⭐️新規 - - Claude(司会) + Gemini(設計思想) + ChatGPT(技術実装)による史上初の3AI協働分析 - - **最終決定**: Rust風トレイトシステム採用 (NyashAddトレイト) - - 静的・動的ハイブリッドディスパッチによるパフォーマンス最適化 - - Everything is Box哲学との完全整合を確認 - - 詳細記録: `sessions/ai_consultation_overload_design_20250810.md` - -6. **🚀 P2PBox/IntentBox基本実装完了** ⭐️新規 - - IntentBox: 通信世界を定義するコンテナ実装 - - P2PBox: 通信ノードの完全実装(send/broadcast/on/off) - - LocalTransport: プロセス内メッセージキュー実装 - - インタープリター完全統合 - - 包括的テストスイート作成・全パス確認 - -7. **🎯 ビルトインBox継承システム設計完了** ⭐️最新 - - 継承廃止→デリゲーション全面移行を決定 - - Gemini+ChatGPT+Claude 3AI大会議で文法設計 - - 最終決定: `box MeshNode extends P2PBox`構文採用 - - super解禁で直感的なAPI実現 - - 詳細記録: `sessions/ai_consultation_*_20250810.md` - -## 📊 プロジェクト現状 - -### ✅ 実装済みBox一覧(全16種類 - Arc統一完了) -| Box名 | 用途 | 実装状態 | テスト | -|-------|------|----------|--------| -| StringBox | 文字列操作 | ✅ 完全実装 | ✅ | -| IntegerBox | 整数演算 | ✅ 完全実装 | ✅ | -| BoolBox | 論理値 | ✅ 完全実装 | ✅ | -| NullBox | null値 | ✅ 完全実装 | ✅ | -| ConsoleBox | コンソール入出力 | ✅ 完全実装 | ✅ | -| MathBox | 数学関数 | ✅ 完全実装 | ✅ | -| TimeBox | 時刻操作 | ✅ 完全実装 | ✅ | -| MapBox | 連想配列 | ✅ 完全実装 | ✅ | -| DebugBox | デバッグ支援 | ✅ 完全実装 | ✅ | -| RandomBox | 乱数生成 | ✅ 完全実装 | ✅ 本日 | -| SoundBox | 音声 | ⚠️ スタブ実装 | - | -| ArrayBox | 配列操作 | ✅ 完全実装 | ✅ 本日 | -| BufferBox | バイナリデータ | ✅ 完全実装 | ✅ 本日 | -| RegexBox | 正規表現 | ✅ 完全実装 | ✅ 本日 | -| JSONBox | JSON解析 | ✅ 完全実装 | ✅ 本日 | -| StreamBox | ストリーム処理 | ✅ 完全実装 | ✅ 本日 | - -### 🏗️ プロジェクト構造計画(ユーザー後日実施) -``` -nyash-project/ # モノレポジトリ構造 -├── nyash-core/ # 現在のnyashメイン実装 -│ ├── src/ # コア実装 -│ ├── tests/ # テストスイート -│ └── examples/ # サンプルアプリ -├── nyash-wasm/ # WebAssembly版 -│ ├── src/ # WASM バインディング -│ └── playground/ # Webプレイグラウンド -├── nyash-lsp/ # Language Server(将来) -└── nyash-vscode/ # VS Code拡張(将来) -``` - -#### 🌟 実装成果まとめ: -```nyash -// 🔥 世界初の完全明示デリゲーション言語実現! -box MeshNode from P2PBox { // from構文採用! - override send(intent, data, target) { // 明示的オーバーライド - me.routing.log(target) - from P2PBox.send(intent, data, target) // 親実装呼び出し - } - - init(nodeId, world) { // init構文決定! - from P2PBox.init(nodeId, world) // コンストラクタ統一構文 - me.routing = RoutingTable() - } -} -``` - -#### 📚 ドキュメント完成: -- ✅ `docs/design-philosophy/explicit-delegation-revolution.md` - 設計思想詳細 -- ✅ `docs/language-specification/override-delegation-syntax.md` - 完全仕様 -- ✅ AI相談記録 - Gemini・ChatGPT絶賛評価の全記録 - -## 🚀 次のステップ(優先順位順) - -### 1. 🎉 完了した革命項目 -- [x] **暗黙オーバーライド問題発見・解決**: HashMap::insert悪魔を完全撲滅 ✅完了 -- [x] **override + from統一構文**: フルスタック実装完成 ✅完了 -- [x] **コンストラクタオーバーロード禁止**: "One Box, One Constructor"実現 ✅完了 -- [x] **完全明示デリゲーション言語**: 世界初達成 ✅完了 - -### 2. 🔥 関数オーバーロード実装(完了済み) -- [x] **NyashAddトレイト定義**: `trait NyashAdd { type Output; fn add(self, rhs: Rhs) -> Self::Output; }` ✅完了 -- [x] **静的・動的ハイブリッドディスパッチ**: 型判明時→静的解決、不明時→vtable動的解決 ✅完了 -- [x] **既存Box型への適用**: IntegerBox, StringBox等にNyashAddトレイト実装 ✅完了 -- [x] **テスト・最適化**: パフォーマンス測定とエッジケース検証 ✅完了 - -### 2. 📡 P2PBox/intentbox実装(✅ 基本実装完了!) -**Everything is Box哲学による分散通信システム** - -#### 🎉 本日の実装成果 -- ✅ **IntentBox完全実装**: 通信世界を定義するコンテナ - - Transportトレイトによる通信方式抽象化 - - LocalTransport実装(プロセス内メッセージキュー) - - Arcパターンでスレッドセーフ - -- ✅ **P2PBox完全実装**: 通信ノードBox - - send/broadcast/on/offメソッド実装 - - Arc構造で適切なクローン対応 - - 複数リスナー登録可能(同一intent対応) - -- ✅ **インタープリター統合**: - - new IntentBox() / new P2PBox(nodeId, world)対応 - - 全メソッドのディスパッチ実装 - - エラーハンドリング完備 - -- ✅ **包括的テストスイート**: - - test_p2p_basic.nyash: 基本機能検証 - - test_p2p_message_types.nyash: 各種データ型対応 - - test_p2p_edge_cases.nyash: エラー処理とエッジケース - - test_p2p_callback_demo.nyash: 実用例デモ - -#### 実装済みの詳細 - -##### Phase 1: 基本設計・構造定義(本日) -```rust -// intentbox - 通信世界の抽象化 -pub struct IntentBox { - id: u64, - transport: Arc>>, - nodes: Arc>>>, -} - -// P2PBox - 通信ノード -pub struct P2PBox { - node_id: String, - intent_box: Arc, - listeners: Arc>>>, -} - -// Transport trait - 通信方法の抽象化 -pub trait Transport: Send + Sync { - fn send(&self, from: &str, to: &str, intent: &str, data: Box); - fn broadcast(&self, from: &str, intent: &str, data: Box); -} -``` - -##### Phase 2: ローカル通信実装(今日〜明日) -```rust -// プロセス内通信Transport -pub struct LocalTransport { - message_queue: Arc>>, -} - -// 基本的なメソッド実装 -impl P2PBox { - pub fn send(&self, intent: &str, data: Box, target: &str) { - self.intent_box.transport.lock().unwrap() - .send(&self.node_id, target, intent, data); - } - - pub fn on(&self, intent: &str, callback: Box) { - // CallbackBoxとして保存 - } -} -``` - -##### Phase 3: Nyash統合(明日) -```nyash -// 使用例 -local_bus = new IntentBox() // デフォルトでローカル通信 - -node_a = new P2PBox("alice", local_bus) -node_b = new P2PBox("bob", local_bus) - -// リスナー登録 -node_b.on("greeting", |data, from| { - print(from + " says: " + data.get("text")) -}) - -// メッセージ送信 -node_a.send("greeting", { "text": "Hello!" }, "bob") -``` - -##### Phase 4: Intent辞書パターン(明後日) -```nyash -// Intent定義の標準化 -ChatIntents = { - "Message": "chat.message", - "Join": "chat.user.joined", - "Leave": "chat.user.left" -} - -// 型安全な使用 -node.send(ChatIntents.Message, data, target) -``` - -##### 残りの実装タスク(将来拡張) -- [ ] **コールバック実行**: MethodBox統合待ち -- [ ] **WebSocket Transport**: ネットワーク通信対応 -- [ ] **ノード登録管理**: IntentBoxでのP2PBox管理 -- [ ] **メッセージ配信**: LocalTransportでの実配信 - -#### 将来の拡張性(設計に組み込み) -- WebSocket Transport(ネットワーク通信) -- SharedMemory Transport(高速IPC) -- Persistence Layer(メッセージ永続化) -- Security Layer(暗号化・認証) - -#### 技術的考慮事項 -- **Arc統一**: 全16Box型と同じパターンで実装 -- **Weak参照**: 循環参照防止のため、IntentBoxはP2PBoxをWeakで保持 -- **非同期対応**: nowait/awaitとの統合を考慮 -- **エラーハンドリング**: ノード切断・タイムアウト処理 - -#### NyashFlowプロジェクトとの関連 -P2PBox実装は将来のNyashFlowビジュアルプログラミングにおいて、 -ノード間のデータフロー実行基盤として活用される重要な技術。 -CharmFlowの教訓を活かし、シンプルで拡張性の高い設計を目指す。 - -### 3. 🎮 実用アプリケーション開発(来週) -- [ ] **P2P チャットアプリ**: P2PBox実装のデモ -- [ ] **分散計算デモ**: 複数ノードでタスク分散 -- [ ] **リアルタイムゲーム**: 低遅延通信のテスト - -### 4. 📚 ドキュメント整備(今週〜来週) -- [ ] Arc設計思想をPHILOSOPHY.mdに追記 -- [ ] 関数オーバーロード設計思想をPHILOSOPHY.mdに追記 -- [ ] P2PBox/intentbox設計思想をPHILOSOPHY.mdに追記 -- [ ] 各Box APIリファレンス完全版作成(P2PBox含む) -- [ ] 分散・並行処理プログラミングガイド - -### 5. 🌐 WebAssembly強化(来週) -- [ ] nyash-wasmを最新core対応に更新 -- [ ] Web Workersでの並行処理サポート -- [ ] P2PBox WebSocket Transport対応 -- [ ] npm パッケージとして公開準備 - -### 6. 🛠️ 開発ツール(今月中) -- [ ] **nyash-lsp**: Language Serverプロジェクト開始 -- [ ] **VS Code拡張**: シンタックスハイライト実装 -- [ ] **デバッガー**: ステップ実行・P2P通信トレース - -### 7. ⚡ パフォーマンス最適化(継続的) -- [ ] 不要なlock呼び出しの特定と削減 -- [ ] P2PBox メッセージ配信最適化 -- [ ] ベンチマークスイート構築 -- [ ] メモリ使用量プロファイリング - -## 💭 技術的な振り返り - -### Arcパターンの成功要因 -1. **設計の一貫性**: 全Box型で同じパターン採用 -2. **Rustの型システム**: コンパイル時の安全性保証 -3. **段階的移行**: 一つずつ確実に実装・テスト - -### 学んだ教訓 -1. **ArrayBoxの見落とし**: 既存実装の確認が重要 -2. **型の互換性**: Box引数の重要性 -3. **テストファースト**: 実装前にテストケース作成 - -### 今後の課題と機会 -1. **エコシステム拡大**: サードパーティBox開発支援 -2. **パフォーマンス**: より効率的なlocking戦略 -3. **開発体験**: より直感的なAPI設計 -4. **AI協働開発**: 複数AI相談システムのさらなる活用 - -## 📝 重要メモ -- **Git状態**: mainブランチは11コミット先行(要プッシュ) -- **Copilot PR #2**: 正常にマージ完了、協働開発成功 -- **AI大相談会記録**: `sessions/ai_consultation_overload_design_20250810.md` -- **プロジェクト再編**: 権限問題のため後日実施予定 -- **関数オーバーロード**: ✅完全実装完了(NyashAddトレイト) -- **P2PBox/IntentBox**: ✅基本実装完了!テスト成功! -- **次回作業**: コールバック実行機能の実装(MethodBox統合) +# 🎯 現在のタスク (2025-08-11 シンプルBoxから段階的実装!) + +## 🚀 2025-08-11 複雑なP2PBox実装をリセット → シンプルBox段階実装開始! + +### 💡 **学習成果** +**複雑すぎる実装を一度に追加すると失敗することを学習!** + +#### **新方針** +- **依存の少ないBox**: まずシンプルなBoxから追加 +- **段階的実装**: 一つずつ確実に動作確認 +- **テストファースト**: 必ず動作確認してから次へ + +### 📋 **段階的実装計画(優先度順)** + +#### **Phase 1: 基本型Box実装** (最優先) + +##### 1. **FloatBox** - 浮動小数点数Box 📊 +- **依存**: なし (f64の基本実装) +- **実装内容**: + - 基本値の保持・表示 + - 四則演算メソッド + - 文字列変換 + - 比較演算子 +- **テスト**: + ```nyash + f = new FloatBox(3.14) + print(f.add(2.86)) // 6.0 + print(f.toString()) // "3.14" + ``` + +##### 2. **ArrayBoxの改良** - 配列機能の強化 📚 +- **依存**: 既存ArrayBox実装 +- **追加機能**: + - sort()メソッド - 配列ソート + - reverse()メソッド - 配列反転 + - indexOf()メソッド - 要素検索 + - slice()メソッド - 部分配列 +- **テスト**: + ```nyash + arr = new ArrayBox() + arr.push(3); arr.push(1); arr.push(2) + arr.sort() // [1, 2, 3] + ``` + +#### **Phase 2: 演算子システム** (高優先) + +##### 3. **基本演算子の改良** ➕➖✖️➗ +- **依存**: 既存の演算子実装 +- **改良内容**: + - 型間演算の対応 (IntegerBox + FloatBox) + - 文字列 + 数値の連結 + - より良いエラーメッセージ +- **テスト**: + ```nyash + print(42 + 3.14) // 45.14 (型変換) + print("Value: " + 42) // "Value: 42" + ``` + +##### 4. **比較演算子の完全実装** 🔍 +- **実装内容**: + - ==, !=, <, >, <=, >= の完全対応 + - 型間比較のサポート + - null比較の正しい動作 +- **テスト**: 全ての型の組み合わせテスト + +#### **Phase 3: ユーティリティBox** (中優先) + +##### 5. **DateTimeBox** - 日時操作 📅 +- **依存**: chrono crate (既存) +- **機能**: + - 現在時刻の取得 + - 日時の計算・比較 + - フォーマット変換 +- **テスト**: 日時計算、文字列変換 + +##### 6. **FileBox** - ファイル操作 📁 +- **依存**: std::fs +- **機能**: + - ファイル読み書き + - 存在確認 + - ディレクトリ操作 +- **テスト**: 基本的なファイル操作 + +### 🎯 **今週の実装目標** + +#### **今日 (2025-08-11)**: FloatBox実装 +1. FloatBox構造体作成 +2. 基本メソッド実装 (add, sub, mul, div) +3. Nyashからの使用テスト +4. インタープリター統合 + +#### **明日**: ArrayBox改良 +1. sort()メソッド実装 +2. reverse()メソッド実装 +3. テストスクリプト作成・動作確認 + +#### **明後日**: 演算子改良 +1. 型間演算の実装 +2. エラーハンドリング改善 +3. 包括的テスト + +### 📊 **実装ステータス** + +#### ✅ 実装済み (Arc統一完了) +- StringBox, IntegerBox, BoolBox, NullBox +- ConsoleBox, MathBox, TimeBox, MapBox +- DebugBox, RandomBox, ArrayBox (基本) +- BufferBox, RegexBox, JSONBox, StreamBox + +#### 🚧 今回追加予定 +- FloatBox (今日) +- ArrayBox改良 (明日) +- 演算子改良 (明後日) + +#### 📋 将来実装予定 +- DateTimeBox, FileBox +- より複雑なBox (P2PBox等) + +### 💭 **重要な原則** + +1. **一つずつ確実に**: 1つのBoxを完全に実装してから次へ +2. **テストファースト**: 必ずNyashスクリプトで動作確認 +3. **段階的複雑化**: シンプルから複雑へ +4. **ビルド確認**: 毎回`cargo build`で確認 +5. **依存関係注意**: 複雑な依存は後回し + +この方針で、確実で安定した実装を進めていきます! --- -最終更新: 2025-08-11 - デリゲーション革命完了!`from`統一構文+`init`構文決定!🎉 - -> 「Everything is Box」の理念が、完全明示デリゲーションという革命的な設計により、 -> より安全で、より明確で、より美しい言語へと進化しました。 -> `box Child from Parent`、`init`、`override`、`from Parent.init()` - -> すべてが統一され、Nyashは真の「完全明示デリゲーション言語」として確立されました。 \ No newline at end of file +最終更新: 2025-08-11 - シンプルBox段階実装方針決定! \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index e46d526f..d33ba781 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,9 +54,6 @@ path = "development/egui_research/experiments/visual_node_prototype.rs" name = "test_icon_extraction" path = "examples/test_icon_extraction.rs" -[[bin]] -name = "test_new_p2p_box" -path = "test_new_p2p_box.rs" [[bin]] name = "test_method_box_integration" diff --git a/src/boxes/message_intent_box.rs b/src/boxes/message_intent_box.rs deleted file mode 100644 index 324e98f2..00000000 --- a/src/boxes/message_intent_box.rs +++ /dev/null @@ -1,134 +0,0 @@ -/** - * MessageIntentBox - メッセージコンテナBox(P2P通信用) - * - * 設計原則: - * - HashMap>でNyashネイティブデータ保持 - * - 同期・シンプル実装(async対応は将来拡張) - * - Everything is Box哲学に準拠 - * - * 注意: 既存のIntentBox(通信世界)とは別物 - * - IntentBox = 通信世界・環境の定義 - * - MessageIntentBox = 実際のメッセージデータ(これ) - */ - -use std::collections::HashMap; -use std::fmt; -use crate::box_trait::{NyashBox, BoxCore, BoxBase, next_box_id}; - -/// MessageIntentBox - Intent型通信メッセージのコンテナ -pub struct MessageIntentBox { - base: BoxBase, - /// Intent種類("chat.message", "file.transfer"等) - pub intent: String, - /// Nyashネイティブデータ保持 - pub payload: HashMap>, -} - -impl MessageIntentBox { - /// 新しいMessageIntentBoxを作成 - pub fn new(intent: &str) -> Self { - Self { - base: BoxBase { - id: next_box_id(), - parent_type_id: None, // ビルトインBox継承なし - }, - intent: intent.to_string(), - payload: HashMap::new(), - } - } - - /// キー-値ペアを設定 - pub fn set(&mut self, key: &str, value: Box) { - self.payload.insert(key.to_string(), value); - } - - /// キーに対応する値を取得 - pub fn get(&self, key: &str) -> Option<&Box> { - self.payload.get(key) - } - - /// キーに対応する値を削除 - pub fn remove(&mut self, key: &str) -> Option> { - self.payload.remove(key) - } - - /// すべてのキーを取得 - pub fn keys(&self) -> Vec { - self.payload.keys().cloned().collect() - } - - /// ペイロードが空かチェック - pub fn is_empty(&self) -> bool { - self.payload.is_empty() - } - - /// ペイロード要素数を取得 - pub fn len(&self) -> usize { - self.payload.len() - } -} - -impl BoxCore for MessageIntentBox { - fn box_id(&self) -> u64 { - self.base.id - } - - fn parent_type_id(&self) -> Option { - self.base.parent_type_id - } - - fn fmt_box(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "MessageIntentBox(intent: {}, payload: {} items)", - self.intent, self.payload.len()) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} - -impl NyashBox for MessageIntentBox { - fn type_name(&self) -> &'static str { - "MessageIntentBox" - } - - fn to_string_box(&self) -> crate::StringBox { - crate::StringBox::new(&format!("MessageIntentBox({})", self.intent)) - } - - fn clone_box(&self) -> Box { - let mut new_intent = MessageIntentBox::new(&self.intent); - - // PayloadをDeepClone - for (key, value) in &self.payload { - new_intent.payload.insert(key.clone(), value.clone_box()); - } - - Box::new(new_intent) - } - - fn equals(&self, other: &dyn NyashBox) -> crate::BoolBox { - if let Some(other_intent) = other.as_any().downcast_ref::() { - crate::BoolBox::new(self.box_id() == other_intent.box_id()) - } else { - crate::BoolBox::new(false) - } - } -} - -impl fmt::Display for MessageIntentBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.fmt_box(f) - } -} - -impl fmt::Debug for MessageIntentBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "MessageIntentBox {{ intent: {:?}, payload: {:?} }}", - self.intent, self.payload.len()) - } -} \ No newline at end of file diff --git a/src/boxes/mod.rs b/src/boxes/mod.rs index 15637df5..24ad41d1 100644 --- a/src/boxes/mod.rs +++ b/src/boxes/mod.rs @@ -108,8 +108,6 @@ pub mod regex; // P2P通信Box群 pub mod intent_box; pub mod p2p_box; -pub mod message_intent_box; -pub mod new_p2p_box; // null関数も再エクスポート pub use null_box::{NullBox, null}; @@ -127,6 +125,4 @@ pub use regex::RegexBox; // P2P通信Boxの再エクスポート pub use intent_box::IntentBox; -pub use p2p_box::P2PBox; -pub use message_intent_box::MessageIntentBox; -pub use new_p2p_box::NewP2PBox; \ No newline at end of file +pub use p2p_box::P2PBox; \ No newline at end of file diff --git a/src/boxes/new_p2p_box.rs b/src/boxes/new_p2p_box.rs deleted file mode 100644 index 4af49911..00000000 --- a/src/boxes/new_p2p_box.rs +++ /dev/null @@ -1,171 +0,0 @@ -/** - * NewP2PBox - 天才アルゴリズム内蔵P2PBox(同期・シンプル版) - * - * 設計原則(4つの核心): - * 1. P2PBoxは、トランスポートがネットでもBusを持ち続ける(ローカル配送・購読・監視用) - * 2. P2PBoxはMessageIntentBoxを使って送る - * 3. 送信アルゴリズム:ローカルならBus、それ以外はTransport - * 4. 受信アルゴリズム:Transport→P2PBox→Bus でローカルハンドラに届く - * - * Everything is Box哲学準拠・同期実装 - */ - -use std::sync::Arc; -use crate::box_trait::{NyashBox, BoxCore, BoxBase, next_box_id}; -use crate::boxes::MessageIntentBox; -use crate::transport_trait::{Transport, TransportKind, create_transport}; -use crate::message_bus::{get_global_message_bus, BusMessage, MessageBus}; -use crate::method_box::MethodBox; - -/// NewP2PBox - 天才アルゴリズム内蔵P2P通信ノード -pub struct NewP2PBox { - base: BoxBase, - node_id: String, - transport: Box, - bus: Arc, // ← 常に保持!(ローカル配送・購読・監視用) -} - -impl NewP2PBox { - /// シンプル同期コンストラクタ - pub fn new(node_id: &str, transport_kind: TransportKind) -> Self { - let bus = get_global_message_bus(); // シングルトン取得 - let transport = create_transport(transport_kind, node_id); // 簡単ファクトリ - - // 自ノード登録 - bus.register_node(node_id).unwrap(); - - Self { - base: BoxBase { - id: next_box_id(), - parent_type_id: None, - }, - node_id: node_id.to_string(), - transport, - bus - } - } - - /// 購読メソッド - Busに登録(Rustクロージャ版) - pub fn on(&self, intent: &str, callback: Box) { - // BusMessageからMessageIntentBoxを抽出するラッパー - let wrapper = Box::new(move |bus_message: &BusMessage| { - // BusMessageのdataをMessageIntentBoxにダウンキャスト - if let Some(intent_box) = bus_message.data.as_any().downcast_ref::() { - callback(intent_box); - } - }); - self.bus.on(&self.node_id, intent, wrapper).unwrap(); - } - - /// 購読メソッド - MethodBox版(Nyash統合用) - pub fn on_method(&self, intent: &str, method_box: MethodBox) -> Result<(), String> { - // MethodBoxをクロージャでラップ - let wrapper = Box::new(move |bus_message: &BusMessage| { - // BusMessageのdataをMessageIntentBoxにダウンキャスト - if let Some(intent_box) = bus_message.data.as_any().downcast_ref::() { - // TODO: インタープリターコンテキストが必要 - // 現在は単純化実装 - println!("🎯 MethodBox callback triggered for intent '{}' from {}", - intent_box.intent, bus_message.from); - - // MethodBox.invoke()を呼び出し(引数としてMessageIntentBoxを渡す) - let args = vec![intent_box.clone_box()]; - match method_box.invoke(args) { - Ok(result) => { - println!("📥 MethodBox execution result: {}", result.to_string_box().value); - } - Err(e) => { - eprintln!("❌ MethodBox execution error: {}", e); - } - } - } - }); - - self.bus.on(&self.node_id, intent, wrapper) - } - - /// 送信メソッド - 天才アルゴリズム内蔵(同期版) - pub fn send(&self, to: &str, intent_box: &MessageIntentBox) -> Result<(), String> { - // 1) 宛先が同プロセス(Busが知っている)ならローカル配送 - if self.bus.has_node(to) { - // MessageIntentBoxからBusMessageに変換 - let message = BusMessage { - from: self.node_id.clone(), - to: to.to_string(), - intent: intent_box.intent.clone(), - data: intent_box.clone_box(), // MessageIntentBox全体をデータとして送信 - timestamp: std::time::SystemTime::now(), - }; - self.bus.route(message)?; // 爆速ローカル - return Ok(()); - } - - // 2) ローカルに居ない → Transportで外へ出す - self.transport.send(to, &intent_box.intent, intent_box.clone_box()) - } - - /// ノードID取得 - pub fn get_node_id(&self) -> &str { - &self.node_id - } -} - -impl BoxCore for NewP2PBox { - fn box_id(&self) -> u64 { - self.base.id - } - - fn parent_type_id(&self) -> Option { - self.base.parent_type_id - } - - fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "NewP2PBox(node_id: {}, transport: {})", - self.node_id, self.transport.transport_type()) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} - -impl NyashBox for NewP2PBox { - fn type_name(&self) -> &'static str { - "NewP2PBox" - } - - fn to_string_box(&self) -> crate::StringBox { - crate::StringBox::new(&format!("NewP2PBox({})", self.node_id)) - } - - fn clone_box(&self) -> Box { - // P2PBoxは基本的にクローンしない(ノードの一意性のため) - // 必要に応じて別のコンストラクタで同じ設定の新ノードを作成する - todo!("P2PBox clone not recommended - create new node instead") - } - - fn equals(&self, other: &dyn NyashBox) -> crate::BoolBox { - if let Some(other_p2p) = other.as_any().downcast_ref::() { - crate::BoolBox::new(self.node_id == other_p2p.node_id) - } else { - crate::BoolBox::new(false) - } - } -} - -impl std::fmt::Display for NewP2PBox { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - self.fmt_box(f) - } -} - -impl std::fmt::Debug for NewP2PBox { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "NewP2PBox {{ node_id: {:?}, transport: {:?} }}", - self.node_id, self.transport.transport_type()) - } -} \ No newline at end of file diff --git a/src/interpreter/expressions.rs b/src/interpreter/expressions.rs index c6a9eab1..271442ee 100644 --- a/src/interpreter/expressions.rs +++ b/src/interpreter/expressions.rs @@ -8,7 +8,7 @@ use super::*; use crate::ast::UnaryOperator; -use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, P2PBox, NewP2PBox, MessageIntentBox}; +use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, P2PBox}; use crate::boxes::{MathBox, ConsoleBox, TimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox}; use crate::operator_traits::OperatorResolver; // TODO: Fix NullBox import issue later @@ -747,7 +747,7 @@ impl NyashInterpreter { "TimeBox" | "DateTimeBox" | "TimerBox" | "RandomBox" | "SoundBox" | "DebugBox" | "MethodBox" | "NullBox" | "ConsoleBox" | "FloatBox" | "BufferBox" | "RegexBox" | "JSONBox" | "StreamBox" | "HTTPClientBox" | - "IntentBox" | "P2PBox" | "NewP2PBox" | "MessageIntentBox" | "EguiBox" + "IntentBox" | "P2PBox" | "EguiBox" ); if is_builtin { @@ -941,26 +941,6 @@ impl NyashInterpreter { message: format!("P2PBox delegation not yet fully implemented: {}.{}", parent, method), }); } - "NewP2PBox" => { - // NewP2PBoxの場合、current_instanceから実際のNewP2PBoxインスタンスを取得 - if let Some(p2p_box) = current_instance.as_any().downcast_ref::() { - self.execute_new_p2p_box_method(p2p_box, method, arguments) - } else { - Err(RuntimeError::TypeError { - message: format!("Expected NewP2PBox instance for method call {}.{}", parent, method), - }) - } - } - "MessageIntentBox" => { - // MessageIntentBoxの場合、current_instanceから実際のMessageIntentBoxインスタンスを取得 - if let Some(message_box) = current_instance.as_any_mut().downcast_mut::() { - self.execute_message_intent_box_method(message_box, method, arguments) - } else { - Err(RuntimeError::TypeError { - message: format!("Expected MessageIntentBox instance for method call {}.{}", parent, method), - }) - } - } "FileBox" => { let file_box = crate::boxes::file::FileBox::new(); self.execute_file_method(&file_box, method, arguments) diff --git a/src/interpreter/methods/p2p_methods.rs b/src/interpreter/methods/p2p_methods.rs index 12b03158..710ac09c 100644 --- a/src/interpreter/methods/p2p_methods.rs +++ b/src/interpreter/methods/p2p_methods.rs @@ -6,7 +6,7 @@ use crate::interpreter::core::NyashInterpreter; use crate::interpreter::core::RuntimeError; use crate::ast::ASTNode; use crate::box_trait::{NyashBox, StringBox}; -use crate::boxes::{IntentBox, P2PBox, NewP2PBox, MessageIntentBox}; +use crate::boxes::{IntentBox, P2PBox}; use crate::method_box::MethodBox; impl NyashInterpreter { @@ -115,143 +115,4 @@ impl NyashInterpreter { }) } } - - /// NewP2PBoxのメソッド実行(天才アルゴリズム版) - pub(in crate::interpreter) fn execute_new_p2p_box_method( - &mut self, - p2p_box: &NewP2PBox, - method: &str, - arguments: &[ASTNode], - ) -> Result, RuntimeError> { - match method { - // ノードID取得 - "getNodeId" | "getId" => { - Ok(Box::new(StringBox::new(p2p_box.get_node_id()))) - } - - // メッセージ送信(天才アルゴリズム) - "send" => { - if arguments.len() != 2 { - return Err(RuntimeError::InvalidOperation { - message: "send requires 2 arguments: target, message_intent_box".to_string(), - }); - } - - let target = self.execute_expression(&arguments[0])?; - let message_box = self.execute_expression(&arguments[1])?; - - if let Some(target_str) = target.as_any().downcast_ref::() { - if let Some(intent_box) = message_box.as_any().downcast_ref::() { - match p2p_box.send(&target_str.value, intent_box) { - Ok(()) => Ok(Box::new(StringBox::new("sent"))), - Err(e) => Err(RuntimeError::InvalidOperation { message: e }), - } - } else { - Err(RuntimeError::TypeError { - message: "send requires MessageIntentBox as second argument".to_string(), - }) - } - } else { - Err(RuntimeError::TypeError { - message: "send requires string target as first argument".to_string(), - }) - } - } - - // リスナー登録(MethodBox版) - "onMethod" => { - if arguments.len() != 2 { - return Err(RuntimeError::InvalidOperation { - message: "onMethod requires 2 arguments: intent, method_box".to_string(), - }); - } - - let intent = self.execute_expression(&arguments[0])?; - let method_box = self.execute_expression(&arguments[1])?; - - if let Some(intent_str) = intent.as_any().downcast_ref::() { - if let Some(method_box) = method_box.as_any().downcast_ref::() { - match p2p_box.on_method(&intent_str.value, method_box.clone()) { - Ok(()) => Ok(Box::new(StringBox::new("listener registered"))), - Err(e) => Err(RuntimeError::InvalidOperation { message: e }), - } - } else { - Err(RuntimeError::TypeError { - message: "onMethod requires MethodBox as second argument".to_string(), - }) - } - } else { - Err(RuntimeError::TypeError { - message: "onMethod requires string intent as first argument".to_string(), - }) - } - } - - _ => Err(RuntimeError::UndefinedVariable { - name: format!("NewP2PBox method '{}' not found", method), - }) - } - } - - /// MessageIntentBoxのメソッド実行 - pub(in crate::interpreter) fn execute_message_intent_box_method( - &mut self, - message_box: &mut MessageIntentBox, - method: &str, - arguments: &[ASTNode], - ) -> Result, RuntimeError> { - match method { - // intent取得 - "getIntent" | "intent" => { - Ok(Box::new(StringBox::new(&message_box.intent))) - } - - // データ設定 - "set" => { - if arguments.len() != 2 { - return Err(RuntimeError::InvalidOperation { - message: "set requires 2 arguments: key, value".to_string(), - }); - } - - let key = self.execute_expression(&arguments[0])?; - let value = self.execute_expression(&arguments[1])?; - - if let Some(key_str) = key.as_any().downcast_ref::() { - message_box.set(&key_str.value, value); - Ok(Box::new(StringBox::new("set"))) - } else { - Err(RuntimeError::TypeError { - message: "set requires string key as first argument".to_string(), - }) - } - } - - // データ取得 - "get" => { - if arguments.len() != 1 { - return Err(RuntimeError::InvalidOperation { - message: "get requires 1 argument: key".to_string(), - }); - } - - let key = self.execute_expression(&arguments[0])?; - if let Some(key_str) = key.as_any().downcast_ref::() { - if let Some(value) = message_box.get(&key_str.value) { - Ok(value.clone_box()) - } else { - Ok(Box::new(crate::boxes::NullBox::new())) - } - } else { - Err(RuntimeError::TypeError { - message: "get requires string key as argument".to_string(), - }) - } - } - - _ => Err(RuntimeError::UndefinedVariable { - name: format!("MessageIntentBox method '{}' not found", method), - }) - } - } } \ No newline at end of file diff --git a/src/interpreter/objects.rs b/src/interpreter/objects.rs index 21f091d0..642c0abb 100644 --- a/src/interpreter/objects.rs +++ b/src/interpreter/objects.rs @@ -9,8 +9,6 @@ use super::*; use crate::boxes::null_box::NullBox; use crate::boxes::console_box::ConsoleBox; -use crate::boxes::{NewP2PBox, MessageIntentBox}; -use crate::transport_trait::TransportKind; // use crate::boxes::intent_box_wrapper::IntentBoxWrapper; use std::sync::Arc; @@ -538,64 +536,6 @@ impl NyashInterpreter { }); } } - "NewP2PBox" => { - // NewP2PBoxは引数2個(node_id, transport_kind)で作成 - if arguments.len() != 2 { - return Err(RuntimeError::InvalidOperation { - message: format!("NewP2PBox constructor expects 2 arguments (node_id, transport_kind), got {}", arguments.len()), - }); - } - - // node_id - let node_id_value = self.execute_expression(&arguments[0])?; - let node_id = if let Some(id_str) = node_id_value.as_any().downcast_ref::() { - id_str.value.clone() - } else { - return Err(RuntimeError::TypeError { - message: "NewP2PBox constructor requires string node_id as first argument".to_string(), - }); - }; - - // transport_kind(文字列 → TransportKind enum) - let transport_value = self.execute_expression(&arguments[1])?; - let transport_kind = if let Some(transport_str) = transport_value.as_any().downcast_ref::() { - match transport_str.value.as_str() { - "InProcess" => TransportKind::InProcess, - "WebSocket" => TransportKind::WebSocket, - "WebRTC" => TransportKind::WebRTC, - _ => { - return Err(RuntimeError::TypeError { - message: format!("Invalid transport kind '{}'. Valid options: InProcess, WebSocket, WebRTC", transport_str.value), - }); - } - } - } else { - return Err(RuntimeError::TypeError { - message: "NewP2PBox constructor requires string transport_kind as second argument".to_string(), - }); - }; - - let p2p_box = Box::new(NewP2PBox::new(&node_id, transport_kind)) as Box; - return Ok(p2p_box); - } - "MessageIntentBox" => { - // MessageIntentBoxは引数1個(intent)で作成 - if arguments.len() != 1 { - return Err(RuntimeError::InvalidOperation { - message: format!("MessageIntentBox constructor expects 1 argument (intent), got {}", arguments.len()), - }); - } - - let intent_value = self.execute_expression(&arguments[0])?; - if let Some(intent_str) = intent_value.as_any().downcast_ref::() { - let message_box = Box::new(MessageIntentBox::new(&intent_str.value)) as Box; - return Ok(message_box); - } else { - return Err(RuntimeError::TypeError { - message: "MessageIntentBox constructor requires string intent as argument".to_string(), - }); - } - } _ => {} } diff --git a/src/lib.rs b/src/lib.rs index 2df99d1c..62d947a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,9 +22,6 @@ pub mod finalization; pub mod exception_box; pub mod method_box; pub mod type_box; // 🌟 TypeBox revolutionary system -pub mod transport_trait; -pub mod message_bus; -pub mod transports; pub mod operator_traits; // 🚀 Rust-style trait-based operator overloading pub mod box_operators; // 🚀 Operator implementations for basic Box types diff --git a/src/message_bus.rs b/src/message_bus.rs deleted file mode 100644 index f9ce0ce9..00000000 --- a/src/message_bus.rs +++ /dev/null @@ -1,173 +0,0 @@ -/** - * MessageBus - Central communication hub (Bus = Local OS metaphor) - * - * Design principles from ChatGPT discussion: - * - Always present in P2PBox (even for network transport) - * - Handles local routing, subscription, monitoring - * - Singleton pattern for process-wide message coordination - * - Synchronous-first implementation - * - * NyaMesh inspiration: - * - InProcessMessageBus singleton pattern - * - Node registration/unregistration - * - Statistics tracking - */ - -use std::collections::HashMap; -use std::sync::{Arc, Mutex, RwLock}; -use crate::NyashBox; - -/// Message structure for internal routing -#[derive(Debug)] -pub struct BusMessage { - pub from: String, - pub to: String, - pub intent: String, - pub data: Box, - pub timestamp: std::time::SystemTime, -} - -impl Clone for BusMessage { - fn clone(&self) -> Self { - Self { - from: self.from.clone(), - to: self.to.clone(), - intent: self.intent.clone(), - data: self.data.clone_box(), // NyashBoxのclone_box()メソッドを使用 - timestamp: self.timestamp, - } - } -} - -/// Node registration information -struct NodeInfo { - node_id: String, - callbacks: HashMap>>, -} - -/// Central MessageBus - handles all local message routing -pub struct MessageBus { - /// Registered nodes in this process - nodes: RwLock>>>, - - /// Bus-level statistics - stats: Mutex, -} - -#[derive(Debug, Clone, Default)] -pub struct BusStats { - pub messages_routed: u64, - pub routing_errors: u64, - pub nodes_registered: u64, - pub total_callbacks: u64, -} - -impl MessageBus { - /// Create new MessageBus instance - pub fn new() -> Self { - Self { - nodes: RwLock::new(HashMap::new()), - stats: Mutex::new(BusStats::default()), - } - } - - /// Register a node in the message bus - pub fn register_node(&self, node_id: &str) -> Result<(), String> { - let mut nodes = self.nodes.write().unwrap(); - - if nodes.contains_key(node_id) { - return Err(format!("Node '{}' already registered", node_id)); - } - - let node_info = NodeInfo { - node_id: node_id.to_string(), - callbacks: HashMap::new(), - }; - - nodes.insert(node_id.to_string(), Arc::new(Mutex::new(node_info))); - - // Update stats - let mut stats = self.stats.lock().unwrap(); - stats.nodes_registered += 1; - - Ok(()) - } - - /// Unregister a node from the message bus - pub fn unregister_node(&self, node_id: &str) { - let mut nodes = self.nodes.write().unwrap(); - nodes.remove(node_id); - } - - /// Check if a node is registered locally - pub fn has_node(&self, node_id: &str) -> bool { - let nodes = self.nodes.read().unwrap(); - nodes.contains_key(node_id) - } - - /// Route message to local node - pub fn route(&self, message: BusMessage) -> Result<(), String> { - let nodes = self.nodes.read().unwrap(); - - if let Some(node) = nodes.get(&message.to) { - let node = node.lock().unwrap(); - - // Find callbacks for this intent - if let Some(callbacks) = node.callbacks.get(&message.intent) { - for callback in callbacks { - callback(&message); - } - } - - // Update stats - let mut stats = self.stats.lock().unwrap(); - stats.messages_routed += 1; - - Ok(()) - } else { - let mut stats = self.stats.lock().unwrap(); - stats.routing_errors += 1; - Err(format!("Node '{}' not found for routing", message.to)) - } - } - - /// Register callback for specific intent on a node - pub fn on(&self, node_id: &str, intent: &str, callback: Box) -> Result<(), String> { - let nodes = self.nodes.read().unwrap(); - - if let Some(node) = nodes.get(node_id) { - let mut node = node.lock().unwrap(); - node.callbacks.entry(intent.to_string()).or_insert_with(Vec::new).push(callback); - - // Update stats - let mut stats = self.stats.lock().unwrap(); - stats.total_callbacks += 1; - - Ok(()) - } else { - Err(format!("Node '{}' not found for callback registration", node_id)) - } - } - - /// Get list of registered nodes - pub fn get_registered_nodes(&self) -> Vec { - let nodes = self.nodes.read().unwrap(); - nodes.keys().cloned().collect() - } - - /// Get bus statistics - pub fn get_stats(&self) -> BusStats { - let stats = self.stats.lock().unwrap(); - stats.clone() - } -} - -use std::sync::OnceLock; - -/// Global MessageBus singleton -static GLOBAL_MESSAGE_BUS: OnceLock> = OnceLock::new(); - -/// Get global message bus instance -pub fn get_global_message_bus() -> Arc { - GLOBAL_MESSAGE_BUS.get_or_init(|| Arc::new(MessageBus::new())).clone() -} \ No newline at end of file diff --git a/src/transport_trait.rs b/src/transport_trait.rs deleted file mode 100644 index a19e1778..00000000 --- a/src/transport_trait.rs +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Transport trait abstraction - NyaMesh style implementation - * - * Design principles from NyaMesh: - * - Transport = NIC (Network Interface Card) - handles communication method only - * - Bus = Local OS - handles routing, subscription, monitoring - * - Clean separation between transport mechanism and message routing - * - * Based on ChatGPT discussion P2PBox architecture: - * - P2PBox always has MessageBus (even for network transport) - * - Transport abstraction allows switching InProcess/WebSocket/WebRTC - * - Synchronous-first implementation strategy - */ - -use crate::NyashBox; -use crate::transports::InProcessTransport; - -/// Transport trait - represents different communication mechanisms -/// Like NyaMesh's TransportInterface, this abstracts the "how to send" part -pub trait Transport: Send + Sync { - /// Initialize the transport (async-compatible but synchronous first) - fn initialize(&mut self) -> Result<(), String>; - - /// Send message through this transport mechanism - /// to: target node ID - /// intent: message intent type - /// data: message payload - fn send(&self, to: &str, intent: &str, data: Box) -> Result<(), String>; - - /// Get transport type identifier (e.g., "inprocess", "websocket", "webrtc") - fn transport_type(&self) -> &'static str; - - /// Check if transport is ready - fn is_ready(&self) -> bool; - - /// Shutdown transport cleanly - fn shutdown(&mut self) -> Result<(), String>; - - /// Get transport statistics - fn get_stats(&self) -> TransportStats; -} - -/// Transport statistics - standardized across all transport types -#[derive(Debug, Clone)] -pub struct TransportStats { - pub transport_type: String, - pub messages_sent: u64, - pub messages_received: u64, - pub errors: u64, - pub is_ready: bool, -} - -impl TransportStats { - pub fn new(transport_type: &str) -> Self { - Self { - transport_type: transport_type.to_string(), - messages_sent: 0, - messages_received: 0, - errors: 0, - is_ready: false, - } - } -} - -/// TransportKind - 通信方式の選択(Nyash同期・シンプル版) -#[derive(Debug, Clone)] -pub enum TransportKind { - InProcess, // プロセス内通信(最初に実装) - WebSocket, // WebSocket通信(将来実装) - WebRTC, // P2P直接通信(将来実装) -} - -/// シンプルファクトリ関数 -pub fn create_transport(kind: TransportKind, node_id: &str) -> Box { - match kind { - TransportKind::InProcess => Box::new(InProcessTransport::new(node_id.to_string())), - TransportKind::WebSocket => todo!("WebSocket transport - 将来実装"), - TransportKind::WebRTC => todo!("WebRTC transport - 将来実装"), - } -} \ No newline at end of file diff --git a/src/transports/in_process_transport.rs b/src/transports/in_process_transport.rs deleted file mode 100644 index 19ed6419..00000000 --- a/src/transports/in_process_transport.rs +++ /dev/null @@ -1,134 +0,0 @@ -/** - * InProcessTransport - Local process communication transport - * - * Based on NyaMesh InProcessTransport design: - * - Synchronous-first implementation (parallelSafe flag support) - * - Direct function pointer callbacks (no async complexity) - * - Simple message routing through global MessageBus - * - * Key features from NyaMesh: - * - parallelSafe = false by default (GUI thread safe) - * - Direct callback execution - * - Statistics tracking - */ - -use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; -use crate::transport_trait::{Transport, TransportStats}; -use crate::message_bus::{get_global_message_bus, BusMessage}; -use crate::NyashBox; - -/// InProcessTransport - for local communication within same process -pub struct InProcessTransport { - /// Node ID for this transport - node_id: String, - - /// Whether transport is initialized - initialized: AtomicBool, - - /// Statistics - messages_sent: AtomicU64, - messages_received: AtomicU64, - errors: AtomicU64, -} - -impl InProcessTransport { - /// Create new InProcessTransport with given node ID - pub fn new(node_id: String) -> Self { - Self { - node_id, - initialized: AtomicBool::new(false), - messages_sent: AtomicU64::new(0), - messages_received: AtomicU64::new(0), - errors: AtomicU64::new(0), - } - } - - /// Get node ID - pub fn node_id(&self) -> &str { - &self.node_id - } -} - -impl Transport for InProcessTransport { - fn initialize(&mut self) -> Result<(), String> { - if self.initialized.load(Ordering::Relaxed) { - return Ok(()); - } - - // Register with global message bus - let bus = get_global_message_bus(); - bus.register_node(&self.node_id)?; - - self.initialized.store(true, Ordering::Relaxed); - Ok(()) - } - - fn send(&self, to: &str, intent: &str, data: Box) -> Result<(), String> { - if !self.initialized.load(Ordering::Relaxed) { - self.errors.fetch_add(1, Ordering::Relaxed); - return Err("Transport not initialized".to_string()); - } - - // Create bus message - let message = BusMessage { - from: self.node_id.clone(), - to: to.to_string(), - intent: intent.to_string(), - data, - timestamp: std::time::SystemTime::now(), - }; - - // Route through global message bus - let bus = get_global_message_bus(); - - // Check if target is local - if bus.has_node(to) { - // Local routing - direct through bus - match bus.route(message) { - Ok(_) => { - self.messages_sent.fetch_add(1, Ordering::Relaxed); - Ok(()) - } - Err(e) => { - self.errors.fetch_add(1, Ordering::Relaxed); - Err(e) - } - } - } else { - // Target not found locally - self.errors.fetch_add(1, Ordering::Relaxed); - Err(format!("Target node '{}' not found in process", to)) - } - } - - fn transport_type(&self) -> &'static str { - "inprocess" - } - - fn is_ready(&self) -> bool { - self.initialized.load(Ordering::Relaxed) - } - - fn shutdown(&mut self) -> Result<(), String> { - if !self.initialized.load(Ordering::Relaxed) { - return Ok(()); - } - - // Unregister from global message bus - let bus = get_global_message_bus(); - bus.unregister_node(&self.node_id); - - self.initialized.store(false, Ordering::Relaxed); - Ok(()) - } - - fn get_stats(&self) -> TransportStats { - TransportStats { - transport_type: self.transport_type().to_string(), - messages_sent: self.messages_sent.load(Ordering::Relaxed), - messages_received: self.messages_received.load(Ordering::Relaxed), - errors: self.errors.load(Ordering::Relaxed), - is_ready: self.is_ready(), - } - } -} \ No newline at end of file diff --git a/src/transports/mod.rs b/src/transports/mod.rs deleted file mode 100644 index c3796659..00000000 --- a/src/transports/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Transport implementations module - * - * Contains various transport implementations: - * - InProcessTransport: For local communication within same process - * - Future: WebSocketTransport, WebRTCTransport, etc. - */ - -pub mod in_process_transport; - -pub use in_process_transport::InProcessTransport; \ No newline at end of file diff --git a/test_new_p2p_box.rs b/test_new_p2p_box.rs deleted file mode 100644 index 620f0cd3..00000000 --- a/test_new_p2p_box.rs +++ /dev/null @@ -1,119 +0,0 @@ -/** - * NewP2PBox天才アルゴリズムテスト - * - * 1. ローカル配送テスト(Bus経由) - * 2. リモート配送テスト(Transport経由) - * 3. イベント購読テスト - * - * MethodBox統合前の基本動作確認 - */ - -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -// Nyashモジュールをインポート -use nyash_rust::boxes::{NewP2PBox, MessageIntentBox, StringBox}; -use nyash_rust::transport_trait::TransportKind; -use nyash_rust::message_bus::get_global_message_bus; - -fn main() { - println!("🚀 NewP2PBox天才アルゴリズムテスト開始"); - - // テスト1: 基本的なP2PBox作成 - test_basic_creation(); - - // テスト2: ローカル配送(Bus経由) - test_local_delivery(); - - // テスト3: イベント購読とコールバック - test_event_subscription(); - - println!("✅ 全テスト完了!"); -} - -fn test_basic_creation() { - println!("\n=== テスト1: 基本的なP2PBox作成 ==="); - - let alice = NewP2PBox::new("alice", TransportKind::InProcess); - let bob = NewP2PBox::new("bob", TransportKind::InProcess); - - println!("✅ Alice作成: {}", alice.get_node_id()); - println!("✅ Bob作成: {}", bob.get_node_id()); - - assert_eq!(alice.get_node_id(), "alice"); - assert_eq!(bob.get_node_id(), "bob"); -} - -fn test_local_delivery() { - println!("\n=== テスト2: ローカル配送テスト ==="); - - let alice = NewP2PBox::new("alice_local", TransportKind::InProcess); - let bob = NewP2PBox::new("bob_local", TransportKind::InProcess); - - // メッセージ作成 - let mut message = MessageIntentBox::new("greeting"); - message.set("text", Box::new(StringBox::new("Hello Bob!"))); - message.set("from_user", Box::new(StringBox::new("Alice"))); - - println!("📨 Aliceからメッセージ送信中..."); - - // Busが両ノードを認識しているかチェック - let bus = get_global_message_bus(); - println!("🚌 Alice認識: {}", bus.has_node("alice_local")); - println!("🚌 Bob認識: {}", bus.has_node("bob_local")); - - // ローカル配送テスト - match alice.send("bob_local", &message) { - Ok(()) => println!("✅ ローカル配送成功!"), - Err(e) => println!("❌ ローカル配送エラー: {}", e), - } -} - -fn test_event_subscription() { - println!("\n=== テスト3: イベント購読テスト ==="); - - let alice = NewP2PBox::new("alice_events", TransportKind::InProcess); - let bob = NewP2PBox::new("bob_events", TransportKind::InProcess); - - // 受信メッセージカウンター - let message_count = Arc::new(Mutex::new(0)); - let count_clone = Arc::clone(&message_count); - - // Bobにイベントリスナー登録 - bob.on("test_message", Box::new(move |intent_box: &MessageIntentBox| { - let mut count = count_clone.lock().unwrap(); - *count += 1; - println!("🎧 Bob received message #{}: intent={}", *count, intent_box.intent); - - // メッセージ内容確認 - if let Some(text_box) = intent_box.get("text") { - if let Some(text) = text_box.as_any().downcast_ref::() { - println!(" 📝 Content: {}", text.value); - } - } - })); - - println!("✅ Bobにイベントリスナー登録完了"); - - // Aliceからメッセージ送信 - let mut test_message = MessageIntentBox::new("test_message"); - test_message.set("text", Box::new(StringBox::new("Test message from Alice!"))); - - println!("📤 Aliceからテストメッセージ送信..."); - match alice.send("bob_events", &test_message) { - Ok(()) => println!("✅ メッセージ送信成功"), - Err(e) => println!("❌ メッセージ送信エラー: {}", e), - } - - // 少し待ってからカウンターチェック - thread::sleep(Duration::from_millis(100)); - let final_count = *message_count.lock().unwrap(); - println!("📊 最終受信メッセージ数: {}", final_count); - - if final_count > 0 { - println!("✅ イベント購読システム動作確認完了!"); - } else { - println!("⚠️ メッセージが受信されませんでした(非同期処理の可能性)"); - } -} \ No newline at end of file