refactor(interpreter): Step 5 - Extract builtins module

- Move execute_builtin_box_method() to expressions/builtins.rs (88 lines)
- Move execute_builtin_birth_method() to expressions/builtins.rs (74 lines)
- Complete expressions module refactoring (5/5 steps)
- Remove orphaned doc comment that prevented compilation
- Total extracted: ~380 lines from mod.rs to 4 specialized modules
- Improved maintainability with single responsibility principle
This commit is contained in:
Moe Charm
2025-08-16 13:11:53 +09:00
parent 69f42c6f1e
commit ef14f44825
3 changed files with 318 additions and 301 deletions

View File

@ -3,3 +3,144 @@
*/ */
use super::*; use super::*;
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, SharedNyashBox};
use crate::boxes::FutureBox;
use crate::{InstanceBox};
use crate::interpreter::core::{NyashInterpreter, RuntimeError};
use std::sync::Arc;
impl NyashInterpreter {
/// フィールドアクセスを実行 - Field access processing with weak reference support
pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str)
-> Result<SharedNyashBox, RuntimeError> {
// 🔥 Static Boxアクセスチェック
if let ASTNode::Variable { name, .. } = object {
// Static boxの可能性をチェック
if self.is_static_box(name) {
let static_result = self.execute_static_field_access(name, field)?;
return Ok(Arc::from(static_result));
}
}
// オブジェクトを評価(通常のフィールドアクセス)
let obj_value = self.execute_expression(object);
let obj_value = obj_value?;
// InstanceBoxにキャスト
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// フィールドの値を取得
let field_value = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in {}", field, instance.class_name),
})?;
eprintln!("✅ FIELD ACCESS: Returning shared reference id={}", field_value.box_id());
// 🔗 Weak Reference Check: Use unified accessor for weak fields
let box_decls = self.shared.box_declarations.read().unwrap();
if let Some(box_decl) = box_decls.get(&instance.class_name) {
if box_decl.weak_fields.contains(&field.to_string()) {
eprintln!("🔗 DEBUG: Accessing weak field '{}' in class '{}'", field, instance.class_name);
// 🎯 PHASE 2: Use unified accessor for auto-nil weak reference handling
if let Some(weak_value) = instance.get_weak_field(field, self) { // Pass self
match &weak_value {
crate::value::NyashValue::Null => {
eprintln!("🔗 DEBUG: Weak field '{}' is null (reference dropped)", field);
// Return null box for compatibility
return Ok(Arc::new(crate::boxes::null_box::NullBox::new()));
}
_ => {
eprintln!("🔗 DEBUG: Weak field '{}' still has valid reference", field);
// Convert back to Box<dyn NyashBox> for now
if let Ok(box_value) = weak_value.to_box() {
if let Ok(inner_box) = box_value.try_lock() {
return Ok(Arc::from(inner_box.clone_box()));
}
}
}
}
}
// If weak field access failed, fall through to normal access
}
}
// Return the shared Arc reference directly
Ok(field_value)
} else {
Err(RuntimeError::TypeError {
message: format!("Cannot access field '{}' on non-instance type. Type: {}", field, obj_value.type_name()),
})
}
}
/// 🔥 Static Box名前空間のフィールドアクセス
fn execute_static_field_access(&mut self, static_box_name: &str, field: &str)
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 1. Static Boxの初期化を確実に実行
self.ensure_static_box_initialized(static_box_name)?;
// 2. GlobalBox.statics.{static_box_name} からインスタンスを取得
let global_box = self.shared.global_box.lock()
.map_err(|_| RuntimeError::RuntimeFailure {
message: "Failed to acquire global box lock".to_string()
})?;
let statics_box = global_box.get_field("statics")
.ok_or(RuntimeError::RuntimeFailure {
message: "statics namespace not found in GlobalBox".to_string()
})?;
let statics_instance = statics_box.as_any()
.downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: "statics field is not an InstanceBox".to_string()
})?;
let static_box_instance = statics_instance.get_field(static_box_name)
.ok_or(RuntimeError::RuntimeFailure {
message: format!("Static box '{}' instance not found in statics namespace", static_box_name)
})?;
let instance = static_box_instance.as_any()
.downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: format!("Static box '{}' is not an InstanceBox", static_box_name)
})?;
// 3. フィールドアクセス
let shared_field = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in static box '{}'", field, static_box_name),
})?;
// Convert Arc to Box for compatibility
Ok((*shared_field).clone_box())
}
/// await式を実行 - Execute await expression
pub(super) fn execute_await(&mut self, expression: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
let value = self.execute_expression(expression)?;
// FutureBoxなら待機して結果を取得
if let Some(future) = value.as_any().downcast_ref::<FutureBox>() {
future.wait_and_get()
.map_err(|msg| RuntimeError::InvalidOperation { message: msg })
} else {
// FutureBoxでなければそのまま返す
Ok(value)
}
}
}

