## 🎯 Problem Identification Complete - SocketBox method calls (bind, isServer, toString) cause infinite blocking - Root cause: Method resolution pipeline deadlock before execute_socket_method - Other Box types (ArrayBox, StringBox, MapBox) work normally - Arc<Mutex> reference sharing confirmed working (Arc addresses match = true) ## 🔧 Debug Infrastructure Added - Comprehensive debug logging in socket_box.rs (bind, isServer, clone, toString) - Method call tracing in http_methods.rs - Deadlock detection points identified at interpreter expressions.rs:462-464 ## 📋 Issue #76 Created for Copilot Investigation - Systematic root cause analysis requirements (Architecture→Parser→Runtime levels) - Comprehensive test cases: minimal/comprehensive/comparison scenarios - Strict prohibition of band-aid fixes - architectural analysis required - Hypothesis: Multiple Arc<Mutex> combinations causing circular deadlock ## 🧪 Test Suite Added - test_socket_deadlock_minimal.nyash: Minimal reproduction case - test_socket_methods_comprehensive.nyash: All methods deadlock verification - test_other_boxes_working.nyash: Normal Box operation confirmation - SOCKETBOX_ISSUE_REPRODUCTION.md: Complete reproduction guide ## 📊 Impact Assessment - Phase 9 HTTP server implementation completely blocked - SocketBox functionality entirely non-functional - Critical blocker for production readiness - Requires immediate systematic investigation 🔥 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1167 lines
53 KiB
Rust
1167 lines
53 KiB
Rust
/*!
|
||
* Expression Processing Module
|
||
*
|
||
* Extracted from core.rs lines 408-787 (~380 lines)
|
||
* Handles expression evaluation, binary operations, method calls, and field access
|
||
* Core philosophy: "Everything is Box" with clean expression evaluation
|
||
*/
|
||
|
||
use super::*;
|
||
use crate::ast::UnaryOperator;
|
||
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
||
use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
|
||
use crate::box_trait::{BoolBox, SharedNyashBox};
|
||
use crate::operator_traits::OperatorResolver;
|
||
use std::sync::Arc;
|
||
// TODO: Fix NullBox import issue later
|
||
// use crate::NullBox;
|
||
|
||
impl NyashInterpreter {
|
||
/// 式を実行 - Expression evaluation engine
|
||
pub(super) fn execute_expression(&mut self, expression: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
match expression {
|
||
ASTNode::Literal { value, .. } => {
|
||
Ok(value.to_nyash_box())
|
||
}
|
||
|
||
ASTNode::Variable { name, .. } => {
|
||
// 🌍 革命的変数解決:local変数 → GlobalBoxフィールド → エラー
|
||
let shared_var = self.resolve_variable(name)
|
||
.map_err(|_| RuntimeError::UndefinedVariableAt {
|
||
name: name.clone(),
|
||
span: expression.span()
|
||
})?;
|
||
Ok((*shared_var).clone_box()) // Convert for external interface
|
||
}
|
||
|
||
ASTNode::BinaryOp { operator, left, right, .. } => {
|
||
self.execute_binary_op(operator, left, right)
|
||
}
|
||
|
||
ASTNode::UnaryOp { operator, operand, .. } => {
|
||
self.execute_unary_op(operator, operand)
|
||
}
|
||
|
||
ASTNode::AwaitExpression { expression, .. } => {
|
||
self.execute_await(expression)
|
||
}
|
||
|
||
ASTNode::MethodCall { object, method, arguments, .. } => {
|
||
let result = self.execute_method_call(object, method, arguments);
|
||
result
|
||
}
|
||
|
||
ASTNode::FieldAccess { object, field, .. } => {
|
||
let shared_result = self.execute_field_access(object, field)?;
|
||
Ok((*shared_result).clone_box()) // Convert Arc to Box for external interface
|
||
}
|
||
|
||
ASTNode::New { class, arguments, type_arguments, .. } => {
|
||
self.execute_new(class, arguments, type_arguments)
|
||
}
|
||
|
||
ASTNode::This { .. } => {
|
||
// 🌍 革命的this解決:local変数から取得
|
||
let shared_this = self.resolve_variable("me")
|
||
.map_err(|_| RuntimeError::InvalidOperation {
|
||
message: "'this' is only available inside methods".to_string(),
|
||
})?;
|
||
Ok((*shared_this).clone_box()) // Convert for external interface
|
||
}
|
||
|
||
ASTNode::Me { .. } => {
|
||
|
||
// 🌍 革命的me解決:local変数から取得(thisと同じ)
|
||
let shared_me = self.resolve_variable("me")
|
||
.map_err(|_| RuntimeError::InvalidOperation {
|
||
message: "'me' is only available inside methods".to_string(),
|
||
})?;
|
||
|
||
Ok((*shared_me).clone_box()) // Convert for external interface
|
||
}
|
||
|
||
ASTNode::ThisField { field, .. } => {
|
||
// 🌍 革命的this.fieldアクセス:local変数から取得
|
||
let this_value = self.resolve_variable("me")
|
||
.map_err(|_| RuntimeError::InvalidOperation {
|
||
message: "'this' is not bound in the current context".to_string(),
|
||
})?;
|
||
|
||
if let Some(instance) = (*this_value).as_any().downcast_ref::<InstanceBox>() {
|
||
let shared_field = instance.get_field(field)
|
||
.ok_or_else(|| RuntimeError::InvalidOperation {
|
||
message: format!("Field '{}' not found on this", field)
|
||
})?;
|
||
Ok((*shared_field).clone_box()) // Convert for external interface
|
||
} else {
|
||
Err(RuntimeError::TypeError {
|
||
message: "'this' is not an instance".to_string(),
|
||
})
|
||
}
|
||
}
|
||
|
||
ASTNode::MeField { field, .. } => {
|
||
// 🌍 革命的me.fieldアクセス:local変数から取得
|
||
let me_value = self.resolve_variable("me")
|
||
.map_err(|_| RuntimeError::InvalidOperation {
|
||
message: "'this' is not bound in the current context".to_string(),
|
||
})?;
|
||
|
||
if let Some(instance) = (*me_value).as_any().downcast_ref::<InstanceBox>() {
|
||
let shared_field = instance.get_field(field)
|
||
.ok_or_else(|| RuntimeError::InvalidOperation {
|
||
message: format!("Field '{}' not found on me", field)
|
||
})?;
|
||
Ok((*shared_field).clone_box()) // Convert for external interface
|
||
} else {
|
||
Err(RuntimeError::TypeError {
|
||
message: "'this' is not an instance".to_string(),
|
||
})
|
||
}
|
||
}
|
||
|
||
ASTNode::FunctionCall { name, arguments, .. } => {
|
||
self.execute_function_call(name, arguments)
|
||
}
|
||
|
||
ASTNode::Arrow { sender, receiver, .. } => {
|
||
self.execute_arrow(sender, receiver)
|
||
}
|
||
|
||
ASTNode::Include { filename, .. } => {
|
||
self.execute_include(filename)?;
|
||
Ok(Box::new(VoidBox::new()))
|
||
}
|
||
|
||
ASTNode::FromCall { parent, method, arguments, .. } => {
|
||
self.execute_from_call(parent, method, arguments)
|
||
}
|
||
|
||
_ => Err(RuntimeError::InvalidOperation {
|
||
message: format!("Cannot execute {:?} as expression", expression.node_type()),
|
||
}),
|
||
}
|
||
}
|
||
|
||
/// 二項演算を実行 - Binary operation processing
|
||
pub(super) fn execute_binary_op(&mut self, op: &BinaryOperator, left: &ASTNode, right: &ASTNode)
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
let left_val = self.execute_expression(left)?;
|
||
let right_val = self.execute_expression(right)?;
|
||
|
||
match op {
|
||
BinaryOperator::Add => {
|
||
// 🚀 New trait-based operator resolution system!
|
||
OperatorResolver::resolve_add(left_val.as_ref(), right_val.as_ref())
|
||
.map_err(|e| RuntimeError::InvalidOperation { message: e.to_string() })
|
||
}
|
||
|
||
BinaryOperator::Equal => {
|
||
let result = left_val.equals(right_val.as_ref());
|
||
Ok(Box::new(result))
|
||
}
|
||
|
||
BinaryOperator::NotEqual => {
|
||
let result = left_val.equals(right_val.as_ref());
|
||
Ok(Box::new(BoolBox::new(!result.value)))
|
||
}
|
||
|
||
BinaryOperator::And => {
|
||
let left_bool = self.is_truthy(&left_val);
|
||
if !left_bool {
|
||
Ok(Box::new(BoolBox::new(false)))
|
||
} else {
|
||
let right_bool = self.is_truthy(&right_val);
|
||
Ok(Box::new(BoolBox::new(right_bool)))
|
||
}
|
||
}
|
||
|
||
BinaryOperator::Or => {
|
||
let left_bool = self.is_truthy(&left_val);
|
||
if left_bool {
|
||
Ok(Box::new(BoolBox::new(true)))
|
||
} else {
|
||
let right_bool = self.is_truthy(&right_val);
|
||
Ok(Box::new(BoolBox::new(right_bool)))
|
||
}
|
||
}
|
||
|
||
BinaryOperator::Subtract => {
|
||
// 🚀 New trait-based subtraction
|
||
OperatorResolver::resolve_sub(left_val.as_ref(), right_val.as_ref())
|
||
.map_err(|e| RuntimeError::InvalidOperation { message: e.to_string() })
|
||
}
|
||
|
||
BinaryOperator::Multiply => {
|
||
// 🚀 New trait-based multiplication
|
||
OperatorResolver::resolve_mul(left_val.as_ref(), right_val.as_ref())
|
||
.map_err(|e| RuntimeError::InvalidOperation { message: e.to_string() })
|
||
}
|
||
|
||
BinaryOperator::Divide => {
|
||
// 🚀 New trait-based division
|
||
OperatorResolver::resolve_div(left_val.as_ref(), right_val.as_ref())
|
||
.map_err(|e| RuntimeError::InvalidOperation { message: e.to_string() })
|
||
}
|
||
|
||
BinaryOperator::Less => {
|
||
let result = CompareBox::less(left_val.as_ref(), right_val.as_ref());
|
||
Ok(Box::new(result))
|
||
}
|
||
|
||
BinaryOperator::Greater => {
|
||
let result = CompareBox::greater(left_val.as_ref(), right_val.as_ref());
|
||
Ok(Box::new(result))
|
||
}
|
||
|
||
BinaryOperator::LessEqual => {
|
||
let result = CompareBox::less_equal(left_val.as_ref(), right_val.as_ref());
|
||
Ok(Box::new(result))
|
||
}
|
||
|
||
BinaryOperator::GreaterEqual => {
|
||
let result = CompareBox::greater_equal(left_val.as_ref(), right_val.as_ref());
|
||
Ok(Box::new(result))
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 単項演算を実行 - Unary operation processing
|
||
pub(super) fn execute_unary_op(&mut self, operator: &UnaryOperator, operand: &ASTNode)
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
let operand_val = self.execute_expression(operand)?;
|
||
|
||
match operator {
|
||
UnaryOperator::Minus => {
|
||
// 数値の符号反転
|
||
if let Some(int_box) = operand_val.as_any().downcast_ref::<IntegerBox>() {
|
||
Ok(Box::new(IntegerBox::new(-int_box.value)))
|
||
} else if let Some(float_box) = operand_val.as_any().downcast_ref::<FloatBox>() {
|
||
Ok(Box::new(FloatBox::new(-float_box.value)))
|
||
} else {
|
||
Err(RuntimeError::TypeError {
|
||
message: "Unary minus can only be applied to Integer or Float".to_string(),
|
||
})
|
||
}
|
||
}
|
||
UnaryOperator::Not => {
|
||
// 論理否定
|
||
if let Some(bool_box) = operand_val.as_any().downcast_ref::<BoolBox>() {
|
||
Ok(Box::new(BoolBox::new(!bool_box.value)))
|
||
} else {
|
||
// どんな値でもtruthyness判定してnot演算を適用
|
||
let is_truthy = self.is_truthy(&operand_val);
|
||
Ok(Box::new(BoolBox::new(!is_truthy)))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// メソッド呼び出しを実行 - Method call processing
|
||
pub(super) fn execute_method_call(&mut self, object: &ASTNode, method: &str, arguments: &[ASTNode])
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
|
||
// 🔥 static関数のチェック
|
||
if let ASTNode::Variable { name, .. } = object {
|
||
// static関数が存在するかチェック
|
||
let static_func = {
|
||
let static_funcs = self.shared.static_functions.read().unwrap();
|
||
if let Some(box_statics) = static_funcs.get(name) {
|
||
if let Some(func) = box_statics.get(method) {
|
||
Some(func.clone())
|
||
} else {
|
||
None
|
||
}
|
||
} else {
|
||
None
|
||
}
|
||
};
|
||
|
||
if let Some(static_func) = static_func {
|
||
// static関数を実行
|
||
if let ASTNode::FunctionDeclaration { params, body, .. } = static_func {
|
||
// 引数を評価
|
||
let mut arg_values = Vec::new();
|
||
for arg in arguments {
|
||
arg_values.push(self.execute_expression(arg)?);
|
||
}
|
||
|
||
// パラメータ数チェック
|
||
if arg_values.len() != params.len() {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!("Static method {}.{} expects {} arguments, got {}",
|
||
name, method, params.len(), arg_values.len()),
|
||
});
|
||
}
|
||
|
||
// 🌍 local変数スタックを保存・クリア(static関数呼び出し開始)
|
||
let saved_locals = self.save_local_vars();
|
||
self.local_vars.clear();
|
||
|
||
// 📤 outbox変数スタックも保存・クリア(static関数専用)
|
||
let saved_outbox = self.save_outbox_vars();
|
||
self.outbox_vars.clear();
|
||
|
||
// 引数をlocal変数として設定
|
||
for (param, value) in params.iter().zip(arg_values.iter()) {
|
||
self.declare_local_variable(param, value.clone_box());
|
||
}
|
||
|
||
// static関数の本体を実行
|
||
let mut result = Box::new(VoidBox::new()) as Box<dyn NyashBox>;
|
||
for statement in &body {
|
||
result = self.execute_statement(statement)?;
|
||
|
||
// return文チェック
|
||
if let super::ControlFlow::Return(return_val) = &self.control_flow {
|
||
result = return_val.clone_box();
|
||
self.control_flow = super::ControlFlow::None;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// local変数スタックを復元
|
||
self.restore_local_vars(saved_locals);
|
||
|
||
// outbox変数スタックを復元
|
||
self.restore_outbox_vars(saved_outbox);
|
||
|
||
return Ok(result);
|
||
}
|
||
}
|
||
}
|
||
|
||
// オブジェクトを評価(通常のメソッド呼び出し)
|
||
let obj_value = self.execute_expression(object)?;
|
||
|
||
// StringBox method calls
|
||
if let Some(string_box) = obj_value.as_any().downcast_ref::<StringBox>() {
|
||
return self.execute_string_method(string_box, method, arguments);
|
||
}
|
||
|
||
// IntegerBox method calls
|
||
if let Some(integer_box) = obj_value.as_any().downcast_ref::<IntegerBox>() {
|
||
return self.execute_integer_method(integer_box, method, arguments);
|
||
}
|
||
|
||
// FloatBox method calls
|
||
if let Some(float_box) = obj_value.as_any().downcast_ref::<FloatBox>() {
|
||
return self.execute_float_method(float_box, method, arguments);
|
||
}
|
||
|
||
// BoolBox method calls
|
||
if let Some(bool_box) = obj_value.as_any().downcast_ref::<BoolBox>() {
|
||
return self.execute_bool_method(bool_box, method, arguments);
|
||
}
|
||
|
||
// ArrayBox method calls
|
||
if let Some(array_box) = obj_value.as_any().downcast_ref::<ArrayBox>() {
|
||
return self.execute_array_method(array_box, method, arguments);
|
||
}
|
||
|
||
// BufferBox method calls
|
||
if let Some(buffer_box) = obj_value.as_any().downcast_ref::<BufferBox>() {
|
||
return self.execute_buffer_method(buffer_box, method, arguments);
|
||
}
|
||
|
||
// FileBox method calls
|
||
if let Some(file_box) = obj_value.as_any().downcast_ref::<crate::boxes::file::FileBox>() {
|
||
return self.execute_file_method(file_box, method, arguments);
|
||
}
|
||
|
||
// ResultBox method calls
|
||
if let Some(result_box) = obj_value.as_any().downcast_ref::<ResultBox>() {
|
||
return self.execute_result_method(result_box, method, arguments);
|
||
}
|
||
|
||
// FutureBox method calls
|
||
if let Some(future_box) = obj_value.as_any().downcast_ref::<FutureBox>() {
|
||
return self.execute_future_method(future_box, method, arguments);
|
||
}
|
||
|
||
// ChannelBox method calls
|
||
if let Some(channel_box) = obj_value.as_any().downcast_ref::<ChannelBox>() {
|
||
return self.execute_channel_method(channel_box, method, arguments);
|
||
}
|
||
|
||
// JSONBox method calls
|
||
if let Some(json_box) = obj_value.as_any().downcast_ref::<JSONBox>() {
|
||
return self.execute_json_method(json_box, method, arguments);
|
||
}
|
||
|
||
// HttpClientBox method calls
|
||
if let Some(http_box) = obj_value.as_any().downcast_ref::<HttpClientBox>() {
|
||
return self.execute_http_method(http_box, method, arguments);
|
||
}
|
||
|
||
// StreamBox method calls
|
||
if let Some(stream_box) = obj_value.as_any().downcast_ref::<StreamBox>() {
|
||
return self.execute_stream_method(stream_box, method, arguments);
|
||
}
|
||
|
||
// RegexBox method calls
|
||
if let Some(regex_box) = obj_value.as_any().downcast_ref::<RegexBox>() {
|
||
return self.execute_regex_method(regex_box, method, arguments);
|
||
}
|
||
|
||
// MathBox method calls
|
||
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
|
||
return self.execute_math_method(math_box, method, arguments);
|
||
}
|
||
|
||
// NullBox method calls
|
||
if let Some(null_box) = obj_value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>() {
|
||
return self.execute_null_method(null_box, method, arguments);
|
||
}
|
||
|
||
// TimeBox method calls
|
||
if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() {
|
||
return self.execute_time_method(time_box, method, arguments);
|
||
}
|
||
|
||
// DateTimeBox method calls
|
||
if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() {
|
||
return self.execute_datetime_method(datetime_box, method, arguments);
|
||
}
|
||
|
||
// TimerBox method calls
|
||
if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() {
|
||
return self.execute_timer_method(timer_box, method, arguments);
|
||
}
|
||
|
||
// MapBox method calls
|
||
if let Some(map_box) = obj_value.as_any().downcast_ref::<MapBox>() {
|
||
return self.execute_map_method(map_box, method, arguments);
|
||
}
|
||
|
||
// RandomBox method calls
|
||
if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() {
|
||
return self.execute_random_method(random_box, method, arguments);
|
||
}
|
||
|
||
// SoundBox method calls
|
||
if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() {
|
||
return self.execute_sound_method(sound_box, method, arguments);
|
||
}
|
||
|
||
// DebugBox method calls
|
||
if let Some(debug_box) = obj_value.as_any().downcast_ref::<DebugBox>() {
|
||
return self.execute_debug_method(debug_box, method, arguments);
|
||
}
|
||
|
||
// ConsoleBox method calls
|
||
if let Some(console_box) = obj_value.as_any().downcast_ref::<crate::boxes::console_box::ConsoleBox>() {
|
||
return self.execute_console_method(console_box, method, arguments);
|
||
}
|
||
|
||
// IntentBox method calls
|
||
if let Some(intent_box) = obj_value.as_any().downcast_ref::<IntentBox>() {
|
||
return self.execute_intent_box_method(intent_box, method, arguments);
|
||
}
|
||
|
||
// SocketBox method calls
|
||
if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() {
|
||
let result = self.execute_socket_method(socket_box, method, arguments)?;
|
||
|
||
// 🔧 FIX: Update stored variable for stateful SocketBox methods
|
||
// These methods modify the SocketBox internal state, so we need to update
|
||
// the stored variable/field to ensure subsequent accesses get the updated state
|
||
if matches!(method, "bind" | "connect" | "close") {
|
||
let updated_instance = socket_box.clone();
|
||
|
||
match object {
|
||
ASTNode::Variable { name, .. } => {
|
||
// Handle local variables
|
||
if let Some(stored_var) = self.local_vars.get_mut(name) {
|
||
*stored_var = Arc::new(updated_instance);
|
||
}
|
||
},
|
||
ASTNode::FieldAccess { object: field_obj, field, .. } => {
|
||
// Handle StaticBox fields like me.server
|
||
if let ASTNode::Variable { name, .. } = field_obj.as_ref() {
|
||
if name == "me" {
|
||
if let Ok(me_instance) = self.resolve_variable("me") {
|
||
if let Some(instance) = (*me_instance).as_any().downcast_ref::<InstanceBox>() {
|
||
let _ = instance.set_field(field, Arc::new(updated_instance));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
_ => {}
|
||
}
|
||
}
|
||
|
||
return Ok(result);
|
||
}
|
||
|
||
// HTTPServerBox method calls
|
||
if let Some(http_server_box) = obj_value.as_any().downcast_ref::<HTTPServerBox>() {
|
||
return self.execute_http_server_method(http_server_box, method, arguments);
|
||
}
|
||
|
||
// HTTPRequestBox method calls
|
||
if let Some(http_request_box) = obj_value.as_any().downcast_ref::<HTTPRequestBox>() {
|
||
return self.execute_http_request_method(http_request_box, method, arguments);
|
||
}
|
||
|
||
// HTTPResponseBox method calls
|
||
if let Some(http_response_box) = obj_value.as_any().downcast_ref::<HTTPResponseBox>() {
|
||
return self.execute_http_response_method(http_response_box, method, arguments);
|
||
}
|
||
|
||
// P2PBox method calls - Temporarily disabled
|
||
// if let Some(p2p_box) = obj_value.as_any().downcast_ref::<P2PBox>() {
|
||
// return self.execute_p2p_box_method(p2p_box, method, arguments);
|
||
// }
|
||
|
||
// EguiBox method calls (非WASM環境のみ)
|
||
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
|
||
if let Some(egui_box) = obj_value.as_any().downcast_ref::<crate::boxes::EguiBox>() {
|
||
return self.execute_egui_method(egui_box, method, arguments);
|
||
}
|
||
|
||
// WebDisplayBox method calls (WASM環境のみ)
|
||
#[cfg(target_arch = "wasm32")]
|
||
if let Some(web_display_box) = obj_value.as_any().downcast_ref::<crate::boxes::WebDisplayBox>() {
|
||
return self.execute_web_display_method(web_display_box, method, arguments);
|
||
}
|
||
|
||
// WebConsoleBox method calls (WASM環境のみ)
|
||
#[cfg(target_arch = "wasm32")]
|
||
if let Some(web_console_box) = obj_value.as_any().downcast_ref::<crate::boxes::WebConsoleBox>() {
|
||
return self.execute_web_console_method(web_console_box, method, arguments);
|
||
}
|
||
|
||
// WebCanvasBox method calls (WASM環境のみ)
|
||
#[cfg(target_arch = "wasm32")]
|
||
if let Some(web_canvas_box) = obj_value.as_any().downcast_ref::<crate::boxes::WebCanvasBox>() {
|
||
return self.execute_web_canvas_method(web_canvas_box, method, arguments);
|
||
}
|
||
|
||
// MethodBox method calls
|
||
if let Some(method_box) = obj_value.as_any().downcast_ref::<crate::method_box::MethodBox>() {
|
||
return self.execute_method_box_method(method_box, method, arguments);
|
||
}
|
||
|
||
// IntegerBox method calls
|
||
if let Some(integer_box) = obj_value.as_any().downcast_ref::<IntegerBox>() {
|
||
return self.execute_integer_method(integer_box, method, arguments);
|
||
}
|
||
|
||
// FloatBox method calls (将来的に追加予定)
|
||
|
||
// RangeBox method calls (将来的に追加予定)
|
||
|
||
// InstanceBox method calls
|
||
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
||
// 🔥 Usage prohibition guard - check if instance is finalized
|
||
if instance.is_finalized() {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: "Instance was finalized; further use is prohibited".to_string(),
|
||
});
|
||
}
|
||
|
||
// fini()は特別処理
|
||
if method == "fini" {
|
||
// 🔥 weak-fini prohibition check - prevent fini() on weak fields
|
||
if let ASTNode::FieldAccess { object: field_object, field, .. } = object {
|
||
// Check if this is me.<field>.fini() pattern
|
||
if let ASTNode::Variable { name, .. } = field_object.as_ref() {
|
||
if name == "me" {
|
||
// Get current instance to check if field is weak
|
||
if let Ok(current_me) = self.resolve_variable("me") {
|
||
if let Some(current_instance) = (*current_me).as_any().downcast_ref::<InstanceBox>() {
|
||
if current_instance.is_weak_field(field) {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!(
|
||
"Cannot finalize weak field '{}' (non-owning reference)",
|
||
field
|
||
),
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 既に解放済みの場合は何もしない(二重fini()対策)
|
||
if instance.is_finalized() {
|
||
return Ok(Box::new(VoidBox::new()));
|
||
}
|
||
|
||
// まず、Box内で定義されたfini()メソッドがあれば実行
|
||
if let Some(fini_method) = instance.get_method("fini") {
|
||
if let ASTNode::FunctionDeclaration { body, .. } = fini_method.clone() {
|
||
// 🌍 革命的メソッド実行:local変数スタックを使用
|
||
let saved_locals = self.save_local_vars();
|
||
self.local_vars.clear();
|
||
|
||
// thisをlocal変数として設定
|
||
self.declare_local_variable("me", obj_value.clone_box());
|
||
|
||
// fini()メソッドの本体を実行
|
||
let mut _result = Box::new(VoidBox::new()) as Box<dyn NyashBox>;
|
||
for statement in &body {
|
||
_result = self.execute_statement(statement)?;
|
||
|
||
// return文チェック
|
||
if let super::ControlFlow::Return(_) = &self.control_flow {
|
||
self.control_flow = super::ControlFlow::None;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// local変数スタックを復元
|
||
self.restore_local_vars(saved_locals);
|
||
}
|
||
}
|
||
|
||
// インスタンスの内部的な解放処理
|
||
instance.fini().map_err(|e| RuntimeError::InvalidOperation {
|
||
message: e,
|
||
})?;
|
||
finalization::mark_as_finalized(instance.box_id());
|
||
return Ok(Box::new(VoidBox::new()));
|
||
}
|
||
|
||
// メソッドを取得
|
||
let method_ast = instance.get_method(method)
|
||
.ok_or(RuntimeError::InvalidOperation {
|
||
message: format!("Method '{}' not found in {}", method, instance.class_name),
|
||
})?
|
||
.clone();
|
||
|
||
// メソッドが関数宣言の形式であることを確認
|
||
if let ASTNode::FunctionDeclaration { params, body, .. } = method_ast {
|
||
// 🚨 FIX: 引数評価を完全に現在のコンテキストで完了させる
|
||
let mut arg_values = Vec::new();
|
||
for (i, arg) in arguments.iter().enumerate() {
|
||
let arg_value = self.execute_expression(arg)?;
|
||
arg_values.push(arg_value);
|
||
}
|
||
|
||
// パラメータ数チェック
|
||
if arg_values.len() != params.len() {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!("Method {} expects {} arguments, got {}",
|
||
method, params.len(), arg_values.len()),
|
||
});
|
||
}
|
||
|
||
// 🌍 NOW SAFE: すべての引数評価完了後にコンテキスト切り替え
|
||
let saved_locals = self.save_local_vars();
|
||
self.local_vars.clear();
|
||
|
||
// thisをlocal変数として設定
|
||
self.declare_local_variable("me", obj_value.clone_box());
|
||
|
||
// パラメータをlocal変数として設定
|
||
for (param, value) in params.iter().zip(arg_values.iter()) {
|
||
self.declare_local_variable(param, value.clone_box());
|
||
}
|
||
|
||
// メソッド本体を実行
|
||
let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
|
||
for statement in &body {
|
||
result = self.execute_statement(statement)?;
|
||
|
||
// return文チェック
|
||
if let super::ControlFlow::Return(return_val) = &self.control_flow {
|
||
result = return_val.clone_box();
|
||
self.control_flow = super::ControlFlow::None;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// local変数スタックを復元
|
||
self.restore_local_vars(saved_locals);
|
||
|
||
Ok(result)
|
||
} else {
|
||
Err(RuntimeError::InvalidOperation {
|
||
message: format!("Method '{}' is not a valid function declaration", method),
|
||
})
|
||
}
|
||
} else {
|
||
Err(RuntimeError::TypeError {
|
||
message: format!("Cannot call method '{}' on non-instance type", method),
|
||
})
|
||
}
|
||
}
|
||
|
||
/// フィールドアクセスを実行 - Field access processing with weak reference support
|
||
pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str)
|
||
-> Result<SharedNyashBox, RuntimeError> {
|
||
|
||
// 🔥 Static Boxアクセスチェック
|
||
if let ASTNode::Variable { name, .. } = object {
|
||
// Static boxの可能性をチェック
|
||
if self.is_static_box(name) {
|
||
let static_result = self.execute_static_field_access(name, field)?;
|
||
return Ok(Arc::from(static_result));
|
||
}
|
||
}
|
||
|
||
|
||
// オブジェクトを評価(通常のフィールドアクセス)
|
||
let obj_value = self.execute_expression(object);
|
||
|
||
let obj_value = obj_value?;
|
||
|
||
// InstanceBoxにキャスト
|
||
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
||
// 🔥 Usage prohibition guard - check if instance is finalized
|
||
if instance.is_finalized() {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: "Instance was finalized; further use is prohibited".to_string(),
|
||
});
|
||
}
|
||
|
||
// フィールドの値を取得
|
||
let field_value = instance.get_field(field)
|
||
.ok_or(RuntimeError::InvalidOperation {
|
||
message: format!("Field '{}' not found in {}", field, instance.class_name),
|
||
})?;
|
||
|
||
eprintln!("✅ FIELD ACCESS: Returning shared reference id={}", field_value.box_id());
|
||
|
||
// 🔗 Weak Reference Check: Use unified accessor for weak fields
|
||
let box_decls = self.shared.box_declarations.read().unwrap();
|
||
if let Some(box_decl) = box_decls.get(&instance.class_name) {
|
||
if box_decl.weak_fields.contains(&field.to_string()) {
|
||
eprintln!("🔗 DEBUG: Accessing weak field '{}' in class '{}'", field, instance.class_name);
|
||
|
||
// 🎯 PHASE 2: Use unified accessor for auto-nil weak reference handling
|
||
if let Some(weak_value) = instance.get_weak_field(field, self) { // Pass self
|
||
match &weak_value {
|
||
crate::value::NyashValue::Null => {
|
||
eprintln!("🔗 DEBUG: Weak field '{}' is null (reference dropped)", field);
|
||
// Return null box for compatibility
|
||
return Ok(Arc::new(crate::boxes::null_box::NullBox::new()));
|
||
}
|
||
_ => {
|
||
eprintln!("🔗 DEBUG: Weak field '{}' still has valid reference", field);
|
||
// Convert back to Box<dyn NyashBox> for now
|
||
if let Ok(box_value) = weak_value.to_box() {
|
||
if let Ok(inner_box) = box_value.try_lock() {
|
||
return Ok(Arc::from(inner_box.clone_box()));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// If weak field access failed, fall through to normal access
|
||
}
|
||
}
|
||
|
||
// Return the shared Arc reference directly
|
||
Ok(field_value)
|
||
} else {
|
||
Err(RuntimeError::TypeError {
|
||
message: format!("Cannot access field '{}' on non-instance type. Type: {}", field, obj_value.type_name()),
|
||
})
|
||
}
|
||
}
|
||
|
||
/// 🔥 Static Box名前空間のフィールドアクセス
|
||
fn execute_static_field_access(&mut self, static_box_name: &str, field: &str)
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
// 1. Static Boxの初期化を確実に実行
|
||
self.ensure_static_box_initialized(static_box_name)?;
|
||
|
||
// 2. GlobalBox.statics.{static_box_name} からインスタンスを取得
|
||
let global_box = self.shared.global_box.lock()
|
||
.map_err(|_| RuntimeError::RuntimeFailure {
|
||
message: "Failed to acquire global box lock".to_string()
|
||
})?;
|
||
|
||
let statics_box = global_box.get_field("statics")
|
||
.ok_or(RuntimeError::RuntimeFailure {
|
||
message: "statics namespace not found in GlobalBox".to_string()
|
||
})?;
|
||
|
||
let statics_instance = statics_box.as_any()
|
||
.downcast_ref::<InstanceBox>()
|
||
.ok_or(RuntimeError::TypeError {
|
||
message: "statics field is not an InstanceBox".to_string()
|
||
})?;
|
||
|
||
let static_box_instance = statics_instance.get_field(static_box_name)
|
||
.ok_or(RuntimeError::RuntimeFailure {
|
||
message: format!("Static box '{}' instance not found in statics namespace", static_box_name)
|
||
})?;
|
||
|
||
let instance = static_box_instance.as_any()
|
||
.downcast_ref::<InstanceBox>()
|
||
.ok_or(RuntimeError::TypeError {
|
||
message: format!("Static box '{}' is not an InstanceBox", static_box_name)
|
||
})?;
|
||
|
||
// 3. フィールドアクセス
|
||
let shared_field = instance.get_field(field)
|
||
.ok_or(RuntimeError::InvalidOperation {
|
||
message: format!("Field '{}' not found in static box '{}'", field, static_box_name),
|
||
})?;
|
||
|
||
// Convert Arc to Box for compatibility
|
||
Ok((*shared_field).clone_box())
|
||
}
|
||
|
||
|
||
/// await式を実行 - Execute await expression
|
||
pub(super) fn execute_await(&mut self, expression: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
let value = self.execute_expression(expression)?;
|
||
|
||
// FutureBoxなら待機して結果を取得
|
||
if let Some(future) = value.as_any().downcast_ref::<FutureBox>() {
|
||
future.wait_and_get()
|
||
.map_err(|msg| RuntimeError::InvalidOperation { message: msg })
|
||
} else {
|
||
// FutureBoxでなければそのまま返す
|
||
Ok(value)
|
||
}
|
||
}
|
||
|
||
/// 🔄 循環参照検出: オブジェクトの一意IDを取得
|
||
fn get_object_id(&self, node: &ASTNode) -> Option<usize> {
|
||
match node {
|
||
ASTNode::Variable { name, .. } => {
|
||
// 変数名のハッシュをIDとして使用
|
||
Some(self.hash_string(name))
|
||
}
|
||
ASTNode::Me { .. } => {
|
||
// 'me'参照の特別なID
|
||
Some(usize::MAX)
|
||
}
|
||
ASTNode::This { .. } => {
|
||
// 'this'参照の特別なID
|
||
Some(usize::MAX - 1)
|
||
}
|
||
_ => None, // 他のノードタイプはID追跡しない
|
||
}
|
||
}
|
||
|
||
/// 🔄 文字列のシンプルなハッシュ関数
|
||
fn hash_string(&self, s: &str) -> usize {
|
||
let mut hash = 0usize;
|
||
for byte in s.bytes() {
|
||
hash = hash.wrapping_mul(31).wrapping_add(byte as usize);
|
||
}
|
||
hash
|
||
}
|
||
|
||
/// 🔗 Convert NyashBox to NyashValue for weak reference operations
|
||
// fn box_to_nyash_value(&self, box_val: &Box<dyn NyashBox>) -> Option<nyash_rust::value::NyashValue> {
|
||
// // Try to convert the box back to NyashValue for weak reference operations
|
||
// // This is a simplified conversion - in reality we might need more sophisticated logic
|
||
// use nyash_rust::value::NyashValue;
|
||
// use crate::box_trait::{StringBox, IntegerBox, BoolBox, VoidBox};
|
||
//
|
||
// if let Some(string_box) = box_val.as_any().downcast_ref::<StringBox>() {
|
||
// Some(NyashValue::String(string_box.value.clone()))
|
||
// } else if let Some(int_box) = box_val.as_any().downcast_ref::<IntegerBox>() {
|
||
// Some(NyashValue::Integer(int_box.value))
|
||
// } else if let Some(bool_box) = box_val.as_any().downcast_ref::<BoolBox>() {
|
||
// Some(NyashValue::Bool(bool_box.value))
|
||
// } else if box_val.as_any().downcast_ref::<VoidBox>().is_some() {
|
||
// Some(NyashValue::Void)
|
||
// } else if box_val.as_any().downcast_ref::<crate::boxes::null_box::NullBox>().is_some() {
|
||
// Some(NyashValue::Null)
|
||
// } else {
|
||
// // For complex types, create a Box variant
|
||
// // Note: This is where we'd store the weak reference
|
||
// None // Simplified for now
|
||
// }
|
||
// }
|
||
|
||
/// 🔥 FromCall実行処理 - from Parent.method(arguments) or from Parent.constructor(arguments)
|
||
pub(super) fn execute_from_call(&mut self, parent: &str, method: &str, arguments: &[ASTNode])
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
|
||
// 1. 現在のコンテキストで'me'変数を取得(現在のインスタンス)
|
||
let current_instance_val = self.resolve_variable("me")
|
||
.map_err(|_| RuntimeError::InvalidOperation {
|
||
message: "'from' can only be used inside methods".to_string(),
|
||
})?;
|
||
|
||
let current_instance = (*current_instance_val).as_any().downcast_ref::<InstanceBox>()
|
||
.ok_or(RuntimeError::TypeError {
|
||
message: "'from' requires current instance to be InstanceBox".to_string(),
|
||
})?;
|
||
|
||
// 2. 現在のクラスのデリゲーション関係を検証
|
||
let current_class = ¤t_instance.class_name;
|
||
let box_declarations = self.shared.box_declarations.read().unwrap();
|
||
|
||
let current_box_decl = box_declarations.get(current_class)
|
||
.ok_or(RuntimeError::UndefinedClass {
|
||
name: current_class.clone()
|
||
})?;
|
||
|
||
// extendsまたはimplementsでparentが指定されているか確認 (Multi-delegation) 🚀
|
||
let is_valid_delegation = current_box_decl.extends.contains(&parent.to_string()) ||
|
||
current_box_decl.implements.contains(&parent.to_string());
|
||
|
||
if !is_valid_delegation {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!("Class '{}' does not delegate to '{}'. Use 'box {} from {}' to establish delegation.",
|
||
current_class, parent, current_class, parent),
|
||
});
|
||
}
|
||
|
||
// 🔥 ビルトインBoxかチェック
|
||
let mut builtin_boxes = vec![
|
||
"IntegerBox", "StringBox", "BoolBox", "ArrayBox", "MapBox",
|
||
"FileBox", "ResultBox", "FutureBox", "ChannelBox", "MathBox",
|
||
"TimeBox", "DateTimeBox", "TimerBox", "RandomBox", "SoundBox",
|
||
"DebugBox", "MethodBox", "NullBox", "ConsoleBox", "FloatBox",
|
||
"BufferBox", "RegexBox", "JSONBox", "StreamBox", "HTTPClientBox",
|
||
"IntentBox", "P2PBox", "SocketBox", "HTTPServerBox", "HTTPRequestBox", "HTTPResponseBox"
|
||
];
|
||
|
||
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
|
||
builtin_boxes.push("EguiBox");
|
||
|
||
let is_builtin = builtin_boxes.contains(&parent);
|
||
|
||
if is_builtin {
|
||
// ビルトインBoxの場合、ロックを解放してからメソッド呼び出し
|
||
drop(box_declarations);
|
||
return self.execute_builtin_box_method(parent, method, current_instance_val.clone_box(), arguments);
|
||
}
|
||
|
||
// 3. 親クラスのBox宣言を取得(ユーザー定義Boxの場合)
|
||
let parent_box_decl = box_declarations.get(parent)
|
||
.ok_or(RuntimeError::UndefinedClass {
|
||
name: parent.to_string()
|
||
})?
|
||
.clone();
|
||
|
||
drop(box_declarations); // ロック早期解放
|
||
|
||
// 4. constructorまたはinitまたはpackの場合の特別処理
|
||
if method == "constructor" || method == "init" || method == "pack" || method == parent {
|
||
return self.execute_from_parent_constructor(parent, &parent_box_decl, current_instance_val.clone_box(), arguments);
|
||
}
|
||
|
||
// 5. 親クラスのメソッドを取得
|
||
let parent_method = parent_box_decl.methods.get(method)
|
||
.ok_or(RuntimeError::InvalidOperation {
|
||
message: format!("Method '{}' not found in parent class '{}'", method, parent),
|
||
})?
|
||
.clone();
|
||
|
||
// 6. 引数を評価
|
||
let mut arg_values = Vec::new();
|
||
for arg in arguments {
|
||
arg_values.push(self.execute_expression(arg)?);
|
||
}
|
||
|
||
// 7. 親メソッドを実行
|
||
if let ASTNode::FunctionDeclaration { params, body, .. } = parent_method {
|
||
// パラメータ数チェック
|
||
if arg_values.len() != params.len() {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!("Parent method {}.{} expects {} arguments, got {}",
|
||
parent, method, params.len(), arg_values.len()),
|
||
});
|
||
}
|
||
|
||
// 🌍 local変数スタックを保存・クリア(親メソッド実行開始)
|
||
let saved_locals = self.save_local_vars();
|
||
self.local_vars.clear();
|
||
|
||
// 'me'を現在のインスタンスに設定(重要:現在のインスタンスを維持)
|
||
self.declare_local_variable("me", current_instance_val.clone_box());
|
||
|
||
// 引数をlocal変数として設定
|
||
for (param, value) in params.iter().zip(arg_values.iter()) {
|
||
self.declare_local_variable(param, value.clone_box());
|
||
}
|
||
|
||
// 親メソッドの本体を実行
|
||
let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
|
||
for statement in &body {
|
||
result = self.execute_statement(statement)?;
|
||
|
||
// return文チェック
|
||
if let super::ControlFlow::Return(return_val) = &self.control_flow {
|
||
result = return_val.clone_box();
|
||
self.control_flow = super::ControlFlow::None;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 🔍 DEBUG: FromCall実行結果をログ出力
|
||
eprintln!("🔍 DEBUG: FromCall {}.{} result: {}", parent, method, result.to_string_box().value);
|
||
|
||
// local変数スタックを復元
|
||
self.restore_local_vars(saved_locals);
|
||
|
||
Ok(result)
|
||
} else {
|
||
Err(RuntimeError::InvalidOperation {
|
||
message: format!("Parent method '{}' is not a valid function declaration", method),
|
||
})
|
||
}
|
||
}
|
||
|
||
/// 🔥 fromCall専用親コンストラクタ実行処理 - from Parent.constructor(arguments)
|
||
fn execute_from_parent_constructor(&mut self, parent: &str, parent_box_decl: &super::BoxDeclaration,
|
||
current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
|
||
// 1. 親クラスのコンストラクタを取得(引数の数でキーを作成)
|
||
// "pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す
|
||
let pack_key = format!("pack/{}", arguments.len());
|
||
let init_key = format!("init/{}", arguments.len());
|
||
let box_name_key = format!("{}/{}", parent, arguments.len());
|
||
|
||
let parent_constructor = parent_box_decl.constructors.get(&pack_key)
|
||
.or_else(|| parent_box_decl.constructors.get(&init_key))
|
||
.or_else(|| parent_box_decl.constructors.get(&box_name_key))
|
||
.ok_or(RuntimeError::InvalidOperation {
|
||
message: format!("No constructor found for parent class '{}' with {} arguments", parent, arguments.len()),
|
||
})?
|
||
.clone();
|
||
|
||
// 2. 引数を評価
|
||
let mut arg_values = Vec::new();
|
||
for arg in arguments {
|
||
arg_values.push(self.execute_expression(arg)?);
|
||
}
|
||
|
||
// 3. 親コンストラクタを実行
|
||
if let ASTNode::FunctionDeclaration { params, body, .. } = parent_constructor {
|
||
// パラメータ数チェック
|
||
if arg_values.len() != params.len() {
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!("Parent constructor {} expects {} arguments, got {}",
|
||
parent, params.len(), arg_values.len()),
|
||
});
|
||
}
|
||
|
||
// 🌍 local変数スタックを保存・クリア(親コンストラクタ実行開始)
|
||
let saved_locals = self.save_local_vars();
|
||
self.local_vars.clear();
|
||
|
||
// 'me'を現在のインスタンスに設定
|
||
self.declare_local_variable("me", current_instance.clone_box());
|
||
|
||
// 引数をlocal変数として設定
|
||
for (param, value) in params.iter().zip(arg_values.iter()) {
|
||
self.declare_local_variable(param, value.clone_box());
|
||
}
|
||
|
||
// 親コンストラクタの本体を実行
|
||
let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
|
||
for statement in &body {
|
||
result = self.execute_statement(statement)?;
|
||
|
||
// return文チェック
|
||
if let super::ControlFlow::Return(return_val) = &self.control_flow {
|
||
result = return_val.clone_box();
|
||
self.control_flow = super::ControlFlow::None;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// local変数スタックを復元
|
||
self.restore_local_vars(saved_locals);
|
||
|
||
// 親コンストラクタは通常現在のインスタンスを返す
|
||
Ok(current_instance)
|
||
} else {
|
||
Err(RuntimeError::InvalidOperation {
|
||
message: format!("Parent constructor is not a valid function declaration"),
|
||
})
|
||
}
|
||
}
|
||
|
||
/// 🔥 ビルトインBoxのメソッド呼び出し
|
||
fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||
|
||
// ビルトインBoxのインスタンスを作成または取得
|
||
// 現在のインスタンスからビルトインBoxのデータを取得し、ビルトインBoxとしてメソッド実行
|
||
|
||
match parent {
|
||
"StringBox" => {
|
||
// StringBoxのインスタンスを作成(デフォルト値)
|
||
let string_box = StringBox::new("");
|
||
self.execute_string_method(&string_box, method, arguments)
|
||
}
|
||
"IntegerBox" => {
|
||
// IntegerBoxのインスタンスを作成(デフォルト値)
|
||
let integer_box = IntegerBox::new(0);
|
||
self.execute_integer_method(&integer_box, method, arguments)
|
||
}
|
||
"ArrayBox" => {
|
||
let array_box = ArrayBox::new();
|
||
self.execute_array_method(&array_box, method, arguments)
|
||
}
|
||
"MapBox" => {
|
||
let map_box = MapBox::new();
|
||
self.execute_map_method(&map_box, method, arguments)
|
||
}
|
||
"MathBox" => {
|
||
let math_box = MathBox::new();
|
||
self.execute_math_method(&math_box, method, arguments)
|
||
}
|
||
"P2PBox" => {
|
||
// P2PBoxの場合、現在のインスタンスからP2PBoxインスタンスを取得する必要がある
|
||
// TODO: 現在のインスタンスのフィールドからP2PBoxを取得
|
||
return Err(RuntimeError::InvalidOperation {
|
||
message: format!("P2PBox delegation not yet fully implemented: {}.{}", parent, method),
|
||
});
|
||
}
|
||
"FileBox" => {
|
||
let file_box = crate::boxes::file::FileBox::new();
|
||
self.execute_file_method(&file_box, method, arguments)
|
||
}
|
||
"ConsoleBox" => {
|
||
let console_box = ConsoleBox::new();
|
||
self.execute_console_method(&console_box, method, arguments)
|
||
}
|
||
"TimeBox" => {
|
||
let time_box = TimeBox::new();
|
||
self.execute_time_method(&time_box, method, arguments)
|
||
}
|
||
"RandomBox" => {
|
||
let random_box = RandomBox::new();
|
||
self.execute_random_method(&random_box, method, arguments)
|
||
}
|
||
"DebugBox" => {
|
||
let debug_box = DebugBox::new();
|
||
self.execute_debug_method(&debug_box, method, arguments)
|
||
}
|
||
"SoundBox" => {
|
||
let sound_box = SoundBox::new();
|
||
self.execute_sound_method(&sound_box, method, arguments)
|
||
}
|
||
"SocketBox" => {
|
||
let socket_box = SocketBox::new();
|
||
self.execute_socket_method(&socket_box, method, arguments)
|
||
}
|
||
"HTTPServerBox" => {
|
||
let http_server_box = HTTPServerBox::new();
|
||
self.execute_http_server_method(&http_server_box, method, arguments)
|
||
}
|
||
"HTTPRequestBox" => {
|
||
let http_request_box = HTTPRequestBox::new();
|
||
self.execute_http_request_method(&http_request_box, method, arguments)
|
||
}
|
||
"HTTPResponseBox" => {
|
||
let http_response_box = HTTPResponseBox::new();
|
||
self.execute_http_response_method(&http_response_box, method, arguments)
|
||
}
|
||
_ => {
|
||
Err(RuntimeError::InvalidOperation {
|
||
message: format!("Unknown built-in Box type for delegation: {}", parent),
|
||
})
|
||
}
|
||
}
|
||
}
|
||
} |