🚀 feat: P2PBox/IntentBox実装 - NyaMesh通信基盤の第一歩

## 🎯 概要
NyaMeshプロジェクトの基盤となるP2PBox/IntentBoxを実装。
シンプルなsend/onインターフェースで通信ノード間のメッセージングを実現。

##  新機能
- **IntentBox**: 通信世界を定義するコンテナ
  - Transportトレイトで通信方式を抽象化
  - LocalTransport実装(プロセス内通信)
  - 将来のWebSocket/SharedMemory拡張に対応

- **P2PBox**: 通信ノードの実装
  - send(intent, data, target) - 特定ノードへ送信
  - broadcast(intent, data) - 全ノードへ配信
  - on(intent, callback) - リスナー登録
  - off(intent) - リスナー解除
  - 同一intentに複数リスナー登録可能

## 🔧 技術詳細
- Arc<Mutex>パターンで完全なスレッドセーフティ
- Arc<P2PBoxInner>構造でBox型システムとの整合性確保
- インタープリター完全統合(new/メソッド呼び出し)

## 🧪 テスト
- test_p2p_basic.nyash - 基本機能検証
- test_p2p_message_types.nyash - 各種データ型対応
- test_p2p_edge_cases.nyash - エラー処理
- test_p2p_callback_demo.nyash - 実用例

## 📝 TODO (将来拡張)
- WebSocket/SharedMemoryトランスポート
- コールバック実行(MethodBox統合待ち)
- ノード登録管理システム

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-11 05:11:52 +09:00
parent 832b2e5953
commit 21eceed324
11 changed files with 898 additions and 7 deletions

View File

@ -442,6 +442,58 @@ impl NyashInterpreter {
});
}
}
"IntentBox" => {
// IntentBoxは引数なしで作成デフォルトローカル通信
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("IntentBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let intent_box = crate::boxes::IntentBox::new();
return Ok(Box::new(intent_box) as Box<dyn NyashBox>);
}
"P2PBox" => {
// P2PBoxは引数2個node_id, intent_boxで作成
if arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: "P2PBox requires at least 1 argument (node_id)".to_string(),
});
}
// 引数を評価
let mut arg_values = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
// 第1引数: ードID
let node_id = if let Some(str_box) = arg_values[0].as_any().downcast_ref::<StringBox>() {
str_box.value.clone()
} else {
return Err(RuntimeError::TypeError {
message: "P2PBox first argument must be a string (node_id)".to_string(),
});
};
// 第2引数: IntentBox省略時はデフォルト
let intent_box = if arg_values.len() > 1 {
if let Some(intent) = arg_values[1].as_any().downcast_ref::<crate::boxes::IntentBox>() {
std::sync::Arc::new(intent.clone())
} else {
return Err(RuntimeError::TypeError {
message: "P2PBox second argument must be an IntentBox".to_string(),
});
}
} else {
// デフォルトのIntentBoxを作成
std::sync::Arc::new(crate::boxes::IntentBox::new())
};
let p2p_box = crate::boxes::P2PBox::new(node_id, intent_box);
return Ok(Box::new(p2p_box));
}
"StreamBox" => {
// StreamBoxは引数なしで作成
if !arguments.is_empty() {
@ -694,7 +746,8 @@ impl NyashInterpreter {
"FileBox" | "ResultBox" | "FutureBox" | "ChannelBox" | "MathBox" |
"TimeBox" | "DateTimeBox" | "TimerBox" | "RandomBox" | "SoundBox" |
"DebugBox" | "MethodBox" | "NullBox" | "ConsoleBox" | "FloatBox" |
"BufferBox" | "RegexBox" | "JSONBox" | "StreamBox" | "HTTPClientBox"
"BufferBox" | "RegexBox" | "JSONBox" | "StreamBox" | "HTTPClientBox" |
"IntentBox" | "P2PBox"
);
// Web専用BoxWASM環境のみ