View File

@ -3,3 +3,178 @@
*/ */
use super::*; use super::*;
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, StringBox, IntegerBox, VoidBox};
use crate::boxes::{ArrayBox, MapBox, MathBox, ConsoleBox, TimeBox, RandomBox, DebugBox, SoundBox, SocketBox};
use crate::boxes::{HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
use crate::boxes::file::FileBox;
use crate::interpreter::core::{NyashInterpreter, RuntimeError};
impl NyashInterpreter {
/// 🔥 ビルトインBoxのメソッド呼び出し
pub(super) fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 🌟 Phase 8.9: birth method support for builtin boxes
if method == "birth" {
return self.execute_builtin_birth_method(parent, current_instance, arguments);
}
// ビルトインBoxのインスタンスを作成または取得
// 現在のインスタンスからビルトインBoxのデータを取得し、ビルトインBoxとしてメソッド実行
match parent {
"StringBox" => {
// StringBoxのインスタンスを作成デフォルト値
let string_box = StringBox::new("");
self.execute_string_method(&string_box, method, arguments)
}
"IntegerBox" => {
// IntegerBoxのインスタンスを作成デフォルト値
let integer_box = IntegerBox::new(0);
self.execute_integer_method(&integer_box, method, arguments)
}
"ArrayBox" => {
let array_box = ArrayBox::new();
self.execute_array_method(&array_box, method, arguments)
}
"MapBox" => {
let map_box = MapBox::new();
self.execute_map_method(&map_box, method, arguments)
}
"MathBox" => {
let math_box = MathBox::new();
self.execute_math_method(&math_box, method, arguments)
}
"P2PBox" => {
// P2PBoxの場合、現在のインスタンスからP2PBoxインスタンスを取得する必要がある
// TODO: 現在のインスタンスのフィールドからP2PBoxを取得
return Err(RuntimeError::InvalidOperation {
message: format!("P2PBox delegation not yet fully implemented: {}.{}", parent, method),
});
}
"FileBox" => {
let file_box = crate::boxes::file::FileBox::new();
self.execute_file_method(&file_box, method, arguments)
}
"ConsoleBox" => {
let console_box = ConsoleBox::new();
self.execute_console_method(&console_box, method, arguments)
}
"TimeBox" => {
let time_box = TimeBox::new();
self.execute_time_method(&time_box, method, arguments)
}
"RandomBox" => {
let random_box = RandomBox::new();
self.execute_random_method(&random_box, method, arguments)
}
"DebugBox" => {
let debug_box = DebugBox::new();
self.execute_debug_method(&debug_box, method, arguments)
}
"SoundBox" => {
let sound_box = SoundBox::new();
self.execute_sound_method(&sound_box, method, arguments)
}
"SocketBox" => {
let socket_box = SocketBox::new();
self.execute_socket_method(&socket_box, method, arguments)
}
"HTTPServerBox" => {
let http_server_box = HTTPServerBox::new();
self.execute_http_server_method(&http_server_box, method, arguments)
}
"HTTPRequestBox" => {
let http_request_box = HTTPRequestBox::new();
self.execute_http_request_method(&http_request_box, method, arguments)
}
"HTTPResponseBox" => {
let http_response_box = HTTPResponseBox::new();
self.execute_http_response_method(&http_response_box, method, arguments)
}
_ => {
Err(RuntimeError::InvalidOperation {
message: format!("Unknown built-in Box type for delegation: {}", parent),
})
}
}
}
/// 🌟 Phase 8.9: Execute birth method for builtin boxes
/// Provides constructor functionality for builtin boxes through explicit birth() calls
pub(super) fn execute_builtin_birth_method(&mut self, builtin_name: &str, current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, 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::<i64>() {
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()))
}
"ArrayBox" => {
// ArrayBoxも引数なしのコンストラクタ
if arg_values.len() != 0 {
return Err(RuntimeError::InvalidOperation {
message: format!("ArrayBox.birth() expects 0 arguments, got {}", arg_values.len()),
});
}
let array_box = ArrayBox::new();
eprintln!("🌟 DEBUG: ArrayBox.birth() created");
Ok(Box::new(VoidBox::new()))
}
_ => {
// 他のビルトインBoxは今後追加
Err(RuntimeError::InvalidOperation {
message: format!("birth() method not yet implemented for builtin box '{}'", builtin_name),
})
}
}
}
}

