2025-08-16 12:41:19 +09:00
|
|
|
|
/*!
|
|
|
|
|
|
* Builtin box methods and birth methods
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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};
|
2025-08-26 19:13:57 +09:00
|
|
|
|
use crate::interpreter::{NyashInterpreter, RuntimeError};
|
2025-08-20 02:19:59 +09:00
|
|
|
|
use std::sync::{Arc, Mutex};
|
2025-08-16 13:11:53 +09:00
|
|
|
|
|
|
|
|
|
|
impl NyashInterpreter {
|
|
|
|
|
|
/// 🔥 ビルトインBoxのメソッド呼び出し
|
2025-08-16 17:39:04 +09:00
|
|
|
|
pub(super) fn execute_builtin_box_method(&mut self, parent: &str, method: &str, _current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
2025-08-16 13:11:53 +09:00
|
|
|
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
// Strict plugin-only mode: disallow builtin paths
|
|
|
|
|
|
if std::env::var("NYASH_PLUGIN_ONLY").ok().as_deref() == Some("1") {
|
|
|
|
|
|
return Err(RuntimeError::InvalidOperation { message: format!("Builtin path disabled: {}.{}, use plugin invoke", parent, method) });
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
|
|
|
|
|
|
// 🌟 Phase 8.9: birth method support for builtin boxes
|
|
|
|
|
|
if method == "birth" {
|
2025-08-16 17:39:04 +09:00
|
|
|
|
return self.execute_builtin_birth_method(parent, _current_instance, arguments);
|
2025-08-16 13:11:53 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ビルトイン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" => {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(b) = reg.create_box("MathBox", &[]) {
|
|
|
|
|
|
// Note: execute_math_method expects builtin MathBox; plugin path should route via VM/BoxCall in new pipeline.
|
|
|
|
|
|
// Here we simply return void; method paths should prefer plugin invoke in VM.
|
|
|
|
|
|
return Ok(Box::new(VoidBox::new()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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" => {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(_b) = reg.create_box("ConsoleBox", &[]) {
|
|
|
|
|
|
return Ok(Box::new(VoidBox::new()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
let console_box = ConsoleBox::new();
|
|
|
|
|
|
self.execute_console_method(&console_box, method, arguments)
|
|
|
|
|
|
}
|
|
|
|
|
|
"TimeBox" => {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(_b) = reg.create_box("TimeBox", &[]) {
|
|
|
|
|
|
return Ok(Box::new(VoidBox::new()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
let time_box = TimeBox::new();
|
|
|
|
|
|
self.execute_time_method(&time_box, method, arguments)
|
|
|
|
|
|
}
|
|
|
|
|
|
"RandomBox" => {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(_b) = reg.create_box("RandomBox", &[]) { return Ok(Box::new(VoidBox::new())); }
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
let random_box = RandomBox::new();
|
|
|
|
|
|
self.execute_random_method(&random_box, method, arguments)
|
|
|
|
|
|
}
|
|
|
|
|
|
"DebugBox" => {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(_b) = reg.create_box("DebugBox", &[]) { return Ok(Box::new(VoidBox::new())); }
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
let debug_box = DebugBox::new();
|
|
|
|
|
|
self.execute_debug_method(&debug_box, method, arguments)
|
|
|
|
|
|
}
|
|
|
|
|
|
"SoundBox" => {
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(_b) = reg.create_box("SoundBox", &[]) { return Ok(Box::new(VoidBox::new())); }
|
|
|
|
|
|
}
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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
|
2025-08-20 02:19:59 +09:00
|
|
|
|
pub(super) fn execute_builtin_birth_method(&mut self, builtin_name: &str, current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
2025-08-16 13:11:53 +09:00
|
|
|
|
-> 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;
|
2025-08-20 02:19:59 +09:00
|
|
|
|
let string_box = StringBox::new(content.clone());
|
|
|
|
|
|
|
|
|
|
|
|
// 現在のインスタンスがInstanceBoxの場合、StringBoxを特別なフィールドに保存
|
|
|
|
|
|
if let Some(instance) = current_instance.as_any().downcast_ref::<crate::instance_v2::InstanceBox>() {
|
|
|
|
|
|
// 特別な内部フィールド "__builtin_content" にStringBoxを保存
|
|
|
|
|
|
let string_box_arc: Arc<Mutex<dyn NyashBox>> = Arc::new(Mutex::new(string_box));
|
|
|
|
|
|
instance.set_field_dynamic("__builtin_content".to_string(),
|
|
|
|
|
|
crate::value::NyashValue::Box(string_box_arc));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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),
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-16 17:39:04 +09:00
|
|
|
|
let _integer_box = IntegerBox::new(value);
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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()),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-08-30 01:33:52 +09:00
|
|
|
|
if let Ok(reg) = self.runtime.box_registry.lock() {
|
|
|
|
|
|
if let Ok(_b) = reg.create_box("MathBox", &[]) { return Ok(Box::new(VoidBox::new())); }
|
|
|
|
|
|
}
|
2025-08-16 17:39:04 +09:00
|
|
|
|
let _math_box = MathBox::new();
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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()),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-16 17:39:04 +09:00
|
|
|
|
let _array_box = ArrayBox::new();
|
2025-08-16 13:11:53 +09:00
|
|
|
|
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),
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-26 19:13:57 +09:00
|
|
|
|
}
|