diff --git a/src/box_arithmetic.rs b/src/box_arithmetic.rs new file mode 100644 index 00000000..0a93f025 --- /dev/null +++ b/src/box_arithmetic.rs @@ -0,0 +1,546 @@ +/*! + * Box Operations - Binary and unary operations between boxes + * + * This module contains the implementation of operation boxes that perform + * arithmetic, logical, and comparison operations between different Box types. + */ + +use crate::box_trait::{NyashBox, BoxCore, StringBox, IntegerBox, BoolBox, VoidBox, BoxBase}; +use std::fmt::{Debug, Display}; +use std::any::Any; + +// ===== Binary Operation Boxes ===== + +/// Binary operations between boxes (addition, concatenation, etc.) +pub struct AddBox { + pub left: Box, + pub right: Box, + base: BoxBase, +} + +impl AddBox { + pub fn new(left: Box, right: Box) -> Self { + Self { + left, + right, + base: BoxBase::new(), + } + } + + /// Execute the addition operation and return the result + pub fn execute(&self) -> Box { + use crate::boxes::math_box::FloatBox; + + // 1. Integer + Integer + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + let result = left_int.value + right_int.value; + return Box::new(IntegerBox::new(result)); + } + + // 2. Float + Float (or mixed with Integer) + if let (Some(left_float), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + let result = left_float.value + right_float.value; + return Box::new(FloatBox::new(result)); + } + + // 3. Integer + Float + if let (Some(left_int), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + let result = left_int.value as f64 + right_float.value; + return Box::new(FloatBox::new(result)); + } + + // 4. Float + Integer + if let (Some(left_float), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + let result = left_float.value + right_int.value as f64; + return Box::new(FloatBox::new(result)); + } + + // 5. String concatenation (fallback for any types) + let left_str = self.left.to_string_box(); + let right_str = self.right.to_string_box(); + let result = format!("{}{}", left_str.value, right_str.value); + Box::new(StringBox::new(result)) + } +} + +impl Debug for AddBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("AddBox") + .field("left", &self.left.to_string_box().value) + .field("right", &self.right.to_string_box().value) + .field("id", &self.base.id) + .finish() + } +} + +impl NyashBox for AddBox { + fn to_string_box(&self) -> StringBox { + let result = self.execute(); + result.to_string_box() + } + + fn equals(&self, other: &dyn NyashBox) -> bool { + if let Some(other_add) = other.as_any().downcast_ref::() { + self.left.equals(other_add.left.as_ref()) && + self.right.equals(other_add.right.as_ref()) + } else { + false + } + } + + fn type_name(&self) -> &'static str { + "AddBox" + } + + fn clone_box(&self) -> Box { + Box::new(AddBox::new( + self.left.clone_box(), + self.right.clone_box() + )) + } +} + +impl BoxCore for AddBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_string_box().value) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl Display for AddBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Subtraction operations between boxes +pub struct SubtractBox { + pub left: Box, + pub right: Box, + base: BoxBase, +} + +impl SubtractBox { + pub fn new(left: Box, right: Box) -> Self { + Self { + left, + right, + base: BoxBase::new(), + } + } + + /// Execute the subtraction operation and return the result + pub fn execute(&self) -> Box { + // For now, only handle integer subtraction + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + let result = left_int.value - right_int.value; + Box::new(IntegerBox::new(result)) + } else { + // Convert to integers and subtract + let left_int = self.left.to_integer_box(); + let right_int = self.right.to_integer_box(); + let result = left_int.value - right_int.value; + Box::new(IntegerBox::new(result)) + } + } +} + +impl Debug for SubtractBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SubtractBox") + .field("left", &self.left.to_string_box().value) + .field("right", &self.right.to_string_box().value) + .field("id", &self.base.id) + .finish() + } +} + +impl NyashBox for SubtractBox { + fn to_string_box(&self) -> StringBox { + let result = self.execute(); + result.to_string_box() + } + + fn equals(&self, other: &dyn NyashBox) -> bool { + if let Some(other_sub) = other.as_any().downcast_ref::() { + self.left.equals(other_sub.left.as_ref()) && + self.right.equals(other_sub.right.as_ref()) + } else { + false + } + } + + fn type_name(&self) -> &'static str { "SubtractBox" } + fn clone_box(&self) -> Box { + Box::new(SubtractBox::new(self.left.clone_box(), self.right.clone_box())) + } +} + +impl BoxCore for SubtractBox { + fn box_id(&self) -> u64 { self.base.id } + fn parent_type_id(&self) -> Option { self.base.parent_type_id } + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_string_box().value) + } + fn as_any(&self) -> &dyn Any { self } + fn as_any_mut(&mut self) -> &mut dyn Any { self } +} + +impl Display for SubtractBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Multiplication operations between boxes +pub struct MultiplyBox { + pub left: Box, + pub right: Box, + base: BoxBase, +} + +impl MultiplyBox { + pub fn new(left: Box, right: Box) -> Self { + Self { + left, + right, + base: BoxBase::new(), + } + } + + /// Execute the multiplication operation and return the result + pub fn execute(&self) -> Box { + // For now, only handle integer multiplication + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + let result = left_int.value * right_int.value; + Box::new(IntegerBox::new(result)) + } else { + // Convert to integers and multiply + let left_int = self.left.to_integer_box(); + let right_int = self.right.to_integer_box(); + let result = left_int.value * right_int.value; + Box::new(IntegerBox::new(result)) + } + } +} + +impl Debug for MultiplyBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("MultiplyBox") + .field("left", &self.left.to_string_box().value) + .field("right", &self.right.to_string_box().value) + .field("id", &self.base.id) + .finish() + } +} + +impl NyashBox for MultiplyBox { + fn to_string_box(&self) -> StringBox { + let result = self.execute(); + result.to_string_box() + } + + fn equals(&self, other: &dyn NyashBox) -> bool { + if let Some(other_mul) = other.as_any().downcast_ref::() { + self.left.equals(other_mul.left.as_ref()) && + self.right.equals(other_mul.right.as_ref()) + } else { + false + } + } + + fn type_name(&self) -> &'static str { "MultiplyBox" } + fn clone_box(&self) -> Box { + Box::new(MultiplyBox::new(self.left.clone_box(), self.right.clone_box())) + } +} + +impl BoxCore for MultiplyBox { + fn box_id(&self) -> u64 { self.base.id } + fn parent_type_id(&self) -> Option { self.base.parent_type_id } + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_string_box().value) + } + fn as_any(&self) -> &dyn Any { self } + fn as_any_mut(&mut self) -> &mut dyn Any { self } +} + +impl Display for MultiplyBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Division operations between boxes +pub struct DivideBox { + pub left: Box, + pub right: Box, + base: BoxBase, +} + +impl DivideBox { + pub fn new(left: Box, right: Box) -> Self { + Self { + left, + right, + base: BoxBase::new(), + } + } + + /// Execute the division operation and return the result + pub fn execute(&self) -> Box { + use crate::boxes::math_box::FloatBox; + + // Handle integer division, but return float result + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + if right_int.value == 0 { + // Return error for division by zero + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + let result = left_int.value as f64 / right_int.value as f64; + Box::new(FloatBox::new(result)) + } else { + // Convert to integers and divide + let left_int = self.left.to_integer_box(); + let right_int = self.right.to_integer_box(); + if right_int.value == 0 { + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + let result = left_int.value as f64 / right_int.value as f64; + Box::new(FloatBox::new(result)) + } + } +} + +impl Debug for DivideBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DivideBox") + .field("left", &self.left.to_string_box().value) + .field("right", &self.right.to_string_box().value) + .field("id", &self.base.id) + .finish() + } +} + +impl NyashBox for DivideBox { + fn to_string_box(&self) -> StringBox { + let result = self.execute(); + result.to_string_box() + } + + fn equals(&self, other: &dyn NyashBox) -> bool { + if let Some(other_div) = other.as_any().downcast_ref::() { + self.left.equals(other_div.left.as_ref()) && + self.right.equals(other_div.right.as_ref()) + } else { + false + } + } + + fn type_name(&self) -> &'static str { "DivideBox" } + fn clone_box(&self) -> Box { + Box::new(DivideBox::new(self.left.clone_box(), self.right.clone_box())) + } +} + +impl BoxCore for DivideBox { + fn box_id(&self) -> u64 { self.base.id } + fn parent_type_id(&self) -> Option { self.base.parent_type_id } + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_string_box().value) + } + fn as_any(&self) -> &dyn Any { self } + fn as_any_mut(&mut self) -> &mut dyn Any { self } +} + +impl Display for DivideBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Comparison operations between boxes +pub struct CompareBox; + +impl CompareBox { + /// Compare two boxes for equality + pub fn equals(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + BoolBox::new(left.equals(right)) + } + + /// Compare two boxes for less than + pub fn less_than(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + // Try integer comparison first + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value < right_int.value); + } + + // Fall back to string comparison + let left_str = left.to_string_box(); + let right_str = right.to_string_box(); + BoolBox::new(left_str.value < right_str.value) + } + + /// Compare two boxes for greater than + pub fn greater_than(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + // Try integer comparison first + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value > right_int.value); + } + + // Fall back to string comparison + let left_str = left.to_string_box(); + let right_str = right.to_string_box(); + BoolBox::new(left_str.value > right_str.value) + } + + /// Compare two boxes for less than or equal + pub fn less_equal(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + // Try integer comparison first + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value <= right_int.value); + } + + // Fall back to string comparison + let left_str = left.to_string_box(); + let right_str = right.to_string_box(); + BoolBox::new(left_str.value <= right_str.value) + } + + /// Compare two boxes for greater than or equal + pub fn greater_equal(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + // Try integer comparison first + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value >= right_int.value); + } + + // Fall back to string comparison + let left_str = left.to_string_box(); + let right_str = right.to_string_box(); + BoolBox::new(left_str.value >= right_str.value) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add_box_integers() { + let left = Box::new(IntegerBox::new(10)) as Box; + let right = Box::new(IntegerBox::new(32)) as Box; + let add_box = AddBox::new(left, right); + let result = add_box.execute(); + + assert_eq!(result.to_string_box().value, "42"); + } + + #[test] + fn test_add_box_strings() { + let left = Box::new(StringBox::new("Hello, ".to_string())) as Box; + let right = Box::new(StringBox::new("World!".to_string())) as Box; + let add_box = AddBox::new(left, right); + let result = add_box.execute(); + + assert_eq!(result.to_string_box().value, "Hello, World!"); + } + + #[test] + fn test_subtract_box() { + let left = Box::new(IntegerBox::new(50)) as Box; + let right = Box::new(IntegerBox::new(8)) as Box; + let sub_box = SubtractBox::new(left, right); + let result = sub_box.execute(); + + assert_eq!(result.to_string_box().value, "42"); + } + + #[test] + fn test_multiply_box() { + let left = Box::new(IntegerBox::new(6)) as Box; + let right = Box::new(IntegerBox::new(7)) as Box; + let mul_box = MultiplyBox::new(left, right); + let result = mul_box.execute(); + + assert_eq!(result.to_string_box().value, "42"); + } + + #[test] + fn test_divide_box() { + let left = Box::new(IntegerBox::new(84)) as Box; + let right = Box::new(IntegerBox::new(2)) as Box; + let div_box = DivideBox::new(left, right); + let result = div_box.execute(); + + // Division returns float + assert_eq!(result.to_string_box().value, "42"); + } + + #[test] + fn test_divide_by_zero() { + let left = Box::new(IntegerBox::new(42)) as Box; + let right = Box::new(IntegerBox::new(0)) as Box; + let div_box = DivideBox::new(left, right); + let result = div_box.execute(); + + assert!(result.to_string_box().value.contains("Division by zero")); + } + + #[test] + fn test_compare_box() { + let left = IntegerBox::new(10); + let right = IntegerBox::new(20); + + assert_eq!(CompareBox::less_than(&left, &right).value, true); + assert_eq!(CompareBox::greater_than(&left, &right).value, false); + assert_eq!(CompareBox::equals(&left, &right).value, false); + } +} \ No newline at end of file diff --git a/src/box_trait.rs b/src/box_trait.rs index cebba74d..844c475e 100644 --- a/src/box_trait.rs +++ b/src/box_trait.rs @@ -921,463 +921,8 @@ impl Display for FutureBox { } } -// ===== Box Operations ===== - -/// Binary operations between boxes (addition, concatenation, etc.) -pub struct AddBox { - pub left: Box, - pub right: Box, - base: BoxBase, -} - -impl AddBox { - pub fn new(left: Box, right: Box) -> Self { - Self { - left, - right, - base: BoxBase::new(), - } - } - - /// Execute the addition operation and return the result - pub fn execute(&self) -> Box { - use crate::boxes::math_box::FloatBox; - - // 1. Integer + Integer - if let (Some(left_int), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(IntegerBox::new(left_int.value + right_int.value)); - } - - // 2. Float + Float - if let (Some(left_float), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_float.value + right_float.value)); - } - - // 3. Integer + Float -> Float - if let (Some(left_int), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_int.value as f64 + right_float.value)); - } - - // 4. Float + Integer -> Float - if let (Some(left_float), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_float.value + right_int.value as f64)); - } - - // 5. Fall back to string concatenation - let left_str = self.left.to_string_box(); - let right_str = self.right.to_string_box(); - Box::new(StringBox::new(format!("{}{}", left_str.value, right_str.value))) - } -} - -impl Debug for AddBox { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AddBox") - .field("left", &self.left.to_string_box().value) - .field("right", &self.right.to_string_box().value) - .field("id", &self.base.id) - .finish() - } -} - -impl NyashBox for AddBox { - fn to_string_box(&self) -> StringBox { - let result = self.execute(); - result.to_string_box() - } - - fn equals(&self, other: &dyn NyashBox) -> BoolBox { - if let Some(other_add) = other.as_any().downcast_ref::() { - let left_eq = self.left.equals(other_add.left.as_ref()); - let right_eq = self.right.equals(other_add.right.as_ref()); - BoolBox::new(left_eq.value && right_eq.value) - } else { - BoolBox::new(false) - } - } - - fn type_name(&self) -> &'static str { - "AddBox" - } - - fn clone_box(&self) -> Box { - Box::new(AddBox::new( - self.left.clone_box(), - self.right.clone_box() - )) - } - -} - -impl BoxCore for AddBox { - fn box_id(&self) -> u64 { - self.base.id - } - - fn parent_type_id(&self) -> Option { - self.base.parent_type_id - } - - fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "({} + {})", self.left.to_string_box().value, self.right.to_string_box().value) - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } -} - -impl Display for AddBox { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.fmt_box(f) - } -} - -// ===== 数値演算Boxの実装 ===== - -/// 減算を行うBox -pub struct SubtractBox { - left: Box, - right: Box, -} - -impl SubtractBox { - pub fn new(left: Box, right: Box) -> Self { - Self { left, right } - } - - pub fn execute(&self) -> Box { - use crate::boxes::math_box::FloatBox; - - // 1. Integer - Integer - if let (Some(left_int), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(IntegerBox::new(left_int.value - right_int.value)); - } - - // 2. Float - Float - if let (Some(left_float), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_float.value - right_float.value)); - } - - // 3. Integer - Float -> Float - if let (Some(left_int), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_int.value as f64 - right_float.value)); - } - - // 4. Float - Integer -> Float - if let (Some(left_float), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_float.value - right_int.value as f64)); - } - - // エラーの場合はvoid返す - Box::new(VoidBox::new()) - } -} - -/// 乗算を行うBox -pub struct MultiplyBox { - left: Box, - right: Box, -} - -impl MultiplyBox { - pub fn new(left: Box, right: Box) -> Self { - Self { left, right } - } - - pub fn execute(&self) -> Box { - use crate::boxes::math_box::FloatBox; - - // 1. Integer * Integer - if let (Some(left_int), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(IntegerBox::new(left_int.value * right_int.value)); - } - - // 2. Float * Float - if let (Some(left_float), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_float.value * right_float.value)); - } - - // 3. Integer * Float -> Float - if let (Some(left_int), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_int.value as f64 * right_float.value)); - } - - // 4. Float * Integer -> Float - if let (Some(left_float), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - return Box::new(FloatBox::new(left_float.value * right_int.value as f64)); - } - - // エラーの場合はvoid返す - Box::new(VoidBox::new()) - } -} - -/// 除算を行うBox -pub struct DivideBox { - left: Box, - right: Box, -} - -impl DivideBox { - pub fn new(left: Box, right: Box) -> Self { - Self { left, right } - } - - pub fn execute(&self) -> Box { - use crate::boxes::math_box::FloatBox; - - // 1. Integer / Integer -> Float (常に浮動小数点で返す) - if let (Some(left_int), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - if right_int.value == 0 { - // ゼロ除算エラー - return Box::new(StringBox::new("Error: Division by zero".to_string())); - } - return Box::new(FloatBox::new(left_int.value as f64 / right_int.value as f64)); - } - - // 2. Float / Float - if let (Some(left_float), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - if right_float.value == 0.0 { - // ゼロ除算エラー - return Box::new(StringBox::new("Error: Division by zero".to_string())); - } - return Box::new(FloatBox::new(left_float.value / right_float.value)); - } - - // 3. Integer / Float -> Float - if let (Some(left_int), Some(right_float)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - if right_float.value == 0.0 { - // ゼロ除算エラー - return Box::new(StringBox::new("Error: Division by zero".to_string())); - } - return Box::new(FloatBox::new(left_int.value as f64 / right_float.value)); - } - - // 4. Float / Integer -> Float - if let (Some(left_float), Some(right_int)) = ( - self.left.as_any().downcast_ref::(), - self.right.as_any().downcast_ref::() - ) { - if right_int.value == 0 { - // ゼロ除算エラー - return Box::new(StringBox::new("Error: Division by zero".to_string())); - } - return Box::new(FloatBox::new(left_float.value / right_int.value as f64)); - } - - // エラーの場合はvoid返す - Box::new(VoidBox::new()) - } -} - -/// 比較演算用のヘルパー -pub struct CompareBox; - -impl CompareBox { - pub fn less(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { - use crate::boxes::FloatBox; - - // Integer < Integer - if let (Some(left_int), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_int.value < right_int.value); - } - - // Float < Float - if let (Some(left_float), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value < right_float.value); - } - - // Integer < Float - if let (Some(left_int), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new((left_int.value as f64) < right_float.value); - } - - // Float < Integer - if let (Some(left_float), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value < (right_int.value as f64)); - } - - BoolBox::new(false) - } - - pub fn greater(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { - use crate::boxes::FloatBox; - - // Integer > Integer - if let (Some(left_int), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_int.value > right_int.value); - } - - // Float > Float - if let (Some(left_float), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value > right_float.value); - } - - // Integer > Float - if let (Some(left_int), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new((left_int.value as f64) > right_float.value); - } - - // Float > Integer - if let (Some(left_float), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value > (right_int.value as f64)); - } - - BoolBox::new(false) - } - - pub fn less_equal(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { - use crate::boxes::FloatBox; - - // Integer <= Integer - if let (Some(left_int), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_int.value <= right_int.value); - } - - // Float <= Float - if let (Some(left_float), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value <= right_float.value); - } - - // Integer <= Float - if let (Some(left_int), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new((left_int.value as f64) <= right_float.value); - } - - // Float <= Integer - if let (Some(left_float), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value <= (right_int.value as f64)); - } - - BoolBox::new(false) - } - - pub fn greater_equal(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { - use crate::boxes::FloatBox; - - // Integer >= Integer - if let (Some(left_int), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_int.value >= right_int.value); - } - - // Float >= Float - if let (Some(left_float), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value >= right_float.value); - } - - // Integer >= Float - if let (Some(left_int), Some(right_float)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new((left_int.value as f64) >= right_float.value); - } - - // Float >= Integer - if let (Some(left_float), Some(right_int)) = ( - left.as_any().downcast_ref::(), - right.as_any().downcast_ref::() - ) { - return BoolBox::new(left_float.value >= (right_int.value as f64)); - } - - BoolBox::new(false) - } -} - -// ===== Tests ===== +// Re-export operation boxes from the dedicated operations module +pub use crate::box_arithmetic::{AddBox, SubtractBox, MultiplyBox, DivideBox, CompareBox}; #[cfg(test)] mod tests { diff --git a/src/box_trait.rs.backup b/src/box_trait.rs.backup new file mode 100644 index 00000000..a4bd6f06 --- /dev/null +++ b/src/box_trait.rs.backup @@ -0,0 +1,1455 @@ +/*! + * Nyash Box Trait System - Everything is Box in Rust + * + * This module implements the core "Everything is Box" philosophy using Rust's + * ownership system and trait system. Every value in Nyash is a Box that + * implements the NyashBox trait. + */ + +use std::fmt::{Debug, Display}; +use std::any::Any; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::fs; +use std::path::Path; + +// 🔥 新しい型エイリアス - 将来的にBoxを全て置き換える +pub type SharedNyashBox = Arc; + +/// 🔥 BoxBase + BoxCore革命 - 統一ID生成システム +/// CharmFlow教訓を活かした互換性保証の基盤 +pub fn next_box_id() -> u64 { + static COUNTER: AtomicU64 = AtomicU64::new(1); + COUNTER.fetch_add(1, Ordering::Relaxed) +} + +/// 🏗️ BoxBase - 全てのBox型の共通基盤構造体 +/// Phase 2: 統一的な基盤データを提供 +/// 🔥 Phase 1: ビルトインBox継承システム - 最小限拡張 +#[derive(Debug, Clone, PartialEq)] +pub struct BoxBase { + pub id: u64, + pub parent_type_id: Option, // ビルトインBox継承用 +} + +impl BoxBase { + /// 新しいBoxBase作成 - 安全なID生成 + pub fn new() -> Self { + Self { + id: next_box_id(), + parent_type_id: None, // ビルトインBox: 継承なし + } + } + + /// ビルトインBox継承用コンストラクタ + pub fn with_parent_type(parent_type_id: std::any::TypeId) -> Self { + Self { + id: next_box_id(), + parent_type_id: Some(parent_type_id), + } + } +} + +/// 🎯 BoxCore - Box型共通メソッドの統一インターフェース +/// Phase 2: 重複コードを削減する中核トレイト +/// 🔥 Phase 2: ビルトインBox継承システム対応 +pub trait BoxCore: Send + Sync { + /// ボックスの一意ID取得 + fn box_id(&self) -> u64; + + /// 継承元の型ID取得(ビルトインBox継承用) + fn parent_type_id(&self) -> Option; + + /// Display実装のための統一フォーマット + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result; + + /// Any変換(ダウンキャスト用) + fn as_any(&self) -> &dyn Any; + + /// Anyミュータブル変換(ダウンキャスト用) + fn as_any_mut(&mut self) -> &mut dyn Any; +} + +/// The fundamental trait that all Nyash values must implement. +/// This embodies the "Everything is Box" philosophy with Rust's type safety. +pub trait NyashBox: BoxCore + Debug { + /// Convert this box to a string representation (equivalent to Python's toString()) + fn to_string_box(&self) -> StringBox; + + /// Check equality with another box (equivalent to Python's equals()) + fn equals(&self, other: &dyn NyashBox) -> BoolBox; + + /// Get the type name of this box for debugging + fn type_name(&self) -> &'static str { + std::any::type_name::() + } + + /// Clone this box (equivalent to Python's copy()) + fn clone_box(&self) -> Box; + + /// Arc参照を返す新しいcloneメソッド(参照共有) + fn clone_arc(&self) -> SharedNyashBox { + Arc::from(self.clone_box()) + } + + // 🌟 TypeBox革命: Get type information as a Box + // Everything is Box極限実現 - 型情報もBoxとして取得! + // TODO: 次のステップで完全実装 + // fn get_type_box(&self) -> std::sync::Arc; +} + +// ===== Basic Box Types ===== + +/// String values in Nyash - immutable and owned +#[derive(Debug, Clone, PartialEq)] +pub struct StringBox { + pub value: String, + base: BoxBase, +} + +impl StringBox { + pub fn new(value: impl Into) -> Self { + Self { + value: value.into(), + base: BoxBase::new(), + } + } + + pub fn empty() -> Self { + Self::new("") + } + + // ===== String Methods for Nyash ===== + + /// Split string by delimiter and return ArrayBox + pub fn split(&self, delimiter: &str) -> Box { + let parts: Vec = self.value.split(delimiter).map(|s| s.to_string()).collect(); + let array_elements: Vec> = parts.into_iter() + .map(|s| Box::new(StringBox::new(s)) as Box) + .collect(); + Box::new(ArrayBox::new_with_elements(array_elements)) + } + + /// Find substring and return position (or -1 if not found) + pub fn find(&self, search: &str) -> Box { + match self.value.find(search) { + Some(pos) => Box::new(IntegerBox::new(pos as i64)), + None => Box::new(IntegerBox::new(-1)), + } + } + + /// Replace all occurrences of old with new + pub fn replace(&self, old: &str, new: &str) -> Box { + Box::new(StringBox::new(self.value.replace(old, new))) + } + + /// Trim whitespace from both ends + pub fn trim(&self) -> Box { + Box::new(StringBox::new(self.value.trim())) + } + + /// Convert to uppercase + pub fn to_upper(&self) -> Box { + Box::new(StringBox::new(self.value.to_uppercase())) + } + + /// Convert to lowercase + pub fn to_lower(&self) -> Box { + Box::new(StringBox::new(self.value.to_lowercase())) + } + + /// Check if string contains substring + pub fn contains(&self, search: &str) -> Box { + Box::new(BoolBox::new(self.value.contains(search))) + } + + /// Check if string starts with prefix + pub fn starts_with(&self, prefix: &str) -> Box { + Box::new(BoolBox::new(self.value.starts_with(prefix))) + } + + /// Check if string ends with suffix + pub fn ends_with(&self, suffix: &str) -> Box { + Box::new(BoolBox::new(self.value.ends_with(suffix))) + } + + /// Join array elements using this string as delimiter + pub fn join(&self, array_box: Box) -> Box { + if let Some(array) = array_box.as_any().downcast_ref::() { + let strings: Vec = array.items.lock().unwrap() + .iter() + .map(|element| element.to_string_box().value) + .collect(); + Box::new(StringBox::new(strings.join(&self.value))) + } else { + // If not an ArrayBox, treat as single element + Box::new(StringBox::new(array_box.to_string_box().value)) + } + } + + /// Get string length + pub fn length(&self) -> Box { + Box::new(IntegerBox::new(self.value.len() as i64)) + } + + /// Get character at index + pub fn get(&self, index: usize) -> Option> { + if let Some(ch) = self.value.chars().nth(index) { + Some(Box::new(StringBox::new(ch.to_string()))) + } else { + None + } + } +} + +impl BoxCore for StringBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.value) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for StringBox { + fn to_string_box(&self) -> StringBox { + self.clone() + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_string) = other.as_any().downcast_ref::() { + BoolBox::new(self.value == other_string.value) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "StringBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl Display for StringBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Integer values in Nyash - 64-bit signed integers +#[derive(Debug, Clone, PartialEq)] +pub struct IntegerBox { + pub value: i64, + base: BoxBase, +} + +impl IntegerBox { + pub fn new(value: i64) -> Self { + Self { + value, + base: BoxBase::new() + } + } + + pub fn zero() -> Self { + Self::new(0) + } +} + +impl BoxCore for IntegerBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.value) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for IntegerBox { + fn to_string_box(&self) -> StringBox { + StringBox::new(self.value.to_string()) + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_int) = other.as_any().downcast_ref::() { + BoolBox::new(self.value == other_int.value) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "IntegerBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl Display for IntegerBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Boolean values in Nyash - true/false +#[derive(Debug, Clone, PartialEq)] +pub struct BoolBox { + pub value: bool, + base: BoxBase, +} + +impl BoolBox { + pub fn new(value: bool) -> Self { + Self { + value, + base: BoxBase::new() + } + } + + pub fn true_box() -> Self { + Self::new(true) + } + + pub fn false_box() -> Self { + Self::new(false) + } +} + +impl BoxCore for BoolBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", if self.value { "true" } else { "false" }) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for BoolBox { + fn to_string_box(&self) -> StringBox { + StringBox::new(if self.value { "true" } else { "false" }) + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_bool) = other.as_any().downcast_ref::() { + BoolBox::new(self.value == other_bool.value) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "BoolBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl Display for BoolBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Void/null values in Nyash - represents empty or null results +#[derive(Debug, Clone, PartialEq)] +pub struct VoidBox { + base: BoxBase, +} + +impl VoidBox { + pub fn new() -> Self { + Self { + base: BoxBase::new() + } + } +} + +impl Default for VoidBox { + fn default() -> Self { + Self::new() + } +} + +impl BoxCore for VoidBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "void") + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for VoidBox { + fn to_string_box(&self) -> StringBox { + StringBox::new("void") + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + BoolBox::new(other.as_any().is::()) + } + + fn type_name(&self) -> &'static str { + "VoidBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl Display for VoidBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +// ArrayBox is now defined in boxes::array module +pub use crate::boxes::array::ArrayBox; + +/// File values in Nyash - file system operations +#[derive(Debug, Clone)] +pub struct FileBox { + pub path: String, + base: BoxBase, +} + +impl FileBox { + pub fn new(path: impl Into) -> Self { + Self { + path: path.into(), + base: BoxBase::new(), + } + } + + // ===== File Methods for Nyash ===== + + /// Read file contents as string + pub fn read(&self) -> Box { + match fs::read_to_string(&self.path) { + Ok(content) => Box::new(StringBox::new(content)), + Err(_) => Box::new(VoidBox::new()), // Return void on error for now + } + } + + /// Write content to file + pub fn write(&self, content: Box) -> Box { + let content_str = content.to_string_box().value; + match fs::write(&self.path, content_str) { + Ok(_) => Box::new(BoolBox::new(true)), + Err(_) => Box::new(BoolBox::new(false)), + } + } + + /// Check if file exists + pub fn exists(&self) -> Box { + Box::new(BoolBox::new(Path::new(&self.path).exists())) + } + + /// Delete file + pub fn delete(&self) -> Box { + match fs::remove_file(&self.path) { + Ok(_) => Box::new(BoolBox::new(true)), + Err(_) => Box::new(BoolBox::new(false)), + } + } + + /// Copy file to destination + pub fn copy(&self, dest_path: &str) -> Box { + match fs::copy(&self.path, dest_path) { + Ok(_) => Box::new(BoolBox::new(true)), + Err(_) => Box::new(BoolBox::new(false)), + } + } +} + +impl BoxCore for FileBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "", self.path) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for FileBox { + fn to_string_box(&self) -> StringBox { + StringBox::new(format!("", self.path)) + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_file) = other.as_any().downcast_ref::() { + BoolBox::new(self.path == other_file.path) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "FileBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl Display for FileBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Error values in Nyash - represents error information +#[derive(Debug, Clone)] +pub struct ErrorBox { + pub error_type: String, + pub message: String, + base: BoxBase, +} + +impl ErrorBox { + pub fn new(error_type: impl Into, message: impl Into) -> Self { + Self { + error_type: error_type.into(), + message: message.into(), + base: BoxBase::new(), + } + } +} + +impl BoxCore for ErrorBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}: {}", self.error_type, self.message) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for ErrorBox { + fn to_string_box(&self) -> StringBox { + StringBox::new(format!("{}: {}", self.error_type, self.message)) + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_error) = other.as_any().downcast_ref::() { + BoolBox::new(self.error_type == other_error.error_type && self.message == other_error.message) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "ErrorBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl Display for ErrorBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Result values in Nyash - represents success or error results +#[derive(Debug)] +pub struct ResultBox { + pub is_success: bool, + pub value: Option>, + pub error: Option, + base: BoxBase, +} + +impl ResultBox { + pub fn new_success(value: Box) -> Self { + Self { + is_success: true, + value: Some(value), + error: None, + base: BoxBase::new(), + } + } + + pub fn new_error(error: ErrorBox) -> Self { + Self { + is_success: false, + value: None, + error: Some(error), + base: BoxBase::new(), + } + } + + // ===== Result Methods for Nyash ===== + + /// Check if result is successful + pub fn is_ok(&self) -> Box { + Box::new(BoolBox::new(self.is_success)) + } + + /// Get success value (returns void if error) + pub fn get_value(&self) -> Box { + match &self.value { + Some(val) => val.clone_box(), + None => Box::new(VoidBox::new()), + } + } + + /// Get error (returns void if success) + pub fn get_error(&self) -> Box { + match &self.error { + Some(err) => Box::new(err.clone()), + None => Box::new(VoidBox::new()), + } + } +} + +impl BoxCore for ResultBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_string_box().value) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl NyashBox for ResultBox { + fn to_string_box(&self) -> StringBox { + if self.is_success { + if let Some(value) = &self.value { + StringBox::new(format!("Result(OK: {})", value.to_string_box().value)) + } else { + StringBox::new("Result(OK: void)".to_string()) + } + } else { + if let Some(error) = &self.error { + StringBox::new(format!("Result(Error: {})", error.to_string_box().value)) + } else { + StringBox::new("Result(Error: unknown)".to_string()) + } + } + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_result) = other.as_any().downcast_ref::() { + if self.is_success != other_result.is_success { + return BoolBox::new(false); + } + + if self.is_success { + // Compare success values + match (&self.value, &other_result.value) { + (Some(a), Some(b)) => a.equals(b.as_ref()), + (None, None) => BoolBox::new(true), + _ => BoolBox::new(false), + } + } else { + // Compare errors + match (&self.error, &other_result.error) { + (Some(a), Some(b)) => a.equals(b), + (None, None) => BoolBox::new(true), + _ => BoolBox::new(false), + } + } + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "ResultBox" + } + + fn clone_box(&self) -> Box { + if self.is_success { + if let Some(value) = &self.value { + Box::new(ResultBox::new_success(value.clone_box())) + } else { + Box::new(ResultBox::new_success(Box::new(VoidBox::new()))) + } + } else { + if let Some(error) = &self.error { + Box::new(ResultBox::new_error(error.clone())) + } else { + Box::new(ResultBox::new_error(ErrorBox::new("Unknown", "Unknown error"))) + } + } + } + +} + +impl Display for ResultBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +/// Future values in Nyash - represents async operations +#[derive(Debug)] +pub struct FutureBox { + pub result: Arc>>>, + pub is_ready: Arc>, + base: BoxBase, +} + +impl Clone for FutureBox { + fn clone(&self) -> Self { + Self { + result: Arc::clone(&self.result), + is_ready: Arc::clone(&self.is_ready), + base: BoxBase::new(), // 新しいIDを生成 + } + } +} + +impl FutureBox { + pub fn new() -> Self { + Self { + result: Arc::new(Mutex::new(None)), + is_ready: Arc::new(Mutex::new(false)), + base: BoxBase::new(), + } + } + + /// Set the result of the future + pub fn set_result(&self, value: Box) { + let mut result = self.result.lock().unwrap(); + *result = Some(value); + let mut ready = self.is_ready.lock().unwrap(); + *ready = true; + } + + /// Get the result (blocks until ready) + pub fn get(&self) -> Box { + // 簡易実装: ビジーウェイト(後でcondvarに改善) + loop { + let ready = self.is_ready.lock().unwrap(); + if *ready { + break; + } + drop(ready); + std::thread::yield_now(); + } + + let result = self.result.lock().unwrap(); + result.as_ref().unwrap().clone_box() + } + + /// Check if the future is ready + pub fn ready(&self) -> Box { + Box::new(BoolBox::new(*self.is_ready.lock().unwrap())) + } + + /// Wait and get the result (for await implementation) + pub fn wait_and_get(&self) -> Result, String> { + // 結果が準備できるまで待機 + while !*self.is_ready.lock().unwrap() { + std::thread::yield_now(); + } + + let result = self.result.lock().unwrap(); + result.as_ref() + .map(|v| v.clone_box()) + .ok_or_else(|| "Future has no result".to_string()) + } +} + +impl NyashBox for FutureBox { + fn to_string_box(&self) -> StringBox { + let ready = *self.is_ready.lock().unwrap(); + if ready { + let result = self.result.lock().unwrap(); + if let Some(value) = result.as_ref() { + StringBox::new(format!("Future(ready: {})", value.to_string_box().value)) + } else { + StringBox::new("Future(ready: void)".to_string()) + } + } else { + StringBox::new("Future(pending)".to_string()) + } + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_future) = other.as_any().downcast_ref::() { + BoolBox::new(self.base.id == other_future.base.id) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "FutureBox" + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + +} + +impl BoxCore for FutureBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_string_box().value) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl Display for FutureBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +// Re-export operation boxes from the dedicated operations module +pub use crate::box_operations::{AddBox, SubtractBox, MultiplyBox, DivideBox, CompareBox}; + +#[cfg(test)] + pub left: Box, + pub right: Box, + base: BoxBase, +} + +impl AddBox { + pub fn new(left: Box, right: Box) -> Self { + Self { + left, + right, + base: BoxBase::new(), + } + } + + /// Execute the addition operation and return the result + pub fn execute(&self) -> Box { + use crate::boxes::math_box::FloatBox; + + // 1. Integer + Integer + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(IntegerBox::new(left_int.value + right_int.value)); + } + + // 2. Float + Float + if let (Some(left_float), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_float.value + right_float.value)); + } + + // 3. Integer + Float -> Float + if let (Some(left_int), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_int.value as f64 + right_float.value)); + } + + // 4. Float + Integer -> Float + if let (Some(left_float), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_float.value + right_int.value as f64)); + } + + // 5. Fall back to string concatenation + let left_str = self.left.to_string_box(); + let right_str = self.right.to_string_box(); + Box::new(StringBox::new(format!("{}{}", left_str.value, right_str.value))) + } +} + +impl Debug for AddBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("AddBox") + .field("left", &self.left.to_string_box().value) + .field("right", &self.right.to_string_box().value) + .field("id", &self.base.id) + .finish() + } +} + +impl NyashBox for AddBox { + fn to_string_box(&self) -> StringBox { + let result = self.execute(); + result.to_string_box() + } + + fn equals(&self, other: &dyn NyashBox) -> BoolBox { + if let Some(other_add) = other.as_any().downcast_ref::() { + let left_eq = self.left.equals(other_add.left.as_ref()); + let right_eq = self.right.equals(other_add.right.as_ref()); + BoolBox::new(left_eq.value && right_eq.value) + } else { + BoolBox::new(false) + } + } + + fn type_name(&self) -> &'static str { + "AddBox" + } + + fn clone_box(&self) -> Box { + Box::new(AddBox::new( + self.left.clone_box(), + self.right.clone_box() + )) + } + +} + +impl BoxCore for AddBox { + fn box_id(&self) -> u64 { + self.base.id + } + + fn parent_type_id(&self) -> Option { + self.base.parent_type_id + } + + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "({} + {})", self.left.to_string_box().value, self.right.to_string_box().value) + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl Display for AddBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.fmt_box(f) + } +} + +// ===== 数値演算Boxの実装 ===== + +/// 減算を行うBox +pub struct SubtractBox { + left: Box, + right: Box, +} + +impl SubtractBox { + pub fn new(left: Box, right: Box) -> Self { + Self { left, right } + } + + pub fn execute(&self) -> Box { + use crate::boxes::math_box::FloatBox; + + // 1. Integer - Integer + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(IntegerBox::new(left_int.value - right_int.value)); + } + + // 2. Float - Float + if let (Some(left_float), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_float.value - right_float.value)); + } + + // 3. Integer - Float -> Float + if let (Some(left_int), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_int.value as f64 - right_float.value)); + } + + // 4. Float - Integer -> Float + if let (Some(left_float), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_float.value - right_int.value as f64)); + } + + // エラーの場合はvoid返す + Box::new(VoidBox::new()) + } +} + +/// 乗算を行うBox +pub struct MultiplyBox { + left: Box, + right: Box, +} + +impl MultiplyBox { + pub fn new(left: Box, right: Box) -> Self { + Self { left, right } + } + + pub fn execute(&self) -> Box { + use crate::boxes::math_box::FloatBox; + + // 1. Integer * Integer + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(IntegerBox::new(left_int.value * right_int.value)); + } + + // 2. Float * Float + if let (Some(left_float), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_float.value * right_float.value)); + } + + // 3. Integer * Float -> Float + if let (Some(left_int), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_int.value as f64 * right_float.value)); + } + + // 4. Float * Integer -> Float + if let (Some(left_float), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + return Box::new(FloatBox::new(left_float.value * right_int.value as f64)); + } + + // エラーの場合はvoid返す + Box::new(VoidBox::new()) + } +} + +/// 除算を行うBox +pub struct DivideBox { + left: Box, + right: Box, +} + +impl DivideBox { + pub fn new(left: Box, right: Box) -> Self { + Self { left, right } + } + + pub fn execute(&self) -> Box { + use crate::boxes::math_box::FloatBox; + + // 1. Integer / Integer -> Float (常に浮動小数点で返す) + if let (Some(left_int), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + if right_int.value == 0 { + // ゼロ除算エラー + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + return Box::new(FloatBox::new(left_int.value as f64 / right_int.value as f64)); + } + + // 2. Float / Float + if let (Some(left_float), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + if right_float.value == 0.0 { + // ゼロ除算エラー + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + return Box::new(FloatBox::new(left_float.value / right_float.value)); + } + + // 3. Integer / Float -> Float + if let (Some(left_int), Some(right_float)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + if right_float.value == 0.0 { + // ゼロ除算エラー + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + return Box::new(FloatBox::new(left_int.value as f64 / right_float.value)); + } + + // 4. Float / Integer -> Float + if let (Some(left_float), Some(right_int)) = ( + self.left.as_any().downcast_ref::(), + self.right.as_any().downcast_ref::() + ) { + if right_int.value == 0 { + // ゼロ除算エラー + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + return Box::new(FloatBox::new(left_float.value / right_int.value as f64)); + } + + // エラーの場合はvoid返す + Box::new(VoidBox::new()) + } +} + +/// 比較演算用のヘルパー +pub struct CompareBox; + +impl CompareBox { + pub fn less(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + use crate::boxes::FloatBox; + + // Integer < Integer + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value < right_int.value); + } + + // Float < Float + if let (Some(left_float), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value < right_float.value); + } + + // Integer < Float + if let (Some(left_int), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new((left_int.value as f64) < right_float.value); + } + + // Float < Integer + if let (Some(left_float), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value < (right_int.value as f64)); + } + + BoolBox::new(false) + } + + pub fn greater(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + use crate::boxes::FloatBox; + + // Integer > Integer + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value > right_int.value); + } + + // Float > Float + if let (Some(left_float), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value > right_float.value); + } + + // Integer > Float + if let (Some(left_int), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new((left_int.value as f64) > right_float.value); + } + + // Float > Integer + if let (Some(left_float), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value > (right_int.value as f64)); + } + + BoolBox::new(false) + } + + pub fn less_equal(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + use crate::boxes::FloatBox; + + // Integer <= Integer + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value <= right_int.value); + } + + // Float <= Float + if let (Some(left_float), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value <= right_float.value); + } + + // Integer <= Float + if let (Some(left_int), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new((left_int.value as f64) <= right_float.value); + } + + // Float <= Integer + if let (Some(left_float), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value <= (right_int.value as f64)); + } + + BoolBox::new(false) + } + + pub fn greater_equal(left: &dyn NyashBox, right: &dyn NyashBox) -> BoolBox { + use crate::boxes::FloatBox; + + // Integer >= Integer + if let (Some(left_int), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_int.value >= right_int.value); + } + + // Float >= Float + if let (Some(left_float), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value >= right_float.value); + } + + // Integer >= Float + if let (Some(left_int), Some(right_float)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new((left_int.value as f64) >= right_float.value); + } + + // Float >= Integer + if let (Some(left_float), Some(right_int)) = ( + left.as_any().downcast_ref::(), + right.as_any().downcast_ref::() + ) { + return BoolBox::new(left_float.value >= (right_int.value as f64)); + } + + BoolBox::new(false) + } +} + +// ===== Tests ===== + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_string_box_creation() { + let s = StringBox::new("Hello, Rust!"); + assert_eq!(s.value, "Hello, Rust!"); + assert_eq!(s.type_name(), "StringBox"); + assert_eq!(s.to_string_box().value, "Hello, Rust!"); + } + + #[test] + fn test_integer_box_creation() { + let i = IntegerBox::new(42); + assert_eq!(i.value, 42); + assert_eq!(i.type_name(), "IntegerBox"); + assert_eq!(i.to_string_box().value, "42"); + } + + #[test] + fn test_bool_box_creation() { + let b = BoolBox::new(true); + assert_eq!(b.value, true); + assert_eq!(b.type_name(), "BoolBox"); + assert_eq!(b.to_string_box().value, "true"); + } + + #[test] + fn test_box_equality() { + let s1 = StringBox::new("test"); + let s2 = StringBox::new("test"); + let s3 = StringBox::new("different"); + + assert!(s1.equals(&s2).value); + assert!(!s1.equals(&s3).value); + } + + #[test] + fn test_add_box_integers() { + let left = Box::new(IntegerBox::new(5)) as Box; + let right = Box::new(IntegerBox::new(3)) as Box; + let add = AddBox::new(left, right); + + let result = add.execute(); + let result_int = result.as_any().downcast_ref::().unwrap(); + assert_eq!(result_int.value, 8); + } + + #[test] + fn test_add_box_strings() { + let left = Box::new(StringBox::new("Hello, ")) as Box; + let right = Box::new(StringBox::new("Rust!")) as Box; + let add = AddBox::new(left, right); + + let result = add.execute(); + let result_str = result.as_any().downcast_ref::().unwrap(); + assert_eq!(result_str.value, "Hello, Rust!"); + } + + #[test] + fn test_box_ids_unique() { + let s1 = StringBox::new("test"); + let s2 = StringBox::new("test"); + + // Same content but different IDs + assert_ne!(s1.box_id(), s2.box_id()); + } + + #[test] + fn test_void_box() { + let v = VoidBox::new(); + assert_eq!(v.type_name(), "VoidBox"); + assert_eq!(v.to_string_box().value, "void"); + } +} \ No newline at end of file diff --git a/src/boxes/traits.rs b/src/boxes/traits.rs new file mode 100644 index 00000000..8872c5e6 --- /dev/null +++ b/src/boxes/traits.rs @@ -0,0 +1,89 @@ +/*! + * Core Box Traits - Essential trait definitions for "Everything is Box" + * + * This module contains the core trait definitions and base structures + * that all Box types must implement. + */ + +use std::fmt::{Debug, Display}; +use std::any::Any; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::Arc; + +/// 🔥 新しい型エイリアス - 将来的にBoxを全て置き換える +pub type SharedNyashBox = Arc; + +/// 🔥 BoxBase + BoxCore革命 - 統一ID生成システム +/// CharmFlow教訓を活かした互換性保証の基盤 +pub fn next_box_id() -> u64 { + static COUNTER: AtomicU64 = AtomicU64::new(1); + COUNTER.fetch_add(1, Ordering::Relaxed) +} + +/// 🏗️ BoxBase - 全てのBox型の共通基盤構造体 +/// Phase 2: 統一的な基盤データを提供 +/// 🔥 Phase 1: ビルトインBox継承システム - 最小限拡張 +#[derive(Debug, Clone, PartialEq)] +pub struct BoxBase { + pub id: u64, + pub parent_type_id: Option, // ビルトインBox継承用 +} + +impl BoxBase { + /// 新しいBoxBase作成 - 安全なID生成 + pub fn new() -> Self { + Self { + id: next_box_id(), + parent_type_id: None, // ビルトインBox: 継承なし + } + } + + /// ビルトインBox継承用コンストラクタ + pub fn with_parent_type(parent_type_id: std::any::TypeId) -> Self { + Self { + id: next_box_id(), + parent_type_id: Some(parent_type_id), + } + } +} + +/// 🚀 BoxCore - 全てのBoxが持つ基盤的な操作 +/// これはフォーマット、型特定、Anyキャストなど基本的な機能 +pub trait BoxCore: Send + Sync { + /// Boxの一意ID取得 + fn box_id(&self) -> u64; + + /// 継承元の型ID取得 (ビルトインBox継承) + fn parent_type_id(&self) -> Option; + + /// フォーマッター用実装 - 内部でto_string_box().valueを使う + fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result; + + /// Any型へのキャスト (ダウンキャスト用) + fn as_any(&self) -> &dyn Any; + + /// Mutable Any型へのキャスト + fn as_any_mut(&mut self) -> &mut dyn Any; +} + +/// 🌟 NyashBox - Nyashの全ての値が実装すべき主要trait +/// BoxCoreを継承し、さらにNyash固有の操作を追加 +pub trait NyashBox: BoxCore + Debug { + /// StringBoxへの変換 (全ての値は文字列表現を持つ) + fn to_string_box(&self) -> super::string_box::StringBox; + + /// IntegerBoxへの変換 (可能な場合) + fn to_integer_box(&self) -> super::integer_box::IntegerBox; + + /// BoolBoxへの変換 (真偽値としての評価) + fn to_bool_box(&self) -> super::bool_box::BoolBox; + + /// 等価性比較 + fn equals(&self, other: &dyn NyashBox) -> bool; + + /// 型名取得 + fn type_name(&self) -> &'static str; + + /// クローン操作 (Box内での値コピー) + fn clone_box(&self) -> Box; +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index ecd3f45a..d38293f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ pub mod method_box; pub mod type_box; // 🌟 TypeBox revolutionary system pub mod operator_traits; // 🚀 Rust-style trait-based operator overloading pub mod box_operators; // 🚀 Operator implementations for basic Box types +pub mod box_arithmetic; // 🚀 Arithmetic operations moved from box_trait.rs // 🔥 NyashValue Revolutionary System (NEW!) pub mod value; @@ -48,7 +49,8 @@ pub mod wasm_test; pub mod tests; // Re-export main types for easy access -pub use box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, AddBox}; +pub use box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox}; +pub use box_arithmetic::{AddBox, SubtractBox, MultiplyBox, DivideBox, CompareBox}; pub use environment::{Environment, PythonCompatEnvironment}; pub use tokenizer::{NyashTokenizer, TokenType, Token}; pub use type_box::{TypeBox, TypeRegistry, MethodSignature}; // 🌟 TypeBox exports diff --git a/src/main.rs b/src/main.rs index b8297912..5dcbe62e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ pub mod finalization; pub mod exception_box; pub mod method_box; pub mod operator_traits; -pub mod box_operators; +pub mod box_arithmetic; // 🚀 Moved from box_trait.rs for better organization pub mod value; // 🔥 NyashValue Revolutionary System // 🚀 MIR Infrastructure