Implement complete P2P communication system with modern architecture

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-12 01:35:36 +00:00
parent 15b2d230ab
commit 861201cab4
10 changed files with 582 additions and 348 deletions

View File

@ -1,32 +1,42 @@
/*! 📡 P2P通信メソッド実装
/*! 📡 P2P通信メソッド実装 (NEW ARCHITECTURE)
* IntentBoxとP2PBoxのNyashインタープリター統合
* Arc<Mutex>パターン対応版
*/
use crate::interpreter::core::NyashInterpreter;
use crate::interpreter::core::RuntimeError;
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, StringBox};
use crate::box_trait::{NyashBox, StringBox, BoolBox};
use crate::boxes::{IntentBox, P2PBox};
use crate::method_box::MethodBox;
impl NyashInterpreter {
/// IntentBoxのメソッド実行
/// IntentBoxのメソッド実行 (Arc<Mutex>版)
pub(in crate::interpreter) fn execute_intent_box_method(
&mut self,
intent_box: &IntentBox,
method: &str,
_arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
let data = intent_box.lock().map_err(|_| RuntimeError::UndefinedVariable {
name: "Failed to lock IntentBox".to_string(),
})?;
match method {
// 基本情報取得
"getType" | "type" => {
Ok(Box::new(StringBox::new("IntentBox")))
// メッセージ名取得
"getName" | "name" => {
Ok(Box::new(StringBox::new(data.name.clone())))
}
// メッセージ処理(テスト用
"processMessages" => {
let messages = intent_box.process_messages();
Ok(Box::new(StringBox::new(format!("Processed {} messages", messages.len()))))
// ペイロード取得JSON文字列として
"getPayload" | "payload" => {
let payload_str = data.payload.to_string();
Ok(Box::new(StringBox::new(payload_str)))
}
// 型情報取得
"getType" | "type" => {
Ok(Box::new(StringBox::new("IntentBox")))
}
_ => Err(RuntimeError::UndefinedVariable {
@ -35,79 +45,68 @@ impl NyashInterpreter {
}
}
/// P2PBoxのメソッド実行
/// P2PBoxのメソッド実行 (Arc<Mutex>版)
pub(in crate::interpreter) fn execute_p2p_box_method(
&mut self,
p2p_box: &P2PBox,
method: &str,
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
let data = p2p_box.lock().map_err(|_| RuntimeError::UndefinedVariable {
name: "Failed to lock P2PBox".to_string(),
})?;
match method {
// ードID取得
"getNodeId" | "getId" => {
Ok(Box::new(StringBox::new(p2p_box.get_node_id())))
Ok(Box::new(StringBox::new(data.get_node_id().to_string())))
}
// メッセージ送信
"send" => {
if arguments.len() < 3 {
return Err(RuntimeError::InvalidOperation {
message: "send requires 3 arguments: intent, data, target".to_string(),
});
}
let intent = self.execute_expression(&arguments[0])?;
let data = self.execute_expression(&arguments[1])?;
let target = self.execute_expression(&arguments[2])?;
if let Some(intent_str) = intent.as_any().downcast_ref::<StringBox>() {
if let Some(target_str) = target.as_any().downcast_ref::<StringBox>() {
return Ok(p2p_box.send(&intent_str.value, data, &target_str.value));
}
}
Err(RuntimeError::TypeError {
message: "send requires string arguments for intent and target".to_string(),
})
// トランスポート種類取得
"getTransportType" | "transport" => {
Ok(Box::new(StringBox::new(data.get_transport_type())))
}
// リスナー登録
"on" => {
if arguments.len() < 2 {
return Err(RuntimeError::InvalidOperation {
message: "on requires 2 arguments: intent, callback".to_string(),
});
}
let intent = self.execute_expression(&arguments[0])?;
let callback = self.execute_expression(&arguments[1])?;
if let Some(intent_str) = intent.as_any().downcast_ref::<StringBox>() {
return Ok(p2p_box.on(&intent_str.value, callback));
}
Err(RuntimeError::TypeError {
message: "on requires string argument for intent".to_string(),
})
}
// リスナー解除
"off" => {
// ノード到達可能性確認
"isReachable" => {
if arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: "off requires 1 argument: intent".to_string(),
return Err(RuntimeError::UndefinedVariable {
name: "isReachable requires node_id argument".to_string(),
});
}
let intent = self.execute_expression(&arguments[0])?;
if let Some(intent_str) = intent.as_any().downcast_ref::<StringBox>() {
return Ok(p2p_box.off(&intent_str.value));
let node_id_result = self.execute_expression(&arguments[0])?;
let node_id = node_id_result.to_string_box().value;
let reachable = data.is_reachable(&node_id);
Ok(Box::new(BoolBox::new(reachable)))
}
// send メソッド実装
"send" => {
if arguments.len() < 2 {
return Err(RuntimeError::UndefinedVariable {
name: "send requires (to, intent) arguments".to_string(),
});
}
Err(RuntimeError::TypeError {
message: "off requires string argument for intent".to_string(),
})
let to_result = self.execute_expression(&arguments[0])?;
let to = to_result.to_string_box().value;
let intent_result = self.execute_expression(&arguments[1])?;
// IntentBoxかチェック
if let Some(intent_box) = intent_result.as_any().downcast_ref::<IntentBox>() {
match data.send(&to, intent_box.clone()) {
Ok(_) => Ok(Box::new(StringBox::new("sent"))),
Err(e) => Err(RuntimeError::UndefinedVariable {
name: format!("Send failed: {:?}", e),
})
}
} else {
Err(RuntimeError::UndefinedVariable {
name: "Second argument must be an IntentBox".to_string(),
})
}
}
_ => Err(RuntimeError::UndefinedVariable {

View File

@ -443,55 +443,72 @@ impl NyashInterpreter {
}
"IntentBox" => {
// IntentBoxは引数なしで作成(デフォルトローカル通信)
if !arguments.is_empty() {
// IntentBoxは引数2個name, payloadで作成
if arguments.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: format!("IntentBox constructor expects 0 arguments, got {}", arguments.len()),
message: format!("IntentBox constructor expects 2 arguments (name, payload), got {}", arguments.len()),
});
}
let intent_box = crate::boxes::IntentBox::new();
// メッセージ名
let name_value = self.execute_expression(&arguments[0])?;
let name = if let Some(name_str) = name_value.as_any().downcast_ref::<StringBox>() {
name_str.value.clone()
} else {
return Err(RuntimeError::TypeError {
message: "IntentBox constructor requires string name as first argument".to_string(),
});
};
// ペイロードJSON形式
let payload_value = self.execute_expression(&arguments[1])?;
let payload = match payload_value.to_string_box().value.parse::<serde_json::Value>() {
Ok(json) => json,
Err(_) => {
// 文字列として保存
serde_json::Value::String(payload_value.to_string_box().value)
}
};
let intent_box = crate::boxes::intent_box::IntentBoxData::new(name, payload);
return Ok(Box::new(intent_box) as Box<dyn NyashBox>);
}
"P2PBox" => {
// P2PBoxは引数2個node_id, intent_box)で作成
if arguments.is_empty() {
// P2PBoxは引数2個node_id, transport_type)で作成
if arguments.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: "P2PBox requires at least 1 argument (node_id)".to_string(),
message: format!("P2PBox constructor expects 2 arguments (node_id, transport_type), got {}", arguments.len()),
});
}
// 引数を評価
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()
// ード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::<StringBox>() {
id_str.value.clone()
} else {
return Err(RuntimeError::TypeError {
message: "P2PBox first argument must be a string (node_id)".to_string(),
message: "P2PBox constructor requires string node_id as first argument".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(),
});
}
// トランスポート種類
let transport_value = self.execute_expression(&arguments[1])?;
let transport_str = if let Some(t_str) = transport_value.as_any().downcast_ref::<StringBox>() {
t_str.value.clone()
} else {
// デフォルトのIntentBoxを作成
std::sync::Arc::new(crate::boxes::IntentBox::new())
return Err(RuntimeError::TypeError {
message: "P2PBox constructor requires string transport_type as second argument".to_string(),
});
};
let p2p_box = crate::boxes::P2PBox::new(node_id, intent_box);
return Ok(Box::new(p2p_box));
let transport_kind = transport_str.parse::<crate::boxes::p2p_box::TransportKind>()
.map_err(|e| RuntimeError::InvalidOperation {
message: format!("Invalid transport type '{}': {}", transport_str, e),
})?;
let p2p_box = crate::boxes::p2p_box::P2PBoxData::new(node_id, transport_kind);
return Ok(Box::new(p2p_box) as Box<dyn NyashBox>);
}
"StreamBox" => {
// StreamBoxは引数なしで作成