refactor: Extract basic type constructors from execute_new function

- Create objects_basic_constructors.rs with create_basic_box() method
- Handle StringBox, IntegerBox, BoolBox, ArrayBox, NullBox, FloatBox, MapBox
- Reduce execute_new function complexity by delegating basic types
- Start decomposing 875-line function into manageable modules
- All tests pass successfully
This commit is contained in:
Moe Charm
2025-08-21 12:28:47 +09:00
parent 4f360e0fbb
commit bf0229c24a
4 changed files with 254 additions and 13 deletions

View File

@ -34,6 +34,7 @@ mod expressions;
mod statements;
mod functions;
mod objects;
mod objects_basic_constructors;
mod io;
mod methods;
mod math_methods;

View File

@ -88,22 +88,22 @@ impl NyashInterpreter {
// 🚧 Legacy implementation (will be removed in Phase 9.78e)
eprintln!("🔍 Falling back to legacy match statement for: {}", class);
// 組み込みBox型のチェック
// Try basic type constructors first
if let Ok(basic_box) = self.create_basic_box(class, arguments) {
return Ok(basic_box);
}
// 組み込みBox型のチェック (基本型以外)
eprintln!("🔍 Starting built-in Box type checks...");
match class {
// Basic Box constructors (CRITICAL - these were missing!)
"StringBox" => {
// StringBoxは引数1個文字列値で作成
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("StringBox constructor expects 1 argument, got {}", arguments.len()),
});
}
let value = self.execute_expression(&arguments[0])?;
let string_value = value.to_string_box().value;
let string_box = Box::new(StringBox::new(string_value)) as Box<dyn NyashBox>;
return Ok(string_box);
// Basic types are handled by create_basic_box() above
"StringBox" | "IntegerBox" | "BoolBox" | "ArrayBox" | "ResultBox" |
"ErrorBox" | "NullBox" | "FloatBox" | "MapBox" => {
// These are handled by create_basic_box(), should not reach here
unreachable!("Basic type {} should have been handled by create_basic_box()", class);
}
/* Basic types are now handled by create_basic_box() - keeping for reference
"IntegerBox" => {
// IntegerBoxは引数1個整数値で作成
if arguments.len() != 1 {

View File

@ -0,0 +1,157 @@
//! Basic type constructors for execute_new
//! Handles StringBox, IntegerBox, BoolBox, ArrayBox, etc.
use crate::ast::ASTNode;
use crate::box_trait::*;
use crate::interpreter::core::{NyashInterpreter as Interpreter, RuntimeError};
use crate::boxes::FloatBox;
use crate::NullBox;
use crate::MapBox;
impl Interpreter {
/// Create basic type boxes (StringBox, IntegerBox, BoolBox, etc.)
pub(super) fn create_basic_box(
&mut self,
class: &str,
arguments: &[ASTNode]
) -> Result<Box<dyn NyashBox>, RuntimeError> {
match class {
"StringBox" => {
// StringBoxは引数1個文字列値で作成
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("StringBox constructor expects 1 argument, got {}", arguments.len()),
});
}
let value = self.execute_expression(&arguments[0])?;
if let Some(s) = value.as_any().downcast_ref::<StringBox>() {
return Ok(Box::new(StringBox::new(s.value.clone())));
} else if let Some(i) = value.as_any().downcast_ref::<IntegerBox>() {
return Ok(Box::new(StringBox::new(i.value.to_string())));
} else if let Some(b) = value.as_any().downcast_ref::<BoolBox>() {
return Ok(Box::new(StringBox::new(b.value.to_string())));
} else {
return Ok(Box::new(StringBox::new(value.to_string_box().value)));
}
}
"IntegerBox" => {
// IntegerBoxは引数1個整数値で作成
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("IntegerBox constructor expects 1 argument, got {}", arguments.len()),
});
}
let value = self.execute_expression(&arguments[0])?;
if let Some(i) = value.as_any().downcast_ref::<IntegerBox>() {
return Ok(Box::new(IntegerBox::new(i.value)));
} else if let Some(s) = value.as_any().downcast_ref::<StringBox>() {
match s.value.parse::<i64>() {
Ok(n) => return Ok(Box::new(IntegerBox::new(n))),
Err(_) => return Err(RuntimeError::TypeError {
message: format!("Cannot convert '{}' to integer", s.value),
}),
}
} else {
return Err(RuntimeError::TypeError {
message: "IntegerBox constructor requires integer or string argument".to_string(),
});
}
}
"BoolBox" => {
// BoolBoxは引数1個ブール値で作成
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("BoolBox constructor expects 1 argument, got {}", arguments.len()),
});
}
let value = self.execute_expression(&arguments[0])?;
if let Some(b) = value.as_any().downcast_ref::<BoolBox>() {
return Ok(Box::new(BoolBox::new(b.value)));
} else if let Some(s) = value.as_any().downcast_ref::<StringBox>() {
let val = match s.value.as_str() {
"true" => true,
"false" => false,
_ => return Err(RuntimeError::TypeError {
message: format!("Cannot convert '{}' to boolean", s.value),
}),
};
return Ok(Box::new(BoolBox::new(val)));
} else {
return Err(RuntimeError::TypeError {
message: "BoolBox constructor requires boolean or string argument".to_string(),
});
}
}
"ArrayBox" => {
// ArrayBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("ArrayBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
return Ok(Box::new(ArrayBox::new()));
}
"NullBox" => {
// NullBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("NullBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
return Ok(Box::new(NullBox::new()));
}
"MapBox" => {
// MapBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("MapBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let map_box = Box::new(MapBox::new()) as Box<dyn NyashBox>;
return Ok(map_box);
}
"FloatBox" => {
// FloatBoxは引数1個浮動小数点数値で作成
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("FloatBox constructor expects 1 argument, got {}", arguments.len()),
});
}
let value = self.execute_expression(&arguments[0])?;
if let Some(f) = value.as_any().downcast_ref::<FloatBox>() {
return Ok(Box::new(FloatBox::new(f.value)));
} else if let Some(i) = value.as_any().downcast_ref::<IntegerBox>() {
return Ok(Box::new(FloatBox::new(i.value as f64)));
} else if let Some(s) = value.as_any().downcast_ref::<StringBox>() {
match s.value.parse::<f64>() {
Ok(n) => return Ok(Box::new(FloatBox::new(n))),
Err(_) => return Err(RuntimeError::TypeError {
message: format!("Cannot convert '{}' to float", s.value),
}),
}
} else {
return Err(RuntimeError::TypeError {
message: "FloatBox constructor requires float, integer, or string argument".to_string(),
});
}
}
_ => {
// Not a basic type
Err(RuntimeError::TypeError {
message: format!("Not a basic type: {}", class),
})
}
}
}
}

View File

@ -0,0 +1,83 @@
//! Non-basic type constructors for execute_new
//! Handles MathBox, ConsoleBox, GUI boxes, Network boxes, etc.
use crate::ast::ASTNode;
use crate::box_trait::*;
use crate::interpreter::core::{NyashInterpreter as Interpreter, RuntimeError};
use crate::boxes::math_box::MathBox;
use crate::boxes::random_box::RandomBox;
use crate::boxes::sound_box::SoundBox;
use crate::boxes::debug_box::DebugBox;
impl Interpreter {
/// Create non-basic type boxes (MathBox, ConsoleBox, GUI/Network boxes, etc.)
pub(super) fn create_non_basic_box(
&mut self,
class: &str,
arguments: &[ASTNode]
) -> Result<Box<dyn NyashBox>, RuntimeError> {
match class {
"MathBox" => {
// MathBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("MathBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let math_box = Box::new(MathBox::new()) as Box<dyn NyashBox>;
return Ok(math_box);
}
"ConsoleBox" => {
// ConsoleBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("ConsoleBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let console_box = Box::new(crate::box_trait::ConsoleBox::new()) as Box<dyn NyashBox>;
return Ok(console_box);
}
"RandomBox" => {
// RandomBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("RandomBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let random_box = Box::new(RandomBox::new()) as Box<dyn NyashBox>;
return Ok(random_box);
}
"SoundBox" => {
// SoundBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("SoundBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let sound_box = Box::new(SoundBox::new()) as Box<dyn NyashBox>;
return Ok(sound_box);
}
"DebugBox" => {
// DebugBoxは引数なしで作成
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("DebugBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
let debug_box = Box::new(DebugBox::new()) as Box<dyn NyashBox>;
return Ok(debug_box);
}
_ => {
// Not a non-basic type handled here
Err(RuntimeError::TypeError {
message: format!("Not a non-basic type handled in this method: {}", class),
})
}
}
}
}