diff --git a/build_output.txt b/build_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/interpreter/expressions/calls.rs b/src/interpreter/expressions/calls.rs index fc6af38b..0fc9dd3c 100644 --- a/src/interpreter/expressions/calls.rs +++ b/src/interpreter/expressions/calls.rs @@ -2,4 +2,741 @@ * Method calls and from delegation calls */ -use super::*; \ No newline at end of file +use super::*; +use crate::ast::ASTNode; +use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, SharedNyashBox}; +use crate::boxes::{ArrayBox, FloatBox, ConsoleBox, MapBox, FutureBox}; +use crate::boxes::{BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox}; +use crate::boxes::{HTTPServerBox, HTTPRequestBox, HTTPResponseBox, MathBox, TimeBox, DateTimeBox}; +use crate::boxes::{RandomBox, SoundBox, DebugBox}; +use crate::{InstanceBox, ChannelBox}; +use crate::interpreter::core::{NyashInterpreter, RuntimeError}; +use crate::interpreter::finalization; +use std::sync::Arc; + +impl NyashInterpreter { + /// メソッド呼び出しを実行 - Method call processing + 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 { + // 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; + 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); + } + } + + // 📚 nyashstd標準ライブラリのメソッドチェック + 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(name) { + if let Some(builtin_method) = static_box.methods.get(method) { + Some(*builtin_method) // Copyトレイトで関数ポインターをコピー + } else { + eprintln!("🔍 Method '{}' not found in nyashstd.{}", method, name); + None + } + } else { + eprintln!("🔍 Static box '{}' not found in nyashstd", 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: {}.{}", 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: {}.{}", name, method); + return Ok(result); + } + } + + // オブジェクトを評価(通常のメソッド呼び出し) + let obj_value = self.execute_expression(object)?; + + // 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); + } + + // 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 + // 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") { + eprintln!("🔧 DEBUG: Stateful method '{}' called, updating stored instance", method); + 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); + // Handle local variables + 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); + // Handle StaticBox fields like me.server + match field_obj.as_ref() { + 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); + } + } + }, + _ => { + eprintln!("🔧 DEBUG: Object type not handled: {:?}", object); + } + } + } + + 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); + } + + // MethodBox method calls + if let Some(method_box) = obj_value.as_any().downcast_ref::() { + return self.execute_method_box_method(method_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 (将来的に追加予定) + + // RangeBox method calls (将来的に追加予定) + + // InstanceBox method calls + if let Some(instance) = obj_value.as_any().downcast_ref::() { + // 🔥 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..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::() { + 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; + 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); + } + } + + // 🔗 Phase 8.9: Weak reference invalidation after user fini + let target_info = obj_value.to_string_box().value; + eprintln!("🔗 DEBUG: Triggering weak reference invalidation for fini: {}", target_info); + self.trigger_weak_reference_invalidation(&target_info); + + // インスタンスの内部的な解放処理 + 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 = 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), + }) + } + } + + /// 🔥 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, 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::() + .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), + }); + } + + // 🔥 Phase 8.8: pack透明化システム - ビルトインBox判定 + use crate::box_trait::is_builtin_box; + + let mut is_builtin = is_builtin_box(parent); + + // GUI機能が有効な場合はEguiBoxも追加判定 + #[cfg(all(feature = "gui", not(target_arch = "wasm32")))] + { + if parent == "EguiBox" { + is_builtin = true; + } + } + + // 🔥 Phase 8.9: Transparency system removed - all delegation must be explicit + // Removed: if is_builtin && method == parent { ... execute_builtin_constructor_call ... } + + 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またはbirthの場合の特別処理 + if method == "constructor" || method == "init" || method == "pack" || method == "birth" || 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 = 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, arguments: &[ASTNode]) + -> Result, RuntimeError> { + + // 1. 親クラスのコンストラクタを取得(引数の数でキーを作成) + // "birth/引数数"、"pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す + let birth_key = format!("birth/{}", arguments.len()); + 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(&birth_key) + .or_else(|| 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 = 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"), + }) + } + } +} \ No newline at end of file diff --git a/src/interpreter/expressions/mod.rs b/src/interpreter/expressions/mod.rs index ecd5938d..4c36dee9 100644 --- a/src/interpreter/expressions/mod.rs +++ b/src/interpreter/expressions/mod.rs @@ -152,523 +152,6 @@ impl NyashInterpreter { } - /// メソッド呼び出しを実行 - Method call processing - 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 { - // 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; - 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); - } - } - - // 📚 nyashstd標準ライブラリのメソッドチェック - 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(name) { - if let Some(builtin_method) = static_box.methods.get(method) { - Some(*builtin_method) // Copyトレイトで関数ポインターをコピー - } else { - eprintln!("🔍 Method '{}' not found in nyashstd.{}", method, name); - None - } - } else { - eprintln!("🔍 Static box '{}' not found in nyashstd", 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: {}.{}", 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: {}.{}", name, method); - return Ok(result); - } - } - - // オブジェクトを評価(通常のメソッド呼び出し) - let obj_value = self.execute_expression(object)?; - - // 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); - } - - // 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 - // 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") { - eprintln!("🔧 DEBUG: Stateful method '{}' called, updating stored instance", method); - 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); - // Handle local variables - 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); - // Handle StaticBox fields like me.server - match field_obj.as_ref() { - 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); - } - } - }, - _ => { - eprintln!("🔧 DEBUG: Object type not handled: {:?}", object); - } - } - } - - 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); - } - - // MethodBox method calls - if let Some(method_box) = obj_value.as_any().downcast_ref::() { - return self.execute_method_box_method(method_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 (将来的に追加予定) - - // RangeBox method calls (将来的に追加予定) - - // InstanceBox method calls - if let Some(instance) = obj_value.as_any().downcast_ref::() { - // 🔥 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..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::() { - 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; - 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); - } - } - - // 🔗 Phase 8.9: Weak reference invalidation after user fini - let target_info = obj_value.to_string_box().value; - eprintln!("🔗 DEBUG: Triggering weak reference invalidation for fini: {}", target_info); - self.trigger_weak_reference_invalidation(&target_info); - - // インスタンスの内部的な解放処理 - 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 = 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) @@ -855,212 +338,6 @@ impl NyashInterpreter { // } // } - /// 🔥 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, 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::() - .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), - }); - } - - // 🔥 Phase 8.8: pack透明化システム - ビルトインBox判定 - use crate::box_trait::{is_builtin_box, BUILTIN_BOXES}; - - let mut is_builtin = is_builtin_box(parent); - - // GUI機能が有効な場合はEguiBoxも追加判定 - #[cfg(all(feature = "gui", not(target_arch = "wasm32")))] - { - if parent == "EguiBox" { - is_builtin = true; - } - } - - // 🔥 Phase 8.9: Transparency system removed - all delegation must be explicit - // Removed: if is_builtin && method == parent { ... execute_builtin_constructor_call ... } - - 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またはbirthの場合の特別処理 - if method == "constructor" || method == "init" || method == "pack" || method == "birth" || 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 = 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, arguments: &[ASTNode]) - -> Result, RuntimeError> { - - // 1. 親クラスのコンストラクタを取得(引数の数でキーを作成) - // "birth/引数数"、"pack/引数数"、"init/引数数"、"Box名/引数数" の順で試す - let birth_key = format!("birth/{}", arguments.len()); - 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(&birth_key) - .or_else(|| 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 = 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, arguments: &[ASTNode])