diff --git a/src/interpreter/async_ops.rs b/src/interpreter/async_ops.rs new file mode 100644 index 00000000..3ce8a31d --- /dev/null +++ b/src/interpreter/async_ops.rs @@ -0,0 +1,25 @@ +/*! + * Async Operations Module + * + * Extracted from expressions.rs lines 1020-1031 (~11 lines) + * Handles await expression processing for asynchronous operations + * Core philosophy: "Everything is Box" with async support + */ + +use super::*; + +impl NyashInterpreter { + /// await式を実行 - 非同期操作の結果を待機 + pub(super) fn execute_await(&mut self, expression: &ASTNode) -> Result, RuntimeError> { + let value = self.execute_expression(expression)?; + + // FutureBoxなら待機して結果を取得 + if let Some(future) = value.as_any().downcast_ref::() { + future.wait_and_get() + .map_err(|msg| RuntimeError::InvalidOperation { message: msg }) + } else { + // FutureBoxでなければそのまま返す + Ok(value) + } + } +} \ No newline at end of file diff --git a/src/interpreter/delegation.rs b/src/interpreter/delegation.rs new file mode 100644 index 00000000..9a70f058 --- /dev/null +++ b/src/interpreter/delegation.rs @@ -0,0 +1,334 @@ +/*! + * Delegation Processing Module + * + * Extracted from expressions.rs lines 1086-1457 (~371 lines) + * Handles 'from' calls, delegation validation, and builtin box method calls + * Core philosophy: "Everything is Box" with explicit delegation + */ + +use super::*; + +impl NyashInterpreter { + /// from呼び出しを実行 - 完全明示デリゲーション + 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 + // ビルトインBoxの場合、専用メソッドで処理 + if is_builtin { + 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. 通常の親メソッド実行 + self.execute_parent_method(parent, method, &parent_box_decl, current_instance_val.clone_box(), arguments) + } + + /// 親クラスのメソッドを実行 + fn execute_parent_method( + &mut self, + parent: &str, + method: &str, + parent_box_decl: &super::BoxDeclaration, + current_instance_val: Box, + arguments: &[ASTNode] + ) -> Result, RuntimeError> { + // 親クラスのメソッドを取得 + let parent_method = parent_box_decl.methods.get(method) + .ok_or(RuntimeError::InvalidOperation { + message: format!("Method '{}' not found in parent class '{}'", method, parent), + })? + .clone(); + + // 引数を評価 + let mut arg_values = Vec::new(); + for arg in arguments { + arg_values.push(self.execute_expression(arg)?); + } + + // 親メソッドを実行 + 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]) + -> Result, RuntimeError> { + + // 🌟 Phase 8.9: birth method support for builtin boxes + if method == "birth" { + return self.execute_builtin_birth_method(parent, current_instance, arguments); + } + + // ビルトインBoxのインスタンスを作成または取得 + match parent { + "StringBox" => { + let string_box = StringBox::new(""); + self.execute_string_method(&string_box, method, arguments) + } + "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) + } + // 他のビルトインBoxは必要に応じて追加 + _ => { + Err(RuntimeError::InvalidOperation { + message: format!("Builtin box '{}' method '{}' not implemented", parent, method), + }) + } + } + } + + /// 🌟 Phase 8.9: Execute birth method for builtin boxes + /// Provides constructor functionality for builtin boxes through explicit birth() calls + fn execute_builtin_birth_method(&mut self, builtin_name: &str, current_instance: Box, arguments: &[ASTNode]) + -> Result, RuntimeError> { + + // 引数を評価 + let mut arg_values = Vec::new(); + for arg in arguments { + arg_values.push(self.execute_expression(arg)?); + } + + // ビルトインBoxの種類に応じて適切なインスタンスを作成して返す + match builtin_name { + "StringBox" => { + if arg_values.len() != 1 { + return Err(RuntimeError::InvalidOperation { + message: format!("StringBox.birth() expects 1 argument, got {}", arg_values.len()), + }); + } + + let content = arg_values[0].to_string_box().value; + eprintln!("🌟 DEBUG: StringBox.birth() created with content: '{}'", content); + let string_box = StringBox::new(content); + Ok(Box::new(VoidBox::new())) // Return void to indicate successful initialization + } + "IntegerBox" => { + if arg_values.len() != 1 { + return Err(RuntimeError::InvalidOperation { + message: format!("IntegerBox.birth() expects 1 argument, got {}", arg_values.len()), + }); + } + + let value = if let Ok(int_val) = arg_values[0].to_string_box().value.parse::() { + int_val + } else { + return Err(RuntimeError::TypeError { + message: format!("Cannot convert '{}' to integer", arg_values[0].to_string_box().value), + }); + }; + + let integer_box = IntegerBox::new(value); + eprintln!("🌟 DEBUG: IntegerBox.birth() created with value: {}", value); + Ok(Box::new(VoidBox::new())) + } + "MathBox" => { + // MathBoxは引数なしのコンストラクタ + if arg_values.len() != 0 { + return Err(RuntimeError::InvalidOperation { + message: format!("MathBox.birth() expects 0 arguments, got {}", arg_values.len()), + }); + } + + let math_box = MathBox::new(); + eprintln!("🌟 DEBUG: MathBox.birth() created"); + Ok(Box::new(VoidBox::new())) + } + // 他のビルトインBoxは必要に応じて追加 + _ => { + Err(RuntimeError::InvalidOperation { + message: format!("birth() method not implemented for builtin box '{}'", builtin_name), + }) + } + } + } +} \ No newline at end of file diff --git a/src/interpreter/field_access.rs b/src/interpreter/field_access.rs new file mode 100644 index 00000000..6f27e5ba --- /dev/null +++ b/src/interpreter/field_access.rs @@ -0,0 +1,132 @@ +/*! + * Field Access Processing Module + * + * Extracted from expressions.rs lines 901-1019 (~118 lines) + * Handles field access for static boxes and instance boxes + * Core philosophy: "Everything is Box" with unified field access + */ + +use super::*; +use crate::box_trait::SharedNyashBox; +use std::sync::Arc; + +impl NyashInterpreter { + /// フィールドアクセスを実行 - static box と instance box の統一処理 + pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str) + -> Result { + + // 🔥 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)?; + + // InstanceBoxにキャスト + if let Some(instance) = obj_value.as_any().downcast_ref::() { + return self.execute_instance_field_access(instance, field); + } + + Err(RuntimeError::InvalidOperation { + message: format!("Cannot access field '{}' on type '{}'", field, obj_value.type_name()), + }) + } + + /// Static Boxフィールドアクセス実行 + pub(super) fn execute_static_field_access(&mut self, box_name: &str, field: &str) + -> Result, RuntimeError> { + + let static_boxes = self.shared.static_boxes.read().unwrap(); + if let Some(static_box) = static_boxes.get(box_name) { + let field_value = static_box.get_field(field) + .ok_or(RuntimeError::InvalidOperation { + message: format!("Field '{}' not found in static box '{}'", field, box_name), + })?; + + Ok((*field_value).clone_box()) + } else { + Err(RuntimeError::InvalidOperation { + message: format!("Static box '{}' not found", box_name), + }) + } + } + + /// Instance Boxフィールドアクセス実行 + fn execute_instance_field_access(&mut self, instance: &InstanceBox, field: &str) + -> Result { + + // 🔥 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 is_weak_field = { + let box_decls = self.shared.box_declarations.read().unwrap(); + if let Some(box_decl) = box_decls.get(&instance.class_name) { + box_decl.weak_fields.contains(&field.to_string()) + } else { + false + } + }; + + if is_weak_field { + return self.handle_weak_field_access(instance, field); + } + + // 通常のフィールドアクセス + Ok(field_value) + } + + /// Weak参照フィールドアクセス処理 + fn handle_weak_field_access(&mut self, instance: &InstanceBox, field: &str) + -> Result { + + 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 + Ok(Arc::new(crate::boxes::null_box::NullBox::new())) + } + _ => { + eprintln!("🔗 DEBUG: Weak field '{}' has live reference", field); + let converted_box = weak_value.to_nyash_box(); + Ok(Arc::new(converted_box)) + } + } + } else { + eprintln!("🔗 DEBUG: Weak field '{}' not found, falling back to normal access", field); + // Fallback to normal field access if weak accessor fails + let field_value = instance.get_field(field) + .ok_or(RuntimeError::InvalidOperation { + message: format!("Field '{}' not found in {}", field, instance.class_name), + })?; + Ok(field_value) + } + } + + /// Static Boxかどうかを判定 + pub(super) fn is_static_box(&self, name: &str) -> bool { + let static_boxes = self.shared.static_boxes.read().unwrap(); + static_boxes.contains_key(name) + } +} \ No newline at end of file diff --git a/src/interpreter/method_dispatch.rs b/src/interpreter/method_dispatch.rs new file mode 100644 index 00000000..a0fb4f10 --- /dev/null +++ b/src/interpreter/method_dispatch.rs @@ -0,0 +1,458 @@ +/*! + * 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 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); + } + + // 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) + } + + /// 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()), + }) + } +} \ No newline at end of file diff --git a/src/interpreter/operators.rs b/src/interpreter/operators.rs new file mode 100644 index 00000000..efa08230 --- /dev/null +++ b/src/interpreter/operators.rs @@ -0,0 +1,328 @@ +/*! + * Operators Processing Module + * + * Extracted from expressions.rs + * Handles binary operations, unary operations, and operator helper functions + * Core philosophy: "Everything is Box" with type-safe operator overloading + */ + +use super::*; +use crate::ast::UnaryOperator; +use crate::box_trait::{BoolBox, SharedNyashBox}; +use crate::operator_traits::{DynamicAdd, DynamicSub, DynamicMul, DynamicDiv, OperatorError}; + +// ======================================================================================== +// Helper Functions for Binary Operations +// ======================================================================================== + +pub(super) fn try_add_operation(left: &dyn NyashBox, right: &dyn NyashBox) -> Option> { + // IntegerBox + IntegerBox + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Some(Box::new(IntegerBox::new(left_int.value + right_int.value))); + } + + // StringBox + anything -> concatenation + if let Some(left_str) = left.as_any().downcast_ref::() { + let right_str = right.to_string_box(); + return Some(Box::new(StringBox::new(format!("{}{}", left_str.value, right_str.value)))); + } + + // BoolBox + BoolBox -> IntegerBox + if let (Some(left_bool), Some(right_bool)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Some(Box::new(IntegerBox::new((left_bool.value as i64) + (right_bool.value as i64)))); + } + + None +} + +pub(super) fn try_sub_operation(left: &dyn NyashBox, right: &dyn NyashBox) -> Option> { + // IntegerBox - IntegerBox + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Some(Box::new(IntegerBox::new(left_int.value - right_int.value))); + } + None +} + +pub(super) fn try_mul_operation(left: &dyn NyashBox, right: &dyn NyashBox) -> Option> { + // IntegerBox * IntegerBox + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Some(Box::new(IntegerBox::new(left_int.value * right_int.value))); + } + + // StringBox * IntegerBox -> repetition + if let (Some(str_box), Some(count_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Some(Box::new(StringBox::new(str_box.value.repeat(count_int.value as usize)))); + } + + None +} + +pub(super) fn try_div_operation(left: &dyn NyashBox, right: &dyn NyashBox) -> Result, String> { + // IntegerBox / IntegerBox + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + if right_int.value == 0 { + return Err("Division by zero".to_string()); + } + return Ok(Box::new(IntegerBox::new(left_int.value / right_int.value))); + } + + Err(format!("Division not supported between {} and {}", left.type_name(), right.type_name())) +} + +pub(super) fn try_mod_operation(left: &dyn NyashBox, right: &dyn NyashBox) -> Result, String> { + // IntegerBox % IntegerBox + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + if right_int.value == 0 { + return Err("Modulo by zero".to_string()); + } + return Ok(Box::new(IntegerBox::new(left_int.value % right_int.value))); + } + + Err(format!("Modulo not supported between {} and {}", left.type_name(), right.type_name())) +} + +// ======================================================================================== +// NyashInterpreter Implementation - Binary and Unary Operations +// ======================================================================================== + +impl NyashInterpreter { + /// 二項演算を実行 + pub(super) fn execute_binary_op(&mut self, op: &BinaryOperator, left: &ASTNode, right: &ASTNode) + -> Result, RuntimeError> + { + // 🎯 State-sharing evaluation for performance + let left_shared = self.execute_expression_shared(left)?; + let right_shared = self.execute_expression_shared(right)?; + let left_val = &**left_shared; + let right_val = &**right_shared; + + match op { + BinaryOperator::Add => { + if let Some(result) = try_add_operation(left_val, right_val) { + Ok(result) + } else { + Err(RuntimeError::InvalidOperation { + message: format!("Cannot add {} and {}", left_val.type_name(), right_val.type_name()), + }) + } + }, + + BinaryOperator::Subtract => { + if let Some(result) = try_sub_operation(left_val, right_val) { + Ok(result) + } else { + Err(RuntimeError::InvalidOperation { + message: format!("Cannot subtract {} from {}", right_val.type_name(), left_val.type_name()), + }) + } + }, + + BinaryOperator::Multiply => { + if let Some(result) = try_mul_operation(left_val, right_val) { + Ok(result) + } else { + Err(RuntimeError::InvalidOperation { + message: format!("Cannot multiply {} and {}", left_val.type_name(), right_val.type_name()), + }) + } + }, + + BinaryOperator::Divide => { + match try_div_operation(left_val, right_val) { + Ok(result) => Ok(result), + Err(msg) => Err(RuntimeError::InvalidOperation { message: msg }), + } + }, + + BinaryOperator::Modulo => { + match try_mod_operation(left_val, right_val) { + Ok(result) => Ok(result), + Err(msg) => Err(RuntimeError::InvalidOperation { message: msg }), + } + }, + + BinaryOperator::Equal => { + let result = self.compare_values(left_val, right_val)?; + Ok(Box::new(BoolBox::new(result))) + }, + + BinaryOperator::NotEqual => { + let result = self.compare_values(left_val, right_val)?; + Ok(Box::new(BoolBox::new(!result))) + }, + + BinaryOperator::LessThan => { + let result = self.less_than_values(left_val, right_val)?; + Ok(Box::new(BoolBox::new(result))) + }, + + BinaryOperator::LessThanOrEqual => { + let less = self.less_than_values(left_val, right_val)?; + let equal = self.compare_values(left_val, right_val)?; + Ok(Box::new(BoolBox::new(less || equal))) + }, + + BinaryOperator::GreaterThan => { + let less = self.less_than_values(left_val, right_val)?; + let equal = self.compare_values(left_val, right_val)?; + Ok(Box::new(BoolBox::new(!less && !equal))) + }, + + BinaryOperator::GreaterThanOrEqual => { + let less = self.less_than_values(left_val, right_val)?; + Ok(Box::new(BoolBox::new(!less))) + }, + + BinaryOperator::And => { + // Short-circuit evaluation + if !self.is_truthy(left_val) { + Ok(Box::new(BoolBox::new(false))) + } else { + Ok(Box::new(BoolBox::new(self.is_truthy(right_val)))) + } + }, + + BinaryOperator::Or => { + // Short-circuit evaluation + if self.is_truthy(left_val) { + Ok(Box::new(BoolBox::new(true))) + } else { + Ok(Box::new(BoolBox::new(self.is_truthy(right_val)))) + } + }, + } + } + + /// 単項演算を実行 + pub(super) fn execute_unary_op(&mut self, operator: &UnaryOperator, operand: &ASTNode) + -> Result, RuntimeError> + { + let operand_shared = self.execute_expression_shared(operand)?; + let operand_val = &**operand_shared; + + match operator { + UnaryOperator::Not => { + let is_truthy = self.is_truthy(operand_val); + Ok(Box::new(BoolBox::new(!is_truthy))) + }, + UnaryOperator::Minus => { + if let Some(int_val) = operand_val.as_any().downcast_ref::() { + Ok(Box::new(IntegerBox::new(-int_val.value))) + } else { + Err(RuntimeError::InvalidOperation { + message: format!("Cannot negate {}", operand_val.type_name()), + }) + } + }, + } + } + + // ======================================================================================== + // Helper Methods for Comparisons + // ======================================================================================== + + /// 値の等価性を比較 + pub(super) fn compare_values(&self, left: &dyn NyashBox, right: &dyn NyashBox) -> Result { + // IntegerBox comparison + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Ok(left_int.value == right_int.value); + } + + // StringBox comparison + if let (Some(left_str), Some(right_str)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Ok(left_str.value == right_str.value); + } + + // BoolBox comparison + if let (Some(left_bool), Some(right_bool)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Ok(left_bool.value == right_bool.value); + } + + // NullBox comparison + if left.type_name() == "NullBox" && right.type_name() == "NullBox" { + return Ok(true); + } + + // Different types are not equal + Ok(false) + } + + /// 値の大小関係を比較 (left < right) + pub(super) fn less_than_values(&self, left: &dyn NyashBox, right: &dyn NyashBox) -> Result { + // IntegerBox comparison + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Ok(left_int.value < right_int.value); + } + + // StringBox comparison (lexicographic) + if let (Some(left_str), Some(right_str)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return Ok(left_str.value < right_str.value); + } + + Err(RuntimeError::InvalidOperation { + message: format!("Cannot compare {} and {}", left.type_name(), right.type_name()), + }) + } + + /// 値の真偽性を判定 + pub(super) fn is_truthy(&self, value: &dyn NyashBox) -> bool { + // BoolBox + if let Some(bool_val) = value.as_any().downcast_ref::() { + return bool_val.value; + } + + // IntegerBox (0 is false, non-zero is true) + if let Some(int_val) = value.as_any().downcast_ref::() { + return int_val.value != 0; + } + + // StringBox (empty string is false) + if let Some(str_val) = value.as_any().downcast_ref::() { + return !str_val.value.is_empty(); + } + + // NullBox is always false + if value.type_name() == "NullBox" { + return false; + } + + // Everything else is true + true + } +} \ No newline at end of file diff --git a/src/interpreter/utils.rs b/src/interpreter/utils.rs new file mode 100644 index 00000000..0cfee34a --- /dev/null +++ b/src/interpreter/utils.rs @@ -0,0 +1,49 @@ +/*! + * Utility Functions Module + * + * Extracted from expressions.rs lines 1033-1085 (~52 lines) + * Handles utility functions for object identification and hash calculations + * Core philosophy: "Everything is Box" with helper utilities + */ + +use super::*; + +impl NyashInterpreter { + /// 🔄 循環参照検出: オブジェクトの一意IDを取得 + pub(super) fn get_object_id(&self, node: &ASTNode) -> Option { + 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追跡しない + } + } + + /// 🔄 文字列のシンプルなハッシュ関数 + pub(super) 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 + /// Note: Currently commented out due to complexity, to be implemented in future phases + #[allow(dead_code)] + fn box_to_nyash_value(&self, _box_val: &Box) -> Option { + // This is a placeholder for future weak reference implementation + // When implemented, this will convert Box types back to NyashValue + // for proper weak reference storage and management + None + } +} \ No newline at end of file