Files
hakorune/src/interpreter/method_dispatch.rs.legacy
Moe Charm 5582ad45c0 feat: Phase 9.78e complete - instance_v2 migration with legacy compatibility
- instance_v2 now includes legacy compatibility layer
- All interpreter code migrated to use instance_v2
- Added legacy field access methods (get_fields, set_field_legacy, etc.)
- Fixed type conversion issues (NyashValue vs SharedNyashBox)
- instance.rs still exists but no longer used in interpreter
- TODO: Remove instance.rs completely in next phase
- TODO: Implement proper SharedNyashBox -> NyashValue conversion

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 22:35:34 +09:00

688 lines
30 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* 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 crate::runtime::plugin_loader_v2::PluginBoxV2;
use std::sync::Arc;
impl NyashInterpreter {
/// メソッド呼び出しを実行 - 全Box型の統一ディスパッチ
pub(super) fn execute_method_call(&mut self, object: &ASTNode, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 🔥 static関数のチェック
if let ASTNode::Variable { name, .. } = object {
// static関数が存在するかチェック
let static_func = {
let static_funcs = self.shared.static_functions.read().unwrap();
if let Some(box_statics) = static_funcs.get(name) {
if let Some(func) = box_statics.get(method) {
Some(func.clone())
} else {
None
}
} else {
None
}
};
if let Some(static_func) = static_func {
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)?;
eprintln!("🔍 DEBUG: execute_method_call - object evaluated to type_name='{}', box_id={}",
obj_value.type_name(), obj_value.box_id());
// 各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<Box<dyn NyashBox>, 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<dyn NyashBox>;
for statement in &body {
result = self.execute_statement(statement)?;
// return文チェック
if let super::ControlFlow::Return(return_val) = &self.control_flow {
result = return_val.clone_box();
self.control_flow = super::ControlFlow::None;
break;
}
}
// local変数スタックを復元
self.restore_local_vars(saved_locals);
// outbox変数スタックを復元
self.restore_outbox_vars(saved_outbox);
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<Option<Box<dyn NyashBox>>, 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<dyn NyashBox>,
method: &str,
arguments: &[ASTNode],
object: &ASTNode
) -> Result<Box<dyn NyashBox>, RuntimeError> {
// Debug: Log the actual type
eprintln!("🔍 DEBUG: dispatch_builtin_method called for type_name='{}', method='{}'",
obj_value.type_name(), method);
eprintln!("🔍 DEBUG: obj_value box_id={}", obj_value.box_id());
// StringBox method calls
if let Some(string_box) = obj_value.as_any().downcast_ref::<StringBox>() {
eprintln!("🔍 DEBUG: Matched as StringBox!");
return self.execute_string_method(string_box, method, arguments);
}
// IntegerBox method calls
if let Some(integer_box) = obj_value.as_any().downcast_ref::<IntegerBox>() {
return self.execute_integer_method(integer_box, method, arguments);
}
// FloatBox method calls
if let Some(float_box) = obj_value.as_any().downcast_ref::<FloatBox>() {
return self.execute_float_method(float_box, method, arguments);
}
// BoolBox method calls
if let Some(bool_box) = obj_value.as_any().downcast_ref::<BoolBox>() {
return self.execute_bool_method(bool_box, method, arguments);
}
// ArrayBox method calls
if let Some(array_box) = obj_value.as_any().downcast_ref::<ArrayBox>() {
return self.execute_array_method(array_box, method, arguments);
}
// BufferBox method calls
if let Some(buffer_box) = obj_value.as_any().downcast_ref::<BufferBox>() {
return self.execute_buffer_method(buffer_box, method, arguments);
}
// FileBox method calls
if let Some(file_box) = obj_value.as_any().downcast_ref::<crate::boxes::file::FileBox>() {
return self.execute_file_method(file_box, method, arguments);
}
// Plugin-backed FileBox method calls
if let Some(pfile) = obj_value.as_any().downcast_ref::<PluginFileBox>() {
return self.execute_plugin_file_method(pfile, method, arguments);
}
// ResultBox method calls
if let Some(result_box) = obj_value.as_any().downcast_ref::<ResultBox>() {
return self.execute_result_method(result_box, method, arguments);
}
// FutureBox method calls
if let Some(future_box) = obj_value.as_any().downcast_ref::<FutureBox>() {
return self.execute_future_method(future_box, method, arguments);
}
// ChannelBox method calls
if let Some(channel_box) = obj_value.as_any().downcast_ref::<ChannelBox>() {
return self.execute_channel_method(channel_box, method, arguments);
}
// JSONBox method calls
if let Some(json_box) = obj_value.as_any().downcast_ref::<JSONBox>() {
return self.execute_json_method(json_box, method, arguments);
}
// HttpClientBox method calls
if let Some(http_box) = obj_value.as_any().downcast_ref::<HttpClientBox>() {
return self.execute_http_method(http_box, method, arguments);
}
// StreamBox method calls
if let Some(stream_box) = obj_value.as_any().downcast_ref::<StreamBox>() {
return self.execute_stream_method(stream_box, method, arguments);
}
// RegexBox method calls
if let Some(regex_box) = obj_value.as_any().downcast_ref::<RegexBox>() {
return self.execute_regex_method(regex_box, method, arguments);
}
// MathBox method calls
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
return self.execute_math_method(math_box, method, arguments);
}
// NullBox method calls
if let Some(null_box) = obj_value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>() {
return self.execute_null_method(null_box, method, arguments);
}
// TimeBox method calls
if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() {
return self.execute_time_method(time_box, method, arguments);
}
// DateTimeBox method calls
if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() {
return self.execute_datetime_method(datetime_box, method, arguments);
}
// TimerBox method calls
if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() {
return self.execute_timer_method(timer_box, method, arguments);
}
// MapBox method calls
if let Some(map_box) = obj_value.as_any().downcast_ref::<MapBox>() {
return self.execute_map_method(map_box, method, arguments);
}
// RandomBox method calls
if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() {
return self.execute_random_method(random_box, method, arguments);
}
// SoundBox method calls
if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() {
return self.execute_sound_method(sound_box, method, arguments);
}
// DebugBox method calls
if let Some(debug_box) = obj_value.as_any().downcast_ref::<DebugBox>() {
return self.execute_debug_method(debug_box, method, arguments);
}
// ConsoleBox method calls
if let Some(console_box) = obj_value.as_any().downcast_ref::<crate::boxes::console_box::ConsoleBox>() {
return self.execute_console_method(console_box, method, arguments);
}
// IntentBox method calls
if let Some(intent_box) = obj_value.as_any().downcast_ref::<IntentBox>() {
return self.execute_intent_box_method(intent_box, method, arguments);
}
// SocketBox method calls
if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() {
let result = self.execute_socket_method(socket_box, method, arguments)?;
// 🔧 FIX: Update stored variable for stateful SocketBox methods
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::<HTTPServerBox>() {
return self.execute_http_server_method(http_server_box, method, arguments);
}
// HTTPRequestBox method calls
if let Some(http_request_box) = obj_value.as_any().downcast_ref::<HTTPRequestBox>() {
return self.execute_http_request_method(http_request_box, method, arguments);
}
// HTTPResponseBox method calls
if let Some(http_response_box) = obj_value.as_any().downcast_ref::<HTTPResponseBox>() {
return self.execute_http_response_method(http_response_box, method, arguments);
}
// P2PBox method calls - Temporarily disabled
// if let Some(p2p_box) = obj_value.as_any().downcast_ref::<P2PBox>() {
// return self.execute_p2p_box_method(p2p_box, method, arguments);
// }
// EguiBox method calls (非WASM環境のみ)
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
if let Some(egui_box) = obj_value.as_any().downcast_ref::<crate::boxes::EguiBox>() {
return self.execute_egui_method(egui_box, method, arguments);
}
// WebDisplayBox method calls (WASM環境のみ)
#[cfg(target_arch = "wasm32")]
if let Some(web_display_box) = obj_value.as_any().downcast_ref::<crate::boxes::WebDisplayBox>() {
return self.execute_web_display_method(web_display_box, method, arguments);
}
// WebConsoleBox method calls (WASM環境のみ)
#[cfg(target_arch = "wasm32")]
if let Some(web_console_box) = obj_value.as_any().downcast_ref::<crate::boxes::WebConsoleBox>() {
return self.execute_web_console_method(web_console_box, method, arguments);
}
// WebCanvasBox method calls (WASM環境のみ)
#[cfg(target_arch = "wasm32")]
if let Some(web_canvas_box) = obj_value.as_any().downcast_ref::<crate::boxes::WebCanvasBox>() {
return self.execute_web_canvas_method(web_canvas_box, method, arguments);
}
// PluginBoxV2 method calls
eprintln!("🔍 DEBUG: Checking for PluginBoxV2...");
if let Some(plugin_box) = obj_value.as_any().downcast_ref::<PluginBoxV2>() {
eprintln!("🔍 DEBUG: Matched as PluginBoxV2! box_type={}, instance_id={}",
plugin_box.box_type, plugin_box.instance_id);
return self.execute_plugin_box_v2_method(plugin_box, method, arguments);
}
eprintln!("🔍 DEBUG: Not matched as PluginBoxV2")
// ユーザー定義Boxのメソッド呼び出し
self.execute_user_defined_method(obj_value, method, arguments)
}
fn execute_plugin_file_method(
&mut self,
pfile: &PluginFileBox,
method: &str,
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, 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) })
}
}
fn execute_plugin_box_v2_method(
&mut self,
plugin_box: &PluginBoxV2,
method: &str,
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
eprintln!("🔍 execute_plugin_box_v2_method called: {}.{}", plugin_box.box_type, method);
// Get global loader to access configuration
let loader = crate::runtime::plugin_loader_v2::get_global_loader_v2();
let loader = loader.read().unwrap();
// Get method_id from configuration
let method_id = if let Some(config) = &loader.config {
// Find library that provides this box type
let (lib_name, _) = config.find_library_for_box(&plugin_box.box_type)
.ok_or_else(|| RuntimeError::InvalidOperation {
message: format!("No plugin provides box type: {}", plugin_box.box_type)
})?;
// Get method_id from toml
if let Ok(toml_content) = std::fs::read_to_string("nyash.toml") {
if let Ok(toml_value) = toml::from_str::<toml::Value>(&toml_content) {
if let Some(box_config) = config.get_box_config(lib_name, &plugin_box.box_type, &toml_value) {
if let Some(method_config) = box_config.methods.get(method) {
eprintln!("🔍 Found method {} with id: {}", method, method_config.method_id);
method_config.method_id
} else {
return Err(RuntimeError::InvalidOperation {
message: format!("Unknown method '{}' for {}", method, plugin_box.box_type)
});
}
} else {
return Err(RuntimeError::InvalidOperation {
message: format!("No configuration for box type: {}", plugin_box.box_type)
});
}
} else {
return Err(RuntimeError::InvalidOperation {
message: "Failed to parse nyash.toml".into()
});
}
} else {
return Err(RuntimeError::InvalidOperation {
message: "Failed to read nyash.toml".into()
});
}
} else {
return Err(RuntimeError::InvalidOperation {
message: "No configuration loaded".into()
});
};
// Evaluate arguments
eprintln!("🔍 DEBUG: Evaluating {} arguments for {}.{}", arguments.len(), plugin_box.box_type, method);
let mut arg_values = Vec::new();
for (i, arg) in arguments.iter().enumerate() {
eprintln!("🔍 DEBUG: Evaluating argument {}", i);
arg_values.push(self.execute_expression(arg)?);
}
eprintln!("🔍 DEBUG: All {} arguments evaluated", arg_values.len());
// Encode arguments using TLV (plugin's expected format)
let mut tlv_data = Vec::new();
// Header: version(2 bytes) + argc(2 bytes)
tlv_data.extend_from_slice(&1u16.to_le_bytes()); // version = 1
tlv_data.extend_from_slice(&(arg_values.len() as u16).to_le_bytes()); // argc
// Encode each argument
for (i, arg) in arg_values.iter().enumerate() {
// For now, convert all arguments to strings
let arg_str = arg.to_string_box().value;
let arg_bytes = arg_str.as_bytes();
// TLV entry: tag(1) + reserved(1) + size(2) + data
tlv_data.push(6); // tag = 6 (String)
tlv_data.push(0); // reserved
tlv_data.extend_from_slice(&(arg_bytes.len() as u16).to_le_bytes()); // size
tlv_data.extend_from_slice(arg_bytes); // data
}
// Debug: print TLV data
eprintln!("🔍 TLV data (len={}): {:?}", tlv_data.len(),
tlv_data.iter().map(|b| format!("{:02x}", b)).collect::<Vec<_>>().join(" "));
// Prepare output buffer
let mut output_buffer = vec![0u8; 4096]; // 4KB buffer
let mut output_len = output_buffer.len();
eprintln!("🔍 Calling plugin invoke_fn: type_id={}, method_id={}, instance_id={}",
plugin_box.type_id, method_id, plugin_box.instance_id);
// Call plugin method
let result = unsafe {
(plugin_box.invoke_fn)(
plugin_box.type_id, // type_id from PluginBoxV2
method_id, // method_id
plugin_box.instance_id, // instance_id
tlv_data.as_ptr(), // arguments
tlv_data.len(), // arguments length
output_buffer.as_mut_ptr(), // output buffer
&mut output_len, // output length
)
};
eprintln!("🔍 Plugin method returned: {}", result);
if result != 0 {
return Err(RuntimeError::RuntimeFailure {
message: format!("Plugin method {} failed with code: {}", method, result)
});
}
// Parse TLV output dynamically
if output_len >= 4 {
// Parse TLV header
let version = u16::from_le_bytes([output_buffer[0], output_buffer[1]]);
let argc = u16::from_le_bytes([output_buffer[2], output_buffer[3]]);
eprintln!("🔍 TLV response: version={}, argc={}", version, argc);
if version == 1 && argc > 0 && output_len >= 8 {
// Parse first TLV entry
let tag = output_buffer[4];
let _reserved = output_buffer[5];
let size = u16::from_le_bytes([output_buffer[6], output_buffer[7]]) as usize;
eprintln!("🔍 TLV entry: tag={}, size={}", tag, size);
if output_len >= 8 + size {
match tag {
2 => {
// I32 type
if size == 4 {
let value = i32::from_le_bytes([
output_buffer[8], output_buffer[9],
output_buffer[10], output_buffer[11]
]);
Ok(Box::new(IntegerBox::new(value as i64)))
} else {
Ok(Box::new(StringBox::new("ok")))
}
}
6 | 7 => {
// String or Bytes type
let data = &output_buffer[8..8+size];
let string = String::from_utf8_lossy(data).to_string();
Ok(Box::new(StringBox::new(string)))
}
9 => {
// Void type
Ok(Box::new(StringBox::new("ok")))
}
_ => {
// Unknown type, treat as string
eprintln!("🔍 Unknown TLV tag: {}", tag);
Ok(Box::new(StringBox::new("ok")))
}
}
} else {
eprintln!("🔍 TLV data truncated");
Ok(Box::new(StringBox::new("ok")))
}
} else {
// No valid TLV data
Ok(Box::new(StringBox::new("ok")))
}
} else {
// No output or too short
Ok(Box::new(StringBox::new("ok")))
}
}
/// 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::<InstanceBox>() {
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::<InstanceBox>() {
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<dyn NyashBox>,
method: &str,
arguments: &[ASTNode]
) -> Result<Box<dyn NyashBox>, RuntimeError> {
// InstanceBox method calls (user-defined methods)
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
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()),
})
}
}