/*! * Method Dispatch Module * * Extracted from expressions.rs lines 383-900 (~517 lines) * Handles method call dispatch for all Box types and static function calls * Core philosophy: "Everything is Box" with unified method dispatch */ use super::*; 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::bid::plugin_box::PluginFileBox; use std::sync::Arc; impl NyashInterpreter { /// メソッド呼び出しを実行 - 全Box型の統一ディスパッチ pub(super) fn execute_method_call(&mut self, object: &ASTNode, method: &str, arguments: &[ASTNode]) -> Result, 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 { return self.execute_static_function(static_func, name, method, arguments); } // 📚 nyashstd標準ライブラリのメソッドチェック if let Some(stdlib_result) = self.try_execute_stdlib_method(name, method, arguments)? { return Ok(stdlib_result); } } // オブジェクトを評価(通常のメソッド呼び出し) let obj_value = self.execute_expression(object)?; // 各Box型に対するメソッドディスパッチ self.dispatch_builtin_method(&obj_value, method, arguments, object) } /// static関数を実行 fn execute_static_function( &mut self, static_func: ASTNode, box_name: &str, method: &str, arguments: &[ASTNode] ) -> Result, RuntimeError> { 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 {}", box_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; 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); Ok(result) } else { Err(RuntimeError::InvalidOperation { message: format!("Invalid static function: {}.{}", box_name, method), }) } } /// nyashstd標準ライブラリメソッド実行を試行 fn try_execute_stdlib_method( &mut self, box_name: &str, method: &str, arguments: &[ASTNode] ) -> Result>, RuntimeError> { let stdlib_method = if let Some(ref stdlib) = self.stdlib { if let Some(nyashstd_namespace) = stdlib.namespaces.get("nyashstd") { if let Some(static_box) = nyashstd_namespace.static_boxes.get(box_name) { if let Some(builtin_method) = static_box.methods.get(method) { Some(*builtin_method) // Copyトレイトで関数ポインターをコピー } else { eprintln!("🔍 Method '{}' not found in nyashstd.{}", method, box_name); None } } else { eprintln!("🔍 Static box '{}' not found in nyashstd", box_name); None } } else { eprintln!("🔍 nyashstd namespace not found in stdlib"); None } } else { eprintln!("🔍 stdlib not initialized for method call"); None }; if let Some(builtin_method) = stdlib_method { eprintln!("🌟 Calling nyashstd method: {}.{}", box_name, method); // 引数を評価 let mut arg_values = Vec::new(); for arg in arguments { arg_values.push(self.execute_expression(arg)?); } // 標準ライブラリのメソッドを実行 let result = builtin_method(&arg_values)?; eprintln!("✅ nyashstd method completed: {}.{}", box_name, method); return Ok(Some(result)); } Ok(None) } /// ビルトインBox型メソッドディスパッチ fn dispatch_builtin_method( &mut self, obj_value: &Box, method: &str, arguments: &[ASTNode], object: &ASTNode ) -> Result, RuntimeError> { // StringBox method calls if let Some(string_box) = obj_value.as_any().downcast_ref::() { return self.execute_string_method(string_box, method, arguments); } // IntegerBox method calls if let Some(integer_box) = obj_value.as_any().downcast_ref::() { return self.execute_integer_method(integer_box, method, arguments); } // FloatBox method calls if let Some(float_box) = obj_value.as_any().downcast_ref::() { return self.execute_float_method(float_box, method, arguments); } // BoolBox method calls if let Some(bool_box) = obj_value.as_any().downcast_ref::() { return self.execute_bool_method(bool_box, method, arguments); } // ArrayBox method calls if let Some(array_box) = obj_value.as_any().downcast_ref::() { return self.execute_array_method(array_box, method, arguments); } // BufferBox method calls if let Some(buffer_box) = obj_value.as_any().downcast_ref::() { return self.execute_buffer_method(buffer_box, method, arguments); } // FileBox method calls if let Some(file_box) = obj_value.as_any().downcast_ref::() { return self.execute_file_method(file_box, method, arguments); } // Plugin-backed FileBox method calls if let Some(pfile) = obj_value.as_any().downcast_ref::() { return self.execute_plugin_file_method(pfile, method, arguments); } // ResultBox method calls if let Some(result_box) = obj_value.as_any().downcast_ref::() { return self.execute_result_method(result_box, method, arguments); } // FutureBox method calls if let Some(future_box) = obj_value.as_any().downcast_ref::() { return self.execute_future_method(future_box, method, arguments); } // ChannelBox method calls if let Some(channel_box) = obj_value.as_any().downcast_ref::() { return self.execute_channel_method(channel_box, method, arguments); } // JSONBox method calls if let Some(json_box) = obj_value.as_any().downcast_ref::() { return self.execute_json_method(json_box, method, arguments); } // HttpClientBox method calls if let Some(http_box) = obj_value.as_any().downcast_ref::() { return self.execute_http_method(http_box, method, arguments); } // StreamBox method calls if let Some(stream_box) = obj_value.as_any().downcast_ref::() { return self.execute_stream_method(stream_box, method, arguments); } // RegexBox method calls if let Some(regex_box) = obj_value.as_any().downcast_ref::() { return self.execute_regex_method(regex_box, method, arguments); } // MathBox method calls if let Some(math_box) = obj_value.as_any().downcast_ref::() { return self.execute_math_method(math_box, method, arguments); } // NullBox method calls if let Some(null_box) = obj_value.as_any().downcast_ref::() { return self.execute_null_method(null_box, method, arguments); } // TimeBox method calls if let Some(time_box) = obj_value.as_any().downcast_ref::() { return self.execute_time_method(time_box, method, arguments); } // DateTimeBox method calls if let Some(datetime_box) = obj_value.as_any().downcast_ref::() { return self.execute_datetime_method(datetime_box, method, arguments); } // TimerBox method calls if let Some(timer_box) = obj_value.as_any().downcast_ref::() { return self.execute_timer_method(timer_box, method, arguments); } // MapBox method calls if let Some(map_box) = obj_value.as_any().downcast_ref::() { return self.execute_map_method(map_box, method, arguments); } // RandomBox method calls if let Some(random_box) = obj_value.as_any().downcast_ref::() { return self.execute_random_method(random_box, method, arguments); } // SoundBox method calls if let Some(sound_box) = obj_value.as_any().downcast_ref::() { return self.execute_sound_method(sound_box, method, arguments); } // DebugBox method calls if let Some(debug_box) = obj_value.as_any().downcast_ref::() { return self.execute_debug_method(debug_box, method, arguments); } // ConsoleBox method calls if let Some(console_box) = obj_value.as_any().downcast_ref::() { return self.execute_console_method(console_box, method, arguments); } // IntentBox method calls if let Some(intent_box) = obj_value.as_any().downcast_ref::() { return self.execute_intent_box_method(intent_box, method, arguments); } // SocketBox method calls if let Some(socket_box) = obj_value.as_any().downcast_ref::() { let result = self.execute_socket_method(socket_box, method, arguments)?; // 🔧 FIX: Update stored variable for stateful SocketBox methods if matches!(method, "bind" | "connect" | "close") { self.update_stateful_socket_box(object, socket_box)?; } return Ok(result); } // HTTPServerBox method calls if let Some(http_server_box) = obj_value.as_any().downcast_ref::() { 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::() { 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::() { 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::() { // 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::() { 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::() { 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::() { 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::() { return self.execute_web_canvas_method(web_canvas_box, method, arguments); } // ユーザー定義Boxのメソッド呼び出し self.execute_user_defined_method(obj_value, method, arguments) } fn execute_plugin_file_method( &mut self, pfile: &PluginFileBox, method: &str, arguments: &[ASTNode], ) -> Result, RuntimeError> { match method { "write" => { if arguments.len() != 1 { return Err(RuntimeError::InvalidOperation { message: "FileBox.write expects 1 argument".into() }); } let arg0 = self.execute_expression(&arguments[0])?; let data = arg0.to_string_box().value; pfile.write_bytes(data.as_bytes()).map_err(|e| RuntimeError::RuntimeFailure { message: format!("plugin write error: {:?}", e) })?; Ok(Box::new(StringBox::new("ok"))) } "read" => { // Default read size let size = 1_048_576usize; // 1MB max let bytes = pfile.read_bytes(size).map_err(|e| RuntimeError::RuntimeFailure { message: format!("plugin read error: {:?}", e) })?; let s = String::from_utf8_lossy(&bytes).to_string(); Ok(Box::new(StringBox::new(s))) } "close" => { pfile.close().map_err(|e| RuntimeError::RuntimeFailure { message: format!("plugin close error: {:?}", e) })?; Ok(Box::new(StringBox::new("ok"))) } _ => Err(RuntimeError::InvalidOperation { message: format!("Unknown method FileBox.{} (plugin)", method) }) } } /// SocketBoxの状態変更を反映 fn update_stateful_socket_box( &mut self, object: &ASTNode, socket_box: &SocketBox ) -> Result<(), RuntimeError> { eprintln!("🔧 DEBUG: Stateful method called, updating stored instance"); let updated_instance = socket_box.clone(); eprintln!("🔧 DEBUG: Updated instance created with ID={}", updated_instance.box_id()); match object { ASTNode::Variable { name, .. } => { eprintln!("🔧 DEBUG: Updating local variable '{}'", name); if let Some(stored_var) = self.local_vars.get_mut(name) { eprintln!("🔧 DEBUG: Found local variable '{}', updating from id={} to id={}", name, stored_var.box_id(), updated_instance.box_id()); *stored_var = Arc::new(updated_instance); } else { eprintln!("🔧 DEBUG: Local variable '{}' not found", name); } }, ASTNode::FieldAccess { object: field_obj, field, .. } => { eprintln!("🔧 DEBUG: Updating field access '{}'", field); self.update_field_with_socket_box(field_obj, field, updated_instance)?; }, _ => { eprintln!("🔧 DEBUG: Object type not handled: {:?}", object); } } Ok(()) } /// フィールドアクセスでのSocketBox更新 fn update_field_with_socket_box( &mut self, field_obj: &ASTNode, field: &str, updated_instance: SocketBox ) -> Result<(), RuntimeError> { match field_obj { ASTNode::Variable { name, .. } => { eprintln!("🔧 DEBUG: Field object is variable '{}'", name); if name == "me" { eprintln!("🔧 DEBUG: Updating me.{} (via variable)", field); if let Ok(me_instance) = self.resolve_variable("me") { eprintln!("🔧 DEBUG: Resolved 'me' instance id={}", me_instance.box_id()); if let Some(instance) = (*me_instance).as_any().downcast_ref::() { eprintln!("🔧 DEBUG: me is InstanceBox, setting field '{}' to updated instance id={}", field, updated_instance.box_id()); let result = instance.set_field(field, Arc::new(updated_instance)); eprintln!("🔧 DEBUG: set_field result: {:?}", result); } else { eprintln!("🔧 DEBUG: me is not an InstanceBox, type: {}", me_instance.type_name()); } } else { eprintln!("🔧 DEBUG: Failed to resolve 'me'"); } } else { eprintln!("🔧 DEBUG: Field object is not 'me', it's '{}'", name); } }, ASTNode::Me { .. } => { eprintln!("🔧 DEBUG: Field object is Me node, updating me.{}", field); if let Ok(me_instance) = self.resolve_variable("me") { eprintln!("🔧 DEBUG: Resolved 'me' instance id={}", me_instance.box_id()); if let Some(instance) = (*me_instance).as_any().downcast_ref::() { eprintln!("🔧 DEBUG: me is InstanceBox, setting field '{}' to updated instance id={}", field, updated_instance.box_id()); let result = instance.set_field(field, Arc::new(updated_instance)); eprintln!("🔧 DEBUG: set_field result: {:?}", result); } else { eprintln!("🔧 DEBUG: me is not an InstanceBox, type: {}", me_instance.type_name()); } } else { eprintln!("🔧 DEBUG: Failed to resolve 'me'"); } }, _ => { eprintln!("🔧 DEBUG: Field object is not a variable or me, type: {:?}", field_obj); } } Ok(()) } /// ユーザー定義Boxメソッド実行 fn execute_user_defined_method( &mut self, obj_value: &Box, method: &str, arguments: &[ASTNode] ) -> Result, RuntimeError> { // InstanceBox method calls (user-defined methods) if let Some(instance) = obj_value.as_any().downcast_ref::() { return self.execute_instance_method(instance, method, arguments); } // Static box method calls would be handled here if implemented // (Currently handled via different mechanism in static function dispatch) Err(RuntimeError::InvalidOperation { message: format!("Method '{}' not found on type '{}'", method, obj_value.type_name()), }) } }