View File

@ -153,138 +153,6 @@ impl NyashInterpreter {
/// フィールドアクセスを実行 - Field access processing with weak reference support
pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str)
-> Result<SharedNyashBox, RuntimeError> {
// 🔥 Static Boxアクセスチェック
if let ASTNode::Variable { name, .. } = object {
// Static boxの可能性をチェック
if self.is_static_box(name) {
let static_result = self.execute_static_field_access(name, field)?;
return Ok(Arc::from(static_result));
}
}
// オブジェクトを評価(通常のフィールドアクセス)
let obj_value = self.execute_expression(object);
let obj_value = obj_value?;
// InstanceBoxにキャスト
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// フィールドの値を取得
let field_value = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in {}", field, instance.class_name),
})?;
eprintln!("✅ FIELD ACCESS: Returning shared reference id={}", field_value.box_id());
// 🔗 Weak Reference Check: Use unified accessor for weak fields
let box_decls = self.shared.box_declarations.read().unwrap();
if let Some(box_decl) = box_decls.get(&instance.class_name) {
if box_decl.weak_fields.contains(&field.to_string()) {
eprintln!("🔗 DEBUG: Accessing weak field '{}' in class '{}'", field, instance.class_name);
// 🎯 PHASE 2: Use unified accessor for auto-nil weak reference handling
if let Some(weak_value) = instance.get_weak_field(field, self) { // Pass self
match &weak_value {
crate::value::NyashValue::Null => {
eprintln!("🔗 DEBUG: Weak field '{}' is null (reference dropped)", field);
// Return null box for compatibility
return Ok(Arc::new(crate::boxes::null_box::NullBox::new()));
}
_ => {
eprintln!("🔗 DEBUG: Weak field '{}' still has valid reference", field);
// Convert back to Box<dyn NyashBox> for now
if let Ok(box_value) = weak_value.to_box() {
if let Ok(inner_box) = box_value.try_lock() {
return Ok(Arc::from(inner_box.clone_box()));
}
}
}
}
}
// If weak field access failed, fall through to normal access
}
}
// Return the shared Arc reference directly
Ok(field_value)
} else {
Err(RuntimeError::TypeError {
message: format!("Cannot access field '{}' on non-instance type. Type: {}", field, obj_value.type_name()),
})
}
}
/// 🔥 Static Box名前空間のフィールドアクセス
fn execute_static_field_access(&mut self, static_box_name: &str, field: &str)
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 1. Static Boxの初期化を確実に実行
self.ensure_static_box_initialized(static_box_name)?;
// 2. GlobalBox.statics.{static_box_name} からインスタンスを取得
let global_box = self.shared.global_box.lock()
.map_err(|_| RuntimeError::RuntimeFailure {
message: "Failed to acquire global box lock".to_string()
})?;
let statics_box = global_box.get_field("statics")
.ok_or(RuntimeError::RuntimeFailure {
message: "statics namespace not found in GlobalBox".to_string()
})?;
let statics_instance = statics_box.as_any()
.downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: "statics field is not an InstanceBox".to_string()
})?;
let static_box_instance = statics_instance.get_field(static_box_name)
.ok_or(RuntimeError::RuntimeFailure {
message: format!("Static box '{}' instance not found in statics namespace", static_box_name)
})?;
let instance = static_box_instance.as_any()
.downcast_ref::<InstanceBox>()
.ok_or(RuntimeError::TypeError {
message: format!("Static box '{}' is not an InstanceBox", static_box_name)
})?;
// 3. フィールドアクセス
let shared_field = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation {
message: format!("Field '{}' not found in static box '{}'", field, static_box_name),
})?;
// Convert Arc to Box for compatibility
Ok((*shared_field).clone_box())
}
/// await式を実行 - Execute await expression
pub(super) fn execute_await(&mut self, expression: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
let value = self.execute_expression(expression)?;
// FutureBoxなら待機して結果を取得
if let Some(future) = value.as_any().downcast_ref::<FutureBox>() {
future.wait_and_get()
.map_err(|msg| RuntimeError::InvalidOperation { message: msg })
} else {
// FutureBoxでなければそのまま返す
Ok(value)
}
}
/// 🔄 循環参照検出: オブジェクトの一意IDを取得 /// 🔄 循環参照検出: オブジェクトの一意IDを取得
fn get_object_id(&self, node: &ASTNode) -> Option<usize> { fn get_object_id(&self, node: &ASTNode) -> Option<usize> {
@ -314,7 +182,6 @@ impl NyashInterpreter {
hash hash
} }
/// 🔗 Convert NyashBox to NyashValue for weak reference operations
// fn box_to_nyash_value(&self, box_val: &Box<dyn NyashBox>) -> Option<nyash_rust::value::NyashValue> { // fn box_to_nyash_value(&self, box_val: &Box<dyn NyashBox>) -> Option<nyash_rust::value::NyashValue> {
// // Try to convert the box back to NyashValue for weak reference operations // // Try to convert the box back to NyashValue for weak reference operations
// // This is a simplified conversion - in reality we might need more sophisticated logic // // This is a simplified conversion - in reality we might need more sophisticated logic
@ -339,170 +206,4 @@ impl NyashInterpreter {
// } // }
/// 🔥 ビルトインBoxのメソッド呼び出し
fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 🌟 Phase 8.9: birth method support for builtin boxes
if method == "birth" {
return self.execute_builtin_birth_method(parent, current_instance, arguments);
}
// ビルトインBoxのインスタンスを作成または取得
// 現在のインスタンスからビルトインBoxのデータを取得し、ビルトインBoxとしてメソッド実行
match parent {
"StringBox" => {
// StringBoxのインスタンスを作成デフォルト値
let string_box = StringBox::new("");
self.execute_string_method(&string_box, method, arguments)
}
"IntegerBox" => {
// IntegerBoxのインスタンスを作成デフォルト値
let integer_box = IntegerBox::new(0);
self.execute_integer_method(&integer_box, method, arguments)
}
"ArrayBox" => {
let array_box = ArrayBox::new();
self.execute_array_method(&array_box, method, arguments)
}
"MapBox" => {
let map_box = MapBox::new();
self.execute_map_method(&map_box, method, arguments)
}
"MathBox" => {
let math_box = MathBox::new();
self.execute_math_method(&math_box, method, arguments)
}
"P2PBox" => {
// P2PBoxの場合、現在のインスタンスからP2PBoxインスタンスを取得する必要がある
// TODO: 現在のインスタンスのフィールドからP2PBoxを取得
return Err(RuntimeError::InvalidOperation {
message: format!("P2PBox delegation not yet fully implemented: {}.{}", parent, method),
});
}
"FileBox" => {
let file_box = crate::boxes::file::FileBox::new();
self.execute_file_method(&file_box, method, arguments)
}
"ConsoleBox" => {
let console_box = ConsoleBox::new();
self.execute_console_method(&console_box, method, arguments)
}
"TimeBox" => {
let time_box = TimeBox::new();
self.execute_time_method(&time_box, method, arguments)
}
"RandomBox" => {
let random_box = RandomBox::new();
self.execute_random_method(&random_box, method, arguments)
}
"DebugBox" => {
let debug_box = DebugBox::new();
self.execute_debug_method(&debug_box, method, arguments)
}
"SoundBox" => {
let sound_box = SoundBox::new();
self.execute_sound_method(&sound_box, method, arguments)
}
"SocketBox" => {
let socket_box = SocketBox::new();
self.execute_socket_method(&socket_box, method, arguments)
}
"HTTPServerBox" => {
let http_server_box = HTTPServerBox::new();
self.execute_http_server_method(&http_server_box, method, arguments)
}
"HTTPRequestBox" => {
let http_request_box = HTTPRequestBox::new();
self.execute_http_request_method(&http_request_box, method, arguments)
}
"HTTPResponseBox" => {
let http_response_box = HTTPResponseBox::new();
self.execute_http_response_method(&http_response_box, method, arguments)
}
_ => {
Err(RuntimeError::InvalidOperation {
message: format!("Unknown built-in Box type for delegation: {}", parent),
})
}
}
}
/// 🌟 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<dyn NyashBox>, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, 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::<i64>() {
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()))
}
"ArrayBox" => {
// ArrayBoxも引数なしのコンストラクタ
if arg_values.len() != 0 {
return Err(RuntimeError::InvalidOperation {
message: format!("ArrayBox.birth() expects 0 arguments, got {}", arg_values.len()),
});
}
let array_box = ArrayBox::new();
eprintln!("🌟 DEBUG: ArrayBox.birth() created");
Ok(Box::new(VoidBox::new()))
}
_ => {
// 他のビルトインBoxは今後追加
Err(RuntimeError::InvalidOperation {
message: format!("birth() method not yet implemented for builtin box '{}'", builtin_name),
})
}
}
}
} }