diff --git a/src/box_arithmetic.rs b/src/box_arithmetic.rs new file mode 100644 index 00000000..1b46d333 --- /dev/null +++ b/src/box_arithmetic.rs @@ -0,0 +1,579 @@ +/*! + * 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) -> BoolBox { + if let Some(other_add) = other.as_any().downcast_ref::() { + BoolBox::new( + self.left.equals(other_add.left.as_ref()).value && + self.right.equals(other_add.right.as_ref()).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.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 + // For simplicity, default to 0 for non-integer types + let left_val = if let Some(int_box) = self.left.as_any().downcast_ref::() { + int_box.value + } else { + 0 + }; + let right_val = if let Some(int_box) = self.right.as_any().downcast_ref::() { + int_box.value + } else { + 0 + }; + let result = left_val - right_val; + 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) -> BoolBox { + if let Some(other_sub) = other.as_any().downcast_ref::() { + BoolBox::new( + self.left.equals(other_sub.left.as_ref()).value && + self.right.equals(other_sub.right.as_ref()).value + ) + } else { + BoolBox::new(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_val = if let Some(int_box) = self.left.as_any().downcast_ref::() { + int_box.value + } else { + 0 + }; + let right_val = if let Some(int_box) = self.right.as_any().downcast_ref::() { + int_box.value + } else { + 0 + }; + let result = left_val * right_val; + 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) -> BoolBox { + if let Some(other_mul) = other.as_any().downcast_ref::() { + BoolBox::new( + self.left.equals(other_mul.left.as_ref()).value && + self.right.equals(other_mul.right.as_ref()).value + ) + } else { + BoolBox::new(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_val = if let Some(int_box) = self.left.as_any().downcast_ref::() { + int_box.value + } else { + 0 + }; + let right_val = if let Some(int_box) = self.right.as_any().downcast_ref::() { + int_box.value + } else { + 1 // Avoid division by zero + }; + if right_val == 0 { + return Box::new(StringBox::new("Error: Division by zero".to_string())); + } + let result = left_val as f64 / right_val 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) -> BoolBox { + if let Some(other_div) = other.as_any().downcast_ref::() { + BoolBox::new( + self.left.equals(other_div.left.as_ref()).value && + self.right.equals(other_div.right.as_ref()).value + ) + } else { + BoolBox::new(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 { + left.equals(right) + } + + /// Compare two boxes for less than + pub fn less(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(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(&left, &right).value, true); + assert_eq!(CompareBox::greater(&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/cli.rs b/src/cli.rs new file mode 100644 index 00000000..7fd82b82 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,176 @@ +/*! + * CLI Argument Parsing Module - Nyash Command Line Interface + * + * This module handles all command-line argument parsing using clap, + * separating CLI concerns from the main execution logic. + */ + +use clap::{Arg, Command, ArgMatches}; + +/// Command-line configuration structure +#[derive(Debug, Clone)] +pub struct CliConfig { + pub file: Option, + pub debug_fuel: Option, + pub dump_mir: bool, + pub verify_mir: bool, + pub mir_verbose: bool, + pub backend: String, + pub compile_wasm: bool, + pub compile_native: bool, + pub output_file: Option, + pub benchmark: bool, + pub iterations: u32, +} + +impl CliConfig { + /// Parse command-line arguments and return configuration + pub fn parse() -> Self { + let matches = Self::build_command().get_matches(); + Self::from_matches(&matches) + } + + /// Build the clap Command structure + fn build_command() -> Command { + Command::new("nyash") + .version("1.0") + .author("Claude Code ") + .about("🦀 Nyash Programming Language - Everything is Box in Rust! 🦀") + .arg( + Arg::new("file") + .help("Nyash file to execute") + .value_name("FILE") + .index(1) + ) + .arg( + Arg::new("debug-fuel") + .long("debug-fuel") + .value_name("ITERATIONS") + .help("Set parser debug fuel limit (default: 100000, 'unlimited' for no limit)") + .default_value("100000") + ) + .arg( + Arg::new("dump-mir") + .long("dump-mir") + .help("Dump MIR (Mid-level Intermediate Representation) instead of executing") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("verify") + .long("verify") + .help("Verify MIR integrity and exit") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("mir-verbose") + .long("mir-verbose") + .help("Show verbose MIR output with statistics") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("backend") + .long("backend") + .value_name("BACKEND") + .help("Choose execution backend: 'interpreter' (default) or 'vm'") + .default_value("interpreter") + ) + .arg( + Arg::new("compile-wasm") + .long("compile-wasm") + .help("Compile to WebAssembly (WAT format) instead of executing") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("compile-native") + .long("compile-native") + .help("Compile to native AOT executable using wasmtime precompilation") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("aot") + .long("aot") + .help("Short form of --compile-native") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("output") + .long("output") + .short('o') + .value_name("FILE") + .help("Output file (for WASM compilation or AOT executable)") + ) + .arg( + Arg::new("benchmark") + .long("benchmark") + .help("Run performance benchmarks across all backends") + .action(clap::ArgAction::SetTrue) + ) + .arg( + Arg::new("iterations") + .long("iterations") + .value_name("COUNT") + .help("Number of iterations for benchmarks (default: 10)") + .default_value("10") + ) + } + + /// Convert ArgMatches to CliConfig + fn from_matches(matches: &ArgMatches) -> Self { + Self { + file: matches.get_one::("file").cloned(), + debug_fuel: parse_debug_fuel(matches.get_one::("debug-fuel").unwrap()), + dump_mir: matches.get_flag("dump-mir"), + verify_mir: matches.get_flag("verify"), + mir_verbose: matches.get_flag("mir-verbose"), + backend: matches.get_one::("backend").unwrap().clone(), + compile_wasm: matches.get_flag("compile-wasm"), + compile_native: matches.get_flag("compile-native") || matches.get_flag("aot"), + output_file: matches.get_one::("output").cloned(), + benchmark: matches.get_flag("benchmark"), + iterations: matches.get_one::("iterations").unwrap().parse().unwrap_or(10), + } + } +} + +/// Parse debug fuel value ("unlimited" or numeric) +fn parse_debug_fuel(value: &str) -> Option { + if value == "unlimited" { + None // No limit + } else { + value.parse::().ok() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_debug_fuel() { + assert_eq!(parse_debug_fuel("unlimited"), None); + assert_eq!(parse_debug_fuel("1000"), Some(1000)); + assert_eq!(parse_debug_fuel("invalid"), None); + } + + #[test] + fn test_default_config() { + // This test would require mocking clap's behavior + // For now, we just ensure the structure is valid + let config = CliConfig { + file: None, + debug_fuel: Some(100000), + dump_mir: false, + verify_mir: false, + mir_verbose: false, + backend: "interpreter".to_string(), + compile_wasm: false, + compile_native: false, + output_file: None, + benchmark: false, + iterations: 10, + }; + + assert_eq!(config.backend, "interpreter"); + assert_eq!(config.iterations, 10); + } +} \ 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 5be2a9ee..5dcbe62e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,12 @@ * * This is the main entry point for the Rust implementation of Nyash, * demonstrating the "Everything is Box" philosophy with Rust's ownership system. + * + * The main function serves as a thin entry point that delegates to the CLI + * and runner modules for actual processing. */ +// Core modules pub mod box_trait; pub mod boxes; pub mod environment; @@ -18,1473 +22,41 @@ 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 -use box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, AddBox, BoxCore}; -use environment::{Environment, PythonCompatEnvironment}; -use tokenizer::{NyashTokenizer, TokenType}; -use ast::ASTNode; -use parser::NyashParser; -use interpreter::NyashInterpreter; - // 🚀 MIR Infrastructure pub mod mir; -use mir::{MirCompiler, MirPrinter}; // 🚀 Backend Infrastructure pub mod backend; -use backend::{VM, wasm::WasmBackend, aot::AotBackend}; -use std::env; -use std::fs; -use std::process; -use clap::{Arg, Command}; +// 🚀 Refactored modules for better organization +pub mod cli; +pub mod runner; + +use cli::CliConfig; +use runner::NyashRunner; + +/// Thin entry point - delegates to CLI parsing and runner execution fn main() { - // 🔥 clap使ったコマンド引数解析 - let matches = Command::new("nyash") - .version("1.0") - .author("Claude Code ") - .about("🦀 Nyash Programming Language - Everything is Box in Rust! 🦀") - .arg( - Arg::new("file") - .help("Nyash file to execute") - .value_name("FILE") - .index(1) - ) - .arg( - Arg::new("debug-fuel") - .long("debug-fuel") - .value_name("ITERATIONS") - .help("Set parser debug fuel limit (default: 100000, 'unlimited' for no limit)") - .default_value("100000") - ) - .arg( - Arg::new("dump-mir") - .long("dump-mir") - .help("Dump MIR (Mid-level Intermediate Representation) instead of executing") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("verify") - .long("verify") - .help("Verify MIR integrity and exit") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("mir-verbose") - .long("mir-verbose") - .help("Show verbose MIR output with statistics") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("backend") - .long("backend") - .value_name("BACKEND") - .help("Choose execution backend: 'interpreter' (default) or 'vm'") - .default_value("interpreter") - ) - .arg( - Arg::new("compile-wasm") - .long("compile-wasm") - .help("Compile to WebAssembly (WAT format) instead of executing") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("compile-native") - .long("compile-native") - .help("Compile to native AOT executable using wasmtime precompilation") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("aot") - .long("aot") - .help("Short form of --compile-native") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("output") - .long("output") - .short('o') - .value_name("FILE") - .help("Output file (for WASM compilation or AOT executable)") - ) - .arg( - Arg::new("benchmark") - .long("benchmark") - .help("Run performance benchmarks across all backends") - .action(clap::ArgAction::SetTrue) - ) - .arg( - Arg::new("iterations") - .long("iterations") - .value_name("COUNT") - .help("Number of iterations for benchmarks (default: 10)") - .default_value("10") - ) - .get_matches(); + // Parse command-line arguments + let config = CliConfig::parse(); - // デバッグ燃料の解析 - let debug_fuel = parse_debug_fuel(matches.get_one::("debug-fuel").unwrap()); - - // MIR mode flags - let dump_mir = matches.get_flag("dump-mir"); - let verify_mir = matches.get_flag("verify"); - let mir_verbose = matches.get_flag("mir-verbose"); - let compile_wasm = matches.get_flag("compile-wasm"); - let compile_native = matches.get_flag("compile-native") || matches.get_flag("aot"); - let backend = matches.get_one::("backend").unwrap(); - let output_file = matches.get_one::("output"); - let benchmark = matches.get_flag("benchmark"); - let iterations: u32 = matches.get_one::("iterations").unwrap().parse().unwrap_or(10); - - // Benchmark mode - can run without a file - if benchmark { - println!("📊 Nyash Performance Benchmark Suite"); - println!("===================================="); - println!("Running {} iterations per test...", iterations); - println!(); - - execute_benchmark_mode(iterations); - return; - } - - if let Some(filename) = matches.get_one::("file") { - // File mode: parse and execute the provided .nyash file - if dump_mir || verify_mir { - println!("🚀 Nyash MIR Compiler - Processing file: {} 🚀", filename); - execute_mir_mode(filename, dump_mir, verify_mir, mir_verbose); - } else if compile_wasm { - println!("🌐 Nyash WASM Compiler - Processing file: {} 🌐", filename); - execute_wasm_mode(filename, output_file); - } else if compile_native { - println!("🚀 Nyash AOT Compiler - Processing file: {} 🚀", filename); - execute_aot_mode(filename, output_file); - } else if backend == "vm" { - println!("🚀 Nyash VM Backend - Executing file: {} 🚀", filename); - execute_vm_mode(filename); - } else { - println!("🦀 Nyash Rust Implementation - Executing file: {} 🦀", filename); - if let Some(fuel) = debug_fuel { - println!("🔥 Debug fuel limit: {} iterations", fuel); - } else { - println!("🔥 Debug fuel limit: unlimited"); - } - println!("===================================================="); - - execute_nyash_file(filename, debug_fuel); - } - } else { - // Demo mode: run built-in demonstrations - println!("🦀 Nyash Rust Implementation - Everything is Box! 🦀"); - println!("===================================================="); - - // Demonstrate basic Box creation and operations - demo_basic_boxes(); - - // Demonstrate Box operations - demo_box_operations(); - - // Demonstrate Box collections - demo_box_collections(); - - // Demonstrate Environment & Scope management - demo_environment_system(); - - // Demonstrate Tokenizer system - demo_tokenizer_system(); - - // Demonstrate Parser system - demo_parser_system(); - - // Demonstrate Interpreter system - demo_interpreter_system(); - - println!("\n🎉 All Box operations completed successfully!"); - println!("Memory safety guaranteed by Rust's borrow checker! 🛡️"); - } -} - -/// デバッグ燃料値をパース("unlimited" または数値) -fn parse_debug_fuel(value: &str) -> Option { - if value == "unlimited" { - None // 無制限 - } else { - value.parse::().ok() - } -} - -fn execute_nyash_file(filename: &str, debug_fuel: Option) { - // Read the file - let code = match fs::read_to_string(filename) { - Ok(content) => content, - Err(e) => { - eprintln!("❌ Error reading file {}: {}", filename, e); - process::exit(1); - } - }; - - println!("📝 File contents:\n{}", code); - println!("\n🚀 Parsing and executing...\n"); - - // テスト用:即座にファイル作成 - std::fs::write("/mnt/c/git/nyash/development/debug_hang_issue/test.txt", "START").ok(); - - // Parse the code with debug fuel limit - eprintln!("🔍 DEBUG: Starting parse with fuel: {:?}...", debug_fuel); - let ast = match NyashParser::parse_from_string_with_fuel(&code, debug_fuel) { - Ok(ast) => { - eprintln!("🔍 DEBUG: Parse completed, AST created"); - ast - }, - Err(e) => { - eprintln!("❌ Parse error: {}", e); - process::exit(1); - } - }; - - eprintln!("🔍 DEBUG: About to print parse success message..."); - println!("✅ Parse successful!"); - eprintln!("🔍 DEBUG: Parse success message printed"); - - // デバッグログファイルに書き込み - if let Ok(mut file) = std::fs::OpenOptions::new() - .create(true) - .append(true) - .open("/mnt/c/git/nyash/development/debug_hang_issue/debug_trace.log") - { - use std::io::Write; - let _ = writeln!(file, "=== MAIN: Parse successful ==="); - let _ = file.flush(); - } - - eprintln!("🔍 DEBUG: Creating interpreter..."); - - // Execute the AST - let mut interpreter = NyashInterpreter::new(); - eprintln!("🔍 DEBUG: Starting execution..."); - match interpreter.execute(ast) { - Ok(result) => { - println!("✅ Execution completed successfully!"); - println!("Result: {}", result.to_string_box().value); - }, - Err(e) => { - // 🔥 Use enhanced error reporting with source context - eprintln!("❌ Runtime error:\n{}", e.detailed_message(Some(&code))); - process::exit(1); - } - } -} - -fn demo_basic_boxes() { - println!("\n📦 1. Basic Box Creation:"); - - // Create basic boxes - let string_box = StringBox::new("Hello from Rust!"); - let integer_box = IntegerBox::new(42); - let bool_box = BoolBox::new(true); - let void_box = VoidBox::new(); - - println!(" StringBox: {} (ID: {})", string_box, string_box.box_id()); - println!(" IntegerBox: {} (ID: {})", integer_box, integer_box.box_id()); - println!(" BoolBox: {} (ID: {})", bool_box, bool_box.box_id()); - println!(" VoidBox: {} (ID: {})", void_box, void_box.box_id()); - - // Test type identification - println!("\n🔍 Type Information:"); - println!(" StringBox type: {}", string_box.type_name()); - println!(" IntegerBox type: {}", integer_box.type_name()); - println!(" BoolBox type: {}", bool_box.type_name()); - println!(" VoidBox type: {}", void_box.type_name()); -} - -fn demo_box_operations() { - println!("\n⚡ 2. Box Operations:"); - - // Integer addition - let left_int = Box::new(IntegerBox::new(10)) as Box; - let right_int = Box::new(IntegerBox::new(32)) as Box; - let int_add = AddBox::new(left_int, right_int); - let int_result = int_add.execute(); - - println!(" Integer Addition: 10 + 32 = {}", int_result.to_string_box()); - - // String concatenation - let left_str = Box::new(StringBox::new("Everything is ")) as Box; - let right_str = Box::new(StringBox::new("Box in Rust!")) as Box; - let str_add = AddBox::new(left_str, right_str); - let str_result = str_add.execute(); - - println!(" String Concatenation: {}", str_result.to_string_box()); - - // Mixed type addition (falls back to string concatenation) - let mixed_left = Box::new(StringBox::new("Answer: ")) as Box; - let mixed_right = Box::new(IntegerBox::new(42)) as Box; - let mixed_add = AddBox::new(mixed_left, mixed_right); - let mixed_result = mixed_add.execute(); - - println!(" Mixed Addition: {}", mixed_result.to_string_box()); -} - -fn demo_box_collections() { - println!("\n📚 3. Box Collections:"); - - // Create a collection of various boxes - let mut box_collection: Vec> = Vec::new(); - - box_collection.push(Box::new(StringBox::new("First Box"))); - box_collection.push(Box::new(IntegerBox::new(100))); - box_collection.push(Box::new(BoolBox::new(false))); - box_collection.push(Box::new(VoidBox::new())); - - println!(" Collection contents:"); - for (i, box_item) in box_collection.iter().enumerate() { - println!(" [{}] {} (Type: {}, ID: {})", - i, - box_item.to_string_box(), - box_item.type_name(), - box_item.box_id()); - } - - // Test equality - println!("\n🔍 Equality Testing:"); - let test1 = StringBox::new("test"); - let test2 = StringBox::new("test"); - let test3 = StringBox::new("different"); - - println!(" \"test\" == \"test\": {}", test1.equals(&test2)); - println!(" \"test\" == \"different\": {}", test1.equals(&test3)); -} - -fn demo_environment_system() { - println!("\n🌐 4. Environment & Scope Management:"); - - // Create global environment - let global_env = Environment::new_global(); - println!(" Created global environment: {}", global_env.lock().unwrap().scope_info()); - - // Add global variables - global_env.lock().unwrap().define("project_name", Box::new(StringBox::new("Nyash in Rust"))); - global_env.lock().unwrap().define("version", Box::new(StringBox::new("v1.0-rust"))); - global_env.lock().unwrap().define("debug_mode", Box::new(BoolBox::new(true))); - - println!(" Global variables: {:?}", global_env.lock().unwrap().list_variables()); - - // Create function scope - let function_env = Environment::new_child(global_env.clone(), "test_function"); - println!(" Created function scope: {}", function_env.lock().unwrap().scope_info()); - - // Add local variables - function_env.lock().unwrap().define("local_var", Box::new(IntegerBox::new(42))); - function_env.lock().unwrap().define("temp_result", Box::new(StringBox::new("processing..."))); - - // Test variable access from child scope - println!("\n 🔍 Variable Access Tests:"); - - // Access global variable from function scope - match function_env.lock().unwrap().get("project_name") { - Ok(value) => println!(" Access global from function: {}", value.to_string_box()), - Err(e) => println!(" Error: {}", e), - } - - // Access local variable - match function_env.lock().unwrap().get("local_var") { - Ok(value) => println!(" Access local variable: {}", value.to_string_box()), - Err(e) => println!(" Error: {}", e), - } - - // Try to access local variable from global (should fail) - match global_env.lock().unwrap().get("local_var") { - Ok(value) => println!(" Unexpected access to local from global: {}", value.to_string_box()), - Err(e) => println!(" ✅ Correctly blocked access to local from global: {}", e), - } - - // Test variable setting (modification) - println!("\n 🔧 Variable Modification Tests:"); - - // Modify global variable from function scope - let _ = function_env.lock().unwrap().set("version", Box::new(StringBox::new("v1.1-rust-updated"))); - - // Check if global was updated - let updated_version = global_env.lock().unwrap().get("version").unwrap(); - println!(" Updated global variable: {}", updated_version.to_string_box()); - - // Create nested scope (function inside function) - let nested_env = Environment::new_child(function_env.clone(), "nested_function"); - nested_env.lock().unwrap().define("nested_var", Box::new(BoolBox::new(false))); - - // Test scope chain - println!("\n 📊 Scope Chain Analysis:"); - let scope_chain = nested_env.lock().unwrap().scope_chain_info(); - for (i, scope_info) in scope_chain.iter().enumerate() { - println!(" Level {}: {}", i, scope_info); - } - - // Test variable shadowing - println!("\n 🌑 Variable Shadowing Test:"); - function_env.lock().unwrap().define("debug_mode", Box::new(BoolBox::new(false))); // Shadow global - - let global_debug = global_env.lock().unwrap().get("debug_mode").unwrap(); - let function_debug = function_env.lock().unwrap().get("debug_mode").unwrap(); - - println!(" Global debug_mode: {}", global_debug.to_string_box()); - println!(" Function debug_mode (shadowed): {}", function_debug.to_string_box()); - - // Test Python compatibility layer - println!("\n 🐍 Python Compatibility Layer:"); - let mut python_env = PythonCompatEnvironment::new(); - python_env.define("py_var", Box::new(StringBox::new("python_style"))); - - let py_value = python_env.get("py_var"); - println!(" Python-style access: {}", py_value.to_string_box()); - println!(" _bindings contains: {:?}", python_env._bindings.keys().collect::>()); - - // Dump all variables for debugging - println!("\n 📋 Complete Variable Dump:"); - let all_vars = nested_env.lock().unwrap().dump_all_variables(); - for (qualified_name, value) in all_vars { - println!(" {}: {}", qualified_name, value); - } -} - -fn demo_tokenizer_system() { - println!("\n🔤 5. Tokenizer System:"); - - // Test simple tokens - println!(" 📝 Simple Token Test:"); - let simple_code = "box TestBox { value }"; - let mut tokenizer = NyashTokenizer::new(simple_code); - - match tokenizer.tokenize() { - Ok(tokens) => { - println!(" Input: {}", simple_code); - println!(" Tokens:"); - for (i, token) in tokens.iter().enumerate() { - if matches!(token.token_type, TokenType::EOF) { - break; // EOF は表示しない - } - println!(" [{}] {:?} at line {}, column {}", - i, token.token_type, token.line, token.column); - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test complex code (same as debug_this_problem.nyash) - println!("\n 🚀 Complex Code Test:"); - let complex_code = r#" -// this問題のミニマル再現 -box TestBox { - value - - getValue() { - return this.value - } -} - -// テスト -obj = new TestBox() -obj.value = "test123" -print("Direct field: " + obj.value) -print("Method call: " + obj.getValue()) -"#; - - let mut complex_tokenizer = NyashTokenizer::new(complex_code); - match complex_tokenizer.tokenize() { - Ok(tokens) => { - let non_eof_tokens: Vec<_> = tokens.iter() - .filter(|t| !matches!(t.token_type, TokenType::EOF)) - .collect(); - - println!(" Successfully tokenized {} tokens", non_eof_tokens.len()); - - // Show first 10 tokens - println!(" First 10 tokens:"); - for (i, token) in non_eof_tokens.iter().take(10).enumerate() { - println!(" [{}] {:?}", i, token.token_type); - } - - // Count token types - let mut token_counts = std::collections::HashMap::new(); - for token in &non_eof_tokens { - let type_name = match &token.token_type { - TokenType::IDENTIFIER(_) => "IDENTIFIER", - TokenType::STRING(_) => "STRING", - TokenType::NUMBER(_) => "NUMBER", - TokenType::BOX => "BOX", - TokenType::NEW => "NEW", - TokenType::THIS => "THIS", - TokenType::RETURN => "RETURN", - TokenType::PRINT => "PRINT", - TokenType::DOT => "DOT", - TokenType::ASSIGN => "ASSIGN", - TokenType::PLUS => "PLUS", - TokenType::LPAREN => "LPAREN", - TokenType::RPAREN => "RPAREN", - TokenType::LBRACE => "LBRACE", - TokenType::RBRACE => "RBRACE", - _ => "OTHER", - }; - *token_counts.entry(type_name).or_insert(0) += 1; - } - - println!(" Token type counts:"); - for (type_name, count) in token_counts { - println!(" {}: {}", type_name, count); - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test string literals and escapes - println!("\n 📝 String Literal Test:"); - let string_code = r#""Hello, World!" "Line 1\nLine 2" "Tab\tSeparated""#; - let mut string_tokenizer = NyashTokenizer::new(string_code); - - match string_tokenizer.tokenize() { - Ok(tokens) => { - for token in tokens.iter() { - if let TokenType::STRING(s) = &token.token_type { - println!(" String: {:?}", s); - } - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test numbers - println!("\n 🔢 Number Test:"); - let number_code = "42 0 123 999"; - let mut number_tokenizer = NyashTokenizer::new(number_code); - - match number_tokenizer.tokenize() { - Ok(tokens) => { - for token in tokens.iter() { - if let TokenType::NUMBER(n) = &token.token_type { - println!(" Number: {}", n); - } - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test error handling - println!("\n ❌ Error Handling Test:"); - let error_code = "box test @#$%"; - let mut error_tokenizer = NyashTokenizer::new(error_code); - - match error_tokenizer.tokenize() { - Ok(_) => println!(" Unexpected success"), - Err(e) => println!(" Expected error: {}", e), - } -} - -fn demo_parser_system() { - println!("\n🌳 6. Parser & AST System:"); - - // Test simple box declaration - println!(" 📝 Simple Box Declaration Test:"); - let simple_code = r#" - box TestBox { - value - - getValue() { - return this.value - } - } - "#; - - match NyashParser::parse_from_string(simple_code) { - Ok(ast) => { - println!(" Input: {}", simple_code.trim()); - println!(" AST: {}", ast); - - if let ASTNode::Program { statements, .. } = &ast { - println!(" Program has {} statements", statements.len()); - for (i, stmt) in statements.iter().enumerate() { - println!(" [{}] {}", i, stmt.info()); - } - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test assignment and method call - println!("\n 🚀 Assignment & Method Call Test:"); - let assignment_code = r#" - obj = new TestBox() - obj.value = "test123" - print("Direct field: " + obj.value) - print("Method call: " + obj.getValue()) - "#; - - match NyashParser::parse_from_string(assignment_code) { - Ok(ast) => { - println!(" Successfully parsed assignment & method call code"); - - if let ASTNode::Program { statements, .. } = &ast { - println!(" Parsed {} statements:", statements.len()); - for (i, stmt) in statements.iter().enumerate() { - println!(" [{}] {} ({})", i, stmt.info(), stmt.node_type()); - } - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test expression parsing - println!("\n ⚡ Expression Parsing Test:"); - let expr_code = r#" - result = x + y * z - condition = a == b && c < d - "#; - - match NyashParser::parse_from_string(expr_code) { - Ok(ast) => { - println!(" Successfully parsed complex expressions"); - - if let ASTNode::Program { statements, .. } = &ast { - for (i, stmt) in statements.iter().enumerate() { - if let ASTNode::Assignment { target, value, .. } = stmt { - println!(" Assignment [{}]: {} = {}", i, target.info(), value.info()); - } - } - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test control structures - println!("\n 🔄 Control Structure Test:"); - let control_code = r#" - if condition { - print("True branch") - } else { - print("False branch") - } - - loop { - print("Loop body") - return - } - "#; - - match NyashParser::parse_from_string(control_code) { - Ok(ast) => { - println!(" Successfully parsed control structures"); - - if let ASTNode::Program { statements, .. } = &ast { - for (i, stmt) in statements.iter().enumerate() { - println!(" [{}] {} ({})", i, stmt.info(), stmt.node_type()); - } - } - } - Err(e) => println!(" Error: {}", e), - } - - // Test the debug_this_problem.nyash equivalent - println!("\n 🐛 Debug This Problem Test (Rust Parser):"); - let debug_code = r#" - // this問題のミニマル再現 - box TestBox { - value - - getValue() { - return this.value - } - } - - // テスト - obj = new TestBox() - obj.value = "test123" - print("Direct field: " + obj.value) - print("Method call: " + obj.getValue()) - "#; - - match NyashParser::parse_from_string(debug_code) { - Ok(ast) => { - println!(" ✅ Successfully parsed debug_this_problem equivalent!"); - - if let ASTNode::Program { statements, .. } = &ast { - println!(" Complete program structure:"); - println!(" Total statements: {}", statements.len()); - - let mut box_count = 0; - let mut assignment_count = 0; - let mut print_count = 0; - let mut method_calls = 0; - - for stmt in statements { - match stmt { - ASTNode::BoxDeclaration { .. } => box_count += 1, - ASTNode::Assignment { .. } => assignment_count += 1, - ASTNode::Print { .. } => print_count += 1, - _ => {} - } - - // Count method calls recursively - count_method_calls(stmt, &mut method_calls); - } - - println!(" - Box declarations: {}", box_count); - println!(" - Assignments: {}", assignment_count); - println!(" - Print statements: {}", print_count); - println!(" - Method calls found: {}", method_calls); - - println!(" 🎯 Parser successfully handles 'this' context in AST!"); - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } -} - -// Helper function to count method calls recursively -fn count_method_calls(node: &ASTNode, count: &mut usize) { - match node { - ASTNode::MethodCall { .. } => { - *count += 1; - } - ASTNode::Program { statements, .. } => { - for stmt in statements { - count_method_calls(stmt, count); - } - } - ASTNode::Assignment { target, value, .. } => { - count_method_calls(target, count); - count_method_calls(value, count); - } - ASTNode::Print { expression, .. } => { - count_method_calls(expression, count); - } - ASTNode::BinaryOp { left, right, .. } => { - count_method_calls(left, count); - count_method_calls(right, count); - } - ASTNode::BoxDeclaration { methods, .. } => { - for method in methods.values() { - count_method_calls(method, count); - } - } - ASTNode::FunctionDeclaration { body, .. } => { - for stmt in body { - count_method_calls(stmt, count); - } - } - ASTNode::Return { value, .. } => { - if let Some(val) = value { - count_method_calls(val, count); - } - } - _ => {} - } -} - -fn demo_interpreter_system() { - println!("\n🚀 7. Interpreter & Execution System:"); - - // Test simple variable assignment and print - println!(" 📝 Simple Assignment & Print Test:"); - let simple_code = r#" - x = 42 - y = "Hello, Nyash!" - print(x) - print(y) - "#; - - match NyashParser::parse_from_string(simple_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Code: {}", simple_code.trim()); - println!(" Output:"); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ Execution successful!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test arithmetic operations - println!("\n ⚡ Arithmetic Operations Test:"); - let arithmetic_code = r#" - a = 10 - b = 32 - result = a + b - print("10 + 32 = " + result) - "#; - - match NyashParser::parse_from_string(arithmetic_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing arithmetic operations..."); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ Arithmetic execution successful!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test if statements - println!("\n 🔄 Control Flow (If) Test:"); - let if_code = r#" - condition = true - if condition { - print("Condition was true!") - result = "success" - } else { - print("Condition was false!") - result = "failure" - } - print("Result: " + result) - "#; - - match NyashParser::parse_from_string(if_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing if statement..."); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ If statement execution successful!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test AND/OR operators - println!("\n 🔗 Logical Operators Test:"); - let logic_code = r#" - a = true - b = false - result1 = a && b - result2 = a || b - print("true && false = " + result1) - print("true || false = " + result2) - "#; - - match NyashParser::parse_from_string(logic_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing logical operators..."); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ Logical operators execution successful!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test loop with break - println!("\n 🔁 Loop with Break Test:"); - let loop_code = r#" - counter = 0 - loop { - counter = counter + 1 - print("Loop iteration: " + counter) - if counter == 3 { - print("Breaking loop!") - break - } - } - print("Final counter: " + counter) - "#; - - match NyashParser::parse_from_string(loop_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing loop with break..."); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ Loop execution successful!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test Box declaration and instance creation - println!("\n 📦 Box Declaration & Instance Test:"); - let box_code = r#" - box TestBox { - value - - getValue() { - return this.value - } - - setValue(newValue) { - this.value = newValue - } - } - - // Create instance - obj = new TestBox() - print("Created TestBox instance: " + obj) - - // Set field directly - obj.value = "test123" - print("Set field directly: obj.value = " + obj.value) - - // Call method that uses this - result = obj.getValue() - print("Method call result: " + result) - - // Call method that modifies via this - obj.setValue("modified value") - print("After setValue: " + obj.value) - "#; - - match NyashParser::parse_from_string(box_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Testing Box instances with 'this' binding..."); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ Box instance & 'this' working correctly!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test global variable - println!("\n 🌍 Global Variable Test:"); - let global_code = r#" - global project_name = "Nyash in Rust" - global version = "v1.0" - - print("Project: " + project_name) - print("Version: " + version) - "#; - - match NyashParser::parse_from_string(global_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Setting global variables..."); - - match interpreter.execute(ast) { - Ok(_) => println!(" ✅ Global variables successful!"), - Err(e) => println!(" ❌ Runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Parse error: {}", e), - } - - // Test Self-Hosting Demonstration - println!("\n 🎆 SELF-HOSTING DEMONSTRATION 🎆:"); - println!(" Loading self-hosting test file..."); - - match std::fs::read_to_string("test_self_hosting_simple.nyash") { - Ok(self_hosting_code) => { - match NyashParser::parse_from_string(&self_hosting_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing self-hosting simulation..."); - - match interpreter.execute(ast) { - Ok(_) => { - println!(" 🚀 LEGENDARY ACHIEVEMENT UNLOCKED! 🚀"); - println!(" Rust-based Nyash interpreter successfully executed"); - println!(" Nyash code that simulates compiling other Nyash code!"); - println!(" Self-hosting level: ULTIMATE META-PROGRAMMING! 🎆"); - }, - Err(e) => println!(" ❌ Self-hosting runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Self-hosting parse error: {}", e), - } - } - Err(_) => { - println!(" ⚠️ test_self_hosting_simple.nyash not found, using inline test:"); - - let inline_self_hosting = r#" - print("🎆 Inline Self-Hosting Test 🎆") - - box MetaCompiler { - name - - init(compilerName) { - this.name = compilerName - } - - compile(code) { - return "Compiled by " + this.name + ": " + code - } - } - - meta = new MetaCompiler() - meta.init("Nyash-in-Rust") - result = meta.compile("Everything is Box!") - print(result) - print("🚀 Meta-compilation successful!") - "#; - - match NyashParser::parse_from_string(inline_self_hosting) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - match interpreter.execute(ast) { - Ok(_) => println!(" 🎆 Inline self-hosting successful! 🎆"), - Err(e) => println!(" ❌ Inline self-hosting error: {}", e), - } - } - Err(e) => println!(" ❌ Inline self-hosting parse error: {}", e), - } - } - } - - // Test Interface Box Implementation - println!("\n 🎆 INTERFACE BOX IMPLEMENTATION TEST 🎆:"); - println!(" Testing interface box syntax support..."); - - match std::fs::read_to_string("test_interface.nyash") { - Ok(interface_code) => { - match NyashParser::parse_from_string(&interface_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing interface box test..."); - - match interpreter.execute(ast) { - Ok(_) => { - println!(" 🚀 INTERFACE BOX STEP 1 SUCCESS! 🚀"); - println!(" ✅ interface box syntax parsing works!"); - println!(" ✅ Interface registration successful!"); - println!(" Next: extends and implements syntax..."); - }, - Err(e) => println!(" ❌ Interface runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Interface parse error: {}", e), - } - } - Err(_) => { - println!(" ⚠️ test_interface.nyash not found, using inline test:"); - - let inline_interface_test = r#" - print("🎆 Inline Interface Test 🎆") - - interface box Testable { - test() - verify(result) - } - - print("Interface box declared successfully!") - print("✅ Step 1: interface box syntax - WORKING!") - "#; - - match NyashParser::parse_from_string(inline_interface_test) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - match interpreter.execute(ast) { - Ok(_) => println!(" 🎆 Interface syntax working! 🎆"), - Err(e) => println!(" ❌ Interface test error: {}", e), - } - } - Err(e) => println!(" ❌ Interface test parse error: {}", e), - } - } - } - - // Test Inheritance Implementation - println!("\n 🚀 INHERITANCE IMPLEMENTATION TEST 🚀:"); - println!(" Testing extends & implements syntax..."); - - match std::fs::read_to_string("test_inheritance.nyash") { - Ok(inheritance_code) => { - match NyashParser::parse_from_string(&inheritance_code) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - println!(" Executing inheritance test..."); - - match interpreter.execute(ast) { - Ok(_) => { - println!(" 🎆 INHERITANCE STEPS 2&3 SUCCESS! 🎆"); - println!(" ✅ extends syntax working!"); - println!(" ✅ implements syntax working!"); - println!(" ✅ Inheritance chain resolution!"); - println!(" ✅ Interface validation!"); - println!(" ✅ Method overriding!"); - }, - Err(e) => println!(" ❌ Inheritance runtime error: {}", e), - } - } - Err(e) => println!(" ❌ Inheritance parse error: {}", e), - } - } - Err(_) => { - println!(" ⚠️ test_inheritance.nyash not found, using inline test:"); - - let inline_inheritance_test = r#" - print("🚀 Inline Inheritance Test 🚀") - - interface box Speakable { - speak() - } - - box Animal { - name - speak() { - return "Animal sound" - } - } - - box Dog extends Animal implements Speakable { - breed - speak() { - return "Woof!" - } - } - - dog = new Dog() - dog.name = "Buddy" - dog.breed = "Labrador" - print("Dog says: " + dog.speak()) - print("✅ Inheritance working!") - "#; - - match NyashParser::parse_from_string(inline_inheritance_test) { - Ok(ast) => { - let mut interpreter = NyashInterpreter::new(); - match interpreter.execute(ast) { - Ok(_) => println!(" 🚀 Inheritance test successful! 🚀"), - Err(e) => println!(" ❌ Inheritance test error: {}", e), - } - } - Err(e) => println!(" ❌ Inheritance test parse error: {}", e), - } - } - } -} - -/// Execute MIR compilation and processing mode -fn execute_mir_mode(filename: &str, dump_mir: bool, verify_mir: bool, verbose: bool) { - // Read the source file - let source = match fs::read_to_string(filename) { - Ok(content) => content, - Err(e) => { - eprintln!("❌ Error reading file '{}': {}", filename, e); - process::exit(1); - } - }; - - // Parse to AST - let ast = match NyashParser::parse_from_string(&source) { - Ok(ast) => ast, - Err(e) => { - eprintln!("❌ Parse error: {}", e); - process::exit(1); - } - }; - - // Compile to MIR - let mut compiler = MirCompiler::new(); - let compile_result = match compiler.compile(ast) { - Ok(result) => result, - Err(e) => { - eprintln!("❌ MIR compilation error: {}", e); - process::exit(1); - } - }; - - // Handle verification - if verify_mir || dump_mir { - match &compile_result.verification_result { - Ok(()) => { - if verify_mir { - println!("✅ MIR verification passed"); - } - }, - Err(errors) => { - eprintln!("❌ MIR verification failed with {} error(s):", errors.len()); - for (i, error) in errors.iter().enumerate() { - eprintln!(" {}: {}", i + 1, error); - } - if verify_mir { - process::exit(1); - } - } - } - } - - // Handle MIR dumping - if dump_mir { - let mut printer = if verbose { - MirPrinter::verbose() - } else { - MirPrinter::new() - }; - - let mir_output = printer.print_module(&compile_result.module); - println!("{}", mir_output); - } - - // Show module statistics if verification was requested - if verify_mir { - let stats = compile_result.module.stats(); - println!("\n📊 Module Statistics:"); - println!(" Functions: {}", stats.function_count); - println!(" Total Blocks: {}", stats.total_blocks); - println!(" Total Instructions: {}", stats.total_instructions); - println!(" Total Values: {}", stats.total_values); - println!(" Pure Functions: {}", stats.pure_functions); - - if stats.function_count > 0 { - for (name, function) in &compile_result.module.functions { - let func_stats = function.stats(); - println!("\n📊 Function '{}' Statistics:", name); - println!(" Blocks: {}", func_stats.block_count); - println!(" Instructions: {}", func_stats.instruction_count); - println!(" Values: {}", func_stats.value_count); - println!(" Phi Functions: {}", func_stats.phi_count); - println!(" Pure: {}", func_stats.is_pure); - } - } - } -} - -/// Execute VM mode -fn execute_vm_mode(filename: &str) { - // Read the source file - let source = match fs::read_to_string(filename) { - Ok(content) => content, - Err(e) => { - eprintln!("❌ Error reading file '{}': {}", filename, e); - process::exit(1); - } - }; - - // Parse to AST - let ast = match NyashParser::parse_from_string(&source) { - Ok(ast) => ast, - Err(e) => { - eprintln!("❌ Parse error: {}", e); - process::exit(1); - } - }; - - // Compile to MIR - let mut compiler = MirCompiler::new(); - let compile_result = match compiler.compile(ast) { - Ok(result) => result, - Err(e) => { - eprintln!("❌ MIR compilation error: {}", e); - process::exit(1); - } - }; - - // Check for verification errors - if let Err(errors) = &compile_result.verification_result { - eprintln!("❌ MIR verification failed with {} error(s):", errors.len()); - for (i, error) in errors.iter().enumerate() { - eprintln!(" {}: {}", i + 1, error); - } - // Continue execution anyway for now - } - - // Execute with VM - let mut vm = VM::new(); - match vm.execute_module(&compile_result.module) { - Ok(result) => { - println!("✅ VM execution completed successfully!"); - println!("Result: {}", result.to_string_box().value); - }, - Err(e) => { - eprintln!("❌ VM runtime error: {}", e); - process::exit(1); - } - } -} - -/// Execute WASM compilation mode -fn execute_wasm_mode(filename: &str, output_file: Option<&String>) { - // Read the source file - let source = match fs::read_to_string(filename) { - Ok(content) => content, - Err(e) => { - eprintln!("❌ Error reading file '{}': {}", filename, e); - process::exit(1); - } - }; - - // Parse to AST - let ast = match NyashParser::parse_from_string(&source) { - Ok(ast) => ast, - Err(e) => { - eprintln!("❌ Parse error: {}", e); - process::exit(1); - } - }; - - // Compile to MIR - let mut compiler = MirCompiler::new(); - let compile_result = match compiler.compile(ast) { - Ok(result) => result, - Err(e) => { - eprintln!("❌ MIR compilation error: {}", e); - process::exit(1); - } - }; - - // Check for verification errors - if let Err(errors) = &compile_result.verification_result { - eprintln!("⚠️ MIR verification warnings ({} issues):", errors.len()); - for (i, error) in errors.iter().enumerate() { - eprintln!(" {}: {}", i + 1, error); - } - println!("Continuing with WASM compilation..."); - } - - // Compile to WASM - let mut wasm_backend = WasmBackend::new(); - match wasm_backend.compile_to_wat(compile_result.module) { - Ok(wat_text) => { - println!("✅ WASM compilation completed successfully!"); - - if let Some(output_path) = output_file { - // Write to file - match fs::write(output_path, &wat_text) { - Ok(_) => println!("📄 WAT output written to: {}", output_path), - Err(e) => { - eprintln!("❌ Error writing to file '{}': {}", output_path, e); - process::exit(1); - } - } - } else { - // Print to stdout - println!("📄 Generated WAT:"); - println!("{}", wat_text); - } - }, - Err(e) => { - eprintln!("❌ WASM compilation error: {}", e); - process::exit(1); - } - } -} - -/// Execute AOT compilation mode -fn execute_aot_mode(filename: &str, output_file: Option<&String>) { - // Read the source file - let source = match fs::read_to_string(filename) { - Ok(content) => content, - Err(e) => { - eprintln!("❌ Error reading file '{}': {}", filename, e); - process::exit(1); - } - }; - - // Parse to AST - let ast = match NyashParser::parse_from_string(&source) { - Ok(ast) => ast, - Err(e) => { - eprintln!("❌ Parse error: {}", e); - process::exit(1); - } - }; - - // Compile to MIR - let mut compiler = MirCompiler::new(); - let compile_result = match compiler.compile(ast) { - Ok(result) => result, - Err(e) => { - eprintln!("❌ MIR compilation error: {}", e); - process::exit(1); - } - }; - - // Check for verification errors - if let Err(errors) = &compile_result.verification_result { - eprintln!("⚠️ MIR verification warnings ({} issues):", errors.len()); - for (i, error) in errors.iter().enumerate() { - eprintln!(" {}: {}", i + 1, error); - } - println!("Continuing with AOT compilation..."); - } - - // Compile to AOT executable - let mut aot_backend = match AotBackend::new() { - Ok(backend) => backend, - Err(e) => { - eprintln!("❌ Failed to create AOT backend: {}", e); - process::exit(1); - } - }; - - // Determine output file name - let output_path = if let Some(output) = output_file { - output.clone() - } else { - // Generate default output name - let input_path = std::path::Path::new(filename); - let stem = input_path.file_stem().unwrap_or_default().to_string_lossy(); - if cfg!(windows) { - format!("{}.exe", stem) - } else { - stem.to_string() - } - }; - - println!("📦 Compiling to AOT executable: {}", output_path); - - match aot_backend.compile_to_executable(compile_result.module, &output_path) { - Ok(()) => { - println!("✅ AOT compilation completed successfully!"); - - // Show statistics - let stats = aot_backend.get_stats(); - println!("📊 Compilation Statistics:"); - println!(" WASM size: {} bytes", stats.wasm_size); - println!(" Precompiled size: {} bytes", stats.precompiled_size); - println!(" Compilation time: {}ms", stats.compilation_time_ms); - println!(" Optimization level: {}", stats.optimization_level); - - if stats.wasm_size > 0 { - let ratio = stats.precompiled_size as f64 / stats.wasm_size as f64; - println!(" Size ratio: {:.2}x", ratio); - } - - println!("📄 AOT precompiled module written to: {}.cwasm", output_path); - println!("🚀 This creates a precompiled WASM module for faster loading"); - }, - Err(e) => { - eprintln!("❌ AOT compilation error: {}", e); - process::exit(1); - } - } -} - -/// Execute benchmark mode -fn execute_benchmark_mode(iterations: u32) { - use nyash_rust::benchmarks::BenchmarkSuite; - - let suite = BenchmarkSuite::new(iterations); - let results = suite.run_all(); - - if results.is_empty() { - println!("❌ No benchmark results - make sure benchmark files exist in benchmarks/ directory"); - println!(" Expected files:"); - println!(" - benchmarks/bench_light.nyash"); - println!(" - benchmarks/bench_medium.nyash"); - println!(" - benchmarks/bench_heavy.nyash"); - process::exit(1); - } - - suite.print_results(&results); + // Create and run the execution coordinator + let runner = NyashRunner::new(config); + runner.run(); } #[cfg(test)] mod tests { use super::*; + use box_trait::{StringBox, BoxCore}; #[test] fn test_main_functionality() { - // This test ensures main() doesn't panic - // In a real implementation, we'd have more comprehensive tests - let string_box = StringBox::new("test"); - assert_eq!(string_box.type_name(), "StringBox"); + // This test ensures the module structure is correct + let string_box = StringBox::new("test".to_string()); assert_eq!(string_box.to_string_box().value, "test"); } } diff --git a/src/runner.rs b/src/runner.rs new file mode 100644 index 00000000..3b211dd7 --- /dev/null +++ b/src/runner.rs @@ -0,0 +1,711 @@ +/*! + * Execution Runner Module - Nyash File and Mode Execution Coordinator + * + * This module handles all execution logic, backend selection, and mode coordination, + * separated from CLI parsing and the main entry point. + */ + +use crate::cli::CliConfig; +use crate::{ + box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, AddBox, BoxCore}, + tokenizer::{NyashTokenizer}, + ast::ASTNode, + parser::NyashParser, + interpreter::NyashInterpreter, + mir::{MirCompiler, MirPrinter}, + backend::{VM, wasm::WasmBackend, aot::AotBackend}, +}; +use std::{fs, process}; + +/// Main execution coordinator +pub struct NyashRunner { + config: CliConfig, +} + +impl NyashRunner { + /// Create a new runner with the given configuration + pub fn new(config: CliConfig) -> Self { + Self { config } + } + + /// Run Nyash based on the configuration + pub fn run(&self) { + // Benchmark mode - can run without a file + if self.config.benchmark { + println!("📊 Nyash Performance Benchmark Suite"); + println!("===================================="); + println!("Running {} iterations per test...", self.config.iterations); + println!(); + + self.execute_benchmark_mode(); + return; + } + + if let Some(ref filename) = self.config.file { + self.execute_file_mode(filename); + } else { + self.execute_demo_mode(); + } + } + + /// Execute file-based mode with backend selection + fn execute_file_mode(&self, filename: &str) { + if self.config.dump_mir || self.config.verify_mir { + println!("🚀 Nyash MIR Compiler - Processing file: {} 🚀", filename); + self.execute_mir_mode(filename); + } else if self.config.compile_wasm { + println!("🌐 Nyash WASM Compiler - Processing file: {} 🌐", filename); + self.execute_wasm_mode(filename); + } else if self.config.compile_native { + println!("🚀 Nyash AOT Compiler - Processing file: {} 🚀", filename); + self.execute_aot_mode(filename); + } else if self.config.backend == "vm" { + println!("🚀 Nyash VM Backend - Executing file: {} 🚀", filename); + self.execute_vm_mode(filename); + } else { + println!("🦀 Nyash Rust Implementation - Executing file: {} 🦀", filename); + if let Some(fuel) = self.config.debug_fuel { + println!("🔥 Debug fuel limit: {} iterations", fuel); + } else { + println!("🔥 Debug fuel limit: unlimited"); + } + println!("===================================================="); + + self.execute_nyash_file(filename); + } + } + + /// Execute demo mode with all demonstrations + fn execute_demo_mode(&self) { + println!("🦀 Nyash Rust Implementation - Everything is Box! 🦀"); + println!("===================================================="); + + // Demonstrate basic Box creation and operations + demo_basic_boxes(); + + // Demonstrate Box operations + demo_box_operations(); + + // Demonstrate Box collections + demo_box_collections(); + + // Demonstrate Environment & Scope management + demo_environment_system(); + + // Demonstrate Tokenizer system + demo_tokenizer_system(); + + // Demonstrate Parser system + demo_parser_system(); + + // Demonstrate Interpreter system + demo_interpreter_system(); + + println!("\n🎉 All Box operations completed successfully!"); + println!("Memory safety guaranteed by Rust's borrow checker! 🛡️"); + } + + /// Execute Nyash file with interpreter + fn execute_nyash_file(&self, filename: &str) { + // Read the file + let code = match fs::read_to_string(filename) { + Ok(content) => content, + Err(e) => { + eprintln!("❌ Error reading file {}: {}", filename, e); + process::exit(1); + } + }; + + println!("📝 File contents:\n{}", code); + println!("\n🚀 Parsing and executing...\n"); + + // Test: immediate file creation + std::fs::write("/mnt/c/git/nyash/development/debug_hang_issue/test.txt", "START").ok(); + + // Parse the code with debug fuel limit + eprintln!("🔍 DEBUG: Starting parse with fuel: {:?}...", self.config.debug_fuel); + let ast = match NyashParser::parse_from_string_with_fuel(&code, self.config.debug_fuel) { + Ok(ast) => { + eprintln!("🔍 DEBUG: Parse completed, AST created"); + ast + }, + Err(e) => { + eprintln!("❌ Parse error: {}", e); + process::exit(1); + } + }; + + eprintln!("🔍 DEBUG: About to print parse success message..."); + println!("✅ Parse successful!"); + eprintln!("🔍 DEBUG: Parse success message printed"); + + // Debug log file write + if let Ok(mut file) = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open("/mnt/c/git/nyash/development/debug_hang_issue/debug_trace.log") + { + use std::io::Write; + let _ = writeln!(file, "=== MAIN: Parse successful ==="); + let _ = file.flush(); + } + + eprintln!("🔍 DEBUG: Creating interpreter..."); + + // Execute the AST + let mut interpreter = NyashInterpreter::new(); + eprintln!("🔍 DEBUG: Starting execution..."); + match interpreter.execute(ast) { + Ok(result) => { + println!("✅ Execution completed successfully!"); + println!("Result: {}", result.to_string_box().value); + }, + Err(e) => { + // Use enhanced error reporting with source context + eprintln!("❌ Runtime error:\n{}", e.detailed_message(Some(&code))); + process::exit(1); + } + } + } + + /// Execute MIR compilation and processing mode + fn execute_mir_mode(&self, filename: &str) { + // Read the file + let code = match fs::read_to_string(filename) { + Ok(content) => content, + Err(e) => { + eprintln!("❌ Error reading file {}: {}", filename, e); + process::exit(1); + } + }; + + // Parse to AST + let ast = match NyashParser::parse_from_string(&code) { + Ok(ast) => ast, + Err(e) => { + eprintln!("❌ Parse error: {}", e); + process::exit(1); + } + }; + + // Compile to MIR + let mut mir_compiler = MirCompiler::new(); + let compile_result = match mir_compiler.compile(ast) { + Ok(result) => result, + Err(e) => { + eprintln!("❌ MIR compilation error: {}", e); + process::exit(1); + } + }; + + // Verify MIR if requested + if self.config.verify_mir { + println!("🔍 Verifying MIR..."); + match &compile_result.verification_result { + Ok(()) => println!("✅ MIR verification passed!"), + Err(errors) => { + eprintln!("❌ MIR verification failed:"); + for error in errors { + eprintln!(" • {}", error); + } + process::exit(1); + } + } + } + + // Dump MIR if requested + if self.config.dump_mir { + let mut printer = if self.config.mir_verbose { + MirPrinter::verbose() + } else { + MirPrinter::new() + }; + + println!("🚀 MIR Output for {}:", filename); + println!("{}", printer.print_module(&compile_result.module)); + } + } + + /// Execute VM mode + fn execute_vm_mode(&self, filename: &str) { + // Read the file + let code = match fs::read_to_string(filename) { + Ok(content) => content, + Err(e) => { + eprintln!("❌ Error reading file {}: {}", filename, e); + process::exit(1); + } + }; + + // Parse to AST + let ast = match NyashParser::parse_from_string(&code) { + Ok(ast) => ast, + Err(e) => { + eprintln!("❌ Parse error: {}", e); + process::exit(1); + } + }; + + // Compile to MIR + let mut mir_compiler = MirCompiler::new(); + let compile_result = match mir_compiler.compile(ast) { + Ok(result) => result, + Err(e) => { + eprintln!("❌ MIR compilation error: {}", e); + process::exit(1); + } + }; + + // Execute with VM + let mut vm = VM::new(); + match vm.execute_module(&compile_result.module) { + Ok(result) => { + println!("✅ VM execution completed successfully!"); + println!("Result: {:?}", result); + }, + Err(e) => { + eprintln!("❌ VM execution error: {}", e); + process::exit(1); + } + } + } + + /// Execute WASM compilation mode + fn execute_wasm_mode(&self, filename: &str) { + // Read the file + let code = match fs::read_to_string(filename) { + Ok(content) => content, + Err(e) => { + eprintln!("❌ Error reading file {}: {}", filename, e); + process::exit(1); + } + }; + + // Parse to AST + let ast = match NyashParser::parse_from_string(&code) { + Ok(ast) => ast, + Err(e) => { + eprintln!("❌ Parse error: {}", e); + process::exit(1); + } + }; + + // Compile to MIR + let mut mir_compiler = MirCompiler::new(); + let compile_result = match mir_compiler.compile(ast) { + Ok(result) => result, + Err(e) => { + eprintln!("❌ MIR compilation error: {}", e); + process::exit(1); + } + }; + + // Compile to WASM + let mut wasm_backend = WasmBackend::new(); + let wasm_code = match wasm_backend.compile_module(compile_result.module) { + Ok(wasm) => wasm, + Err(e) => { + eprintln!("❌ WASM compilation error: {}", e); + process::exit(1); + } + }; + + // Determine output file + let output = self.config.output_file.as_deref() + .unwrap_or_else(|| { + if filename.ends_with(".nyash") { + filename.strip_suffix(".nyash").unwrap_or(filename) + } else { + filename + } + }); + let output_file = format!("{}.wat", output); + + // Write WASM output + let output_str = match std::str::from_utf8(&wasm_code) { + Ok(s) => s, + Err(_) => { + eprintln!("❌ Generated WASM is not valid UTF-8"); + process::exit(1); + } + }; + + match fs::write(&output_file, output_str) { + Ok(()) => { + println!("✅ WASM compilation successful!"); + println!("Output written to: {}", output_file); + }, + Err(e) => { + eprintln!("❌ Error writing WASM file {}: {}", output_file, e); + process::exit(1); + } + } + } + + /// Execute AOT compilation mode + fn execute_aot_mode(&self, filename: &str) { + // Read the file + let code = match fs::read_to_string(filename) { + Ok(content) => content, + Err(e) => { + eprintln!("❌ Error reading file {}: {}", filename, e); + process::exit(1); + } + }; + + // Parse to AST + let ast = match NyashParser::parse_from_string(&code) { + Ok(ast) => ast, + Err(e) => { + eprintln!("❌ Parse error: {}", e); + process::exit(1); + } + }; + + // Compile to MIR + let mut mir_compiler = MirCompiler::new(); + let compile_result = match mir_compiler.compile(ast) { + Ok(result) => result, + Err(e) => { + eprintln!("❌ MIR compilation error: {}", e); + process::exit(1); + } + }; + + // Compile via AOT backend + let mut aot_backend = match AotBackend::new() { + Ok(backend) => backend, + Err(e) => { + eprintln!("❌ Failed to create AOT backend: {}", e); + process::exit(1); + } + }; + + let output = self.config.output_file.as_deref() + .unwrap_or_else(|| { + if filename.ends_with(".nyash") { + filename.strip_suffix(".nyash").unwrap_or(filename) + } else { + filename + } + }); + + match aot_backend.compile_to_executable(compile_result.module, output) { + Ok(()) => { + println!("✅ AOT compilation successful!"); + println!("Executable written to: {}", output); + }, + Err(e) => { + eprintln!("❌ AOT compilation error: {}", e); + process::exit(1); + } + } + } + + /// Execute benchmark mode + fn execute_benchmark_mode(&self) { + println!("🏁 Running benchmark mode with {} iterations", self.config.iterations); + + // Simple benchmark test file + let test_code = r#" + local x + x = 42 + local y + y = x + 58 + return y + "#; + + println!("\n🧪 Test code:"); + println!("{}", test_code); + + // Benchmark interpreter + println!("\n⚡ Interpreter Backend:"); + let start = std::time::Instant::now(); + for _ in 0..self.config.iterations { + if let Ok(ast) = NyashParser::parse_from_string(test_code) { + let mut interpreter = NyashInterpreter::new(); + let _ = interpreter.execute(ast); + } + } + let interpreter_time = start.elapsed(); + println!(" {} iterations in {:?} ({:.2} ops/sec)", + self.config.iterations, interpreter_time, + self.config.iterations as f64 / interpreter_time.as_secs_f64()); + + // Benchmark VM if available + println!("\n🚀 VM Backend:"); + let start = std::time::Instant::now(); + for _ in 0..self.config.iterations { + if let Ok(ast) = NyashParser::parse_from_string(test_code) { + let mut mir_compiler = MirCompiler::new(); + if let Ok(compile_result) = mir_compiler.compile(ast) { + let mut vm = VM::new(); + let _ = vm.execute_module(&compile_result.module); + } + } + } + let vm_time = start.elapsed(); + println!(" {} iterations in {:?} ({:.2} ops/sec)", + self.config.iterations, vm_time, + self.config.iterations as f64 / vm_time.as_secs_f64()); + + // Performance comparison + let speedup = interpreter_time.as_secs_f64() / vm_time.as_secs_f64(); + println!("\n📊 Performance Summary:"); + println!(" VM is {:.2}x {} than Interpreter", + if speedup > 1.0 { speedup } else { 1.0 / speedup }, + if speedup > 1.0 { "faster" } else { "slower" }); + } +} + +// Demo functions (moved from main.rs) +fn demo_basic_boxes() { + println!("\n📦 1. Basic Box Creation:"); + + // Create different types of boxes + let string_box = StringBox::new("Hello, Nyash!".to_string()); + let int_box = IntegerBox::new(42); + let bool_box = BoolBox::new(true); + let void_box = VoidBox::new(); + + println!(" StringBox: {}", string_box.to_string_box().value); + println!(" IntegerBox: {}", int_box.to_string_box().value); + println!(" BoolBox: {}", bool_box.to_string_box().value); + println!(" VoidBox: {}", void_box.to_string_box().value); + + // Show unique IDs + println!(" Box IDs: String={}, Integer={}, Bool={}, Void={}", + string_box.box_id(), int_box.box_id(), bool_box.box_id(), void_box.box_id()); +} + +fn demo_box_operations() { + println!("\n🔄 2. Box Operations:"); + + // Addition between boxes + let left = IntegerBox::new(10); + let right = IntegerBox::new(32); + let add_box = AddBox::new(Box::new(left), Box::new(right)); + + println!(" 10 + 32 = {}", add_box.to_string_box().value); + + // String concatenation + let str1 = StringBox::new("Hello, ".to_string()); + let str2 = StringBox::new("World!".to_string()); + let concat_box = AddBox::new(Box::new(str1), Box::new(str2)); + + println!(" \"Hello, \" + \"World!\" = {}", concat_box.to_string_box().value); +} + +fn demo_box_collections() { + println!("\n📚 3. Box Collections:"); + + // This would be expanded when ArrayBox is implemented + println!(" Box collections functionality placeholder"); + println!(" (ArrayBox and other collection types will be demonstrated here)"); +} + +fn demo_environment_system() { + println!("\n🌍 4. Environment & Scope Management:"); + println!(" Environment demo placeholder - full testing done in interpreter"); +} + +fn demo_tokenizer_system() { + println!("\n🔤 5. Tokenizer System:"); + + // Test code to tokenize + let test_code = "x = 42 + y"; + println!(" Input: {}", test_code); + + // Tokenize the code + let mut tokenizer = NyashTokenizer::new(test_code); + + match tokenizer.tokenize() { + Ok(tokens) => { + println!(" Tokenized {} tokens successfully", tokens.len()); + }, + Err(e) => println!(" Tokenization error: {}", e), + } +} + +fn demo_parser_system() { + println!("\n🌳 6. Parser & AST System:"); + + // Test simple box declaration + println!(" 📝 Simple Box Declaration Test:"); + let simple_code = r#" + box TestBox { + value + + getValue() { + return this.value + } + } + "#; + + match NyashParser::parse_from_string(simple_code) { + Ok(ast) => { + println!(" Input: {}", simple_code.trim()); + println!(" AST: {}", ast); + + if let ASTNode::Program { statements, .. } = &ast { + println!(" Program has {} statements", statements.len()); + for (i, stmt) in statements.iter().enumerate() { + println!(" [{}] {}", i, stmt.info()); + } + } + } + Err(e) => println!(" Error: {}", e), + } + + // Test assignment and method call + println!("\n 🚀 Assignment & Method Call Test:"); + let assignment_code = r#" + obj = new TestBox() + obj.value = "test123" + print("Direct field: " + obj.value) + print("Method call: " + obj.getValue()) + "#; + + match NyashParser::parse_from_string(assignment_code) { + Ok(ast) => { + println!(" Successfully parsed assignment & method call code"); + + if let ASTNode::Program { statements, .. } = &ast { + println!(" Parsed {} statements:", statements.len()); + for (i, stmt) in statements.iter().enumerate() { + println!(" [{}] {} ({})", i, stmt.info(), stmt.node_type()); + } + } + } + Err(e) => println!(" Error: {}", e), + } + + // Test expression parsing + println!("\n ⚡ Expression Parsing Test:"); + let expr_code = r#" + result = x + y * z + condition = a == b && c < d + "#; + + match NyashParser::parse_from_string(expr_code) { + Ok(ast) => { + println!(" Successfully parsed complex expressions"); + + if let ASTNode::Program { statements, .. } = &ast { + for (i, stmt) in statements.iter().enumerate() { + if let ASTNode::Assignment { target, value, .. } = stmt { + println!(" Assignment [{}]: {} = {}", i, target.info(), value.info()); + } + } + } + } + Err(e) => println!(" Error: {}", e), + } + + // Test control structures + println!("\n 🔄 Control Structure Test:"); + let control_code = r#" + if condition { + print("True branch") + } else { + print("False branch") + } + + loop { + print("Loop body") + return + } + "#; + + match NyashParser::parse_from_string(control_code) { + Ok(ast) => { + println!(" Successfully parsed control structures"); + + if let ASTNode::Program { statements, .. } = &ast { + for (i, stmt) in statements.iter().enumerate() { + println!(" [{}] {} ({})", i, stmt.info(), stmt.node_type()); + } + } + } + Err(e) => println!(" Error: {}", e), + } +} + +fn demo_interpreter_system() { + println!("\n🎭 7. Interpreter System:"); + + // Simple execution test + let simple_code = r#" + local x + x = 42 + return x + "#; + + println!(" 📝 Simple Variable Test:"); + println!(" Code: {}", simple_code.trim()); + + match NyashParser::parse_from_string(simple_code) { + Ok(ast) => { + let mut interpreter = NyashInterpreter::new(); + match interpreter.execute(ast) { + Ok(result) => { + println!(" ✅ Result: {}", result.to_string_box().value); + }, + Err(e) => { + println!(" ❌ Execution error: {}", e); + } + } + } + Err(e) => println!(" ❌ Parse error: {}", e), + } + + // Expression evaluation test + let expr_code = r#" + local result + result = 10 + 32 + return result + "#; + + println!("\n ⚡ Expression Evaluation Test:"); + println!(" Code: {}", expr_code.trim()); + + match NyashParser::parse_from_string(expr_code) { + Ok(ast) => { + let mut interpreter = NyashInterpreter::new(); + match interpreter.execute(ast) { + Ok(result) => { + println!(" ✅ Result: {}", result.to_string_box().value); + }, + Err(e) => { + println!(" ❌ Execution error: {}", e); + } + } + } + Err(e) => println!(" ❌ Parse error: {}", e), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_runner_creation() { + let config = CliConfig { + file: None, + debug_fuel: Some(100000), + dump_mir: false, + verify_mir: false, + mir_verbose: false, + backend: "interpreter".to_string(), + compile_wasm: false, + compile_native: false, + output_file: None, + benchmark: false, + iterations: 10, + }; + + let runner = NyashRunner::new(config); + assert_eq!(runner.config.backend, "interpreter"); + } +} \ No newline at end of file