Phase 1 Complete: FloatBox full implementation with operators and methods

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-11 19:35:25 +00:00
parent 19cfe70df9
commit 93cad22d31
7 changed files with 252 additions and 96 deletions

View File

@ -10,6 +10,7 @@
*/
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox};
use crate::boxes::math_box::FloatBox;
use crate::operator_traits::{
NyashAdd, NyashSub, NyashMul, NyashDiv,
DynamicAdd, DynamicSub, DynamicMul, DynamicDiv,
@ -66,8 +67,10 @@ impl DynamicAdd for IntegerBox {
return Some(Box::new(IntegerBox::new(self.value + other_int.value)));
}
// IntegerBox + FloatBox (if FloatBox exists)
// TODO: Add when FloatBox is properly integrated
// IntegerBox + FloatBox -> FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
return Some(Box::new(FloatBox::new(self.value as f64 + other_float.value)));
}
// Fallback: Convert both to strings and concatenate
// This preserves the existing AddBox behavior
@ -88,8 +91,10 @@ impl DynamicSub for IntegerBox {
return Some(Box::new(IntegerBox::new(self.value - other_int.value)));
}
// IntegerBox - FloatBox (if FloatBox exists)
// TODO: Add when FloatBox is properly integrated
// IntegerBox - FloatBox -> FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
return Some(Box::new(FloatBox::new(self.value as f64 - other_float.value)));
}
None // Subtraction not supported for other types
}
@ -106,6 +111,11 @@ impl DynamicMul for IntegerBox {
return Some(Box::new(IntegerBox::new(self.value * other_int.value)));
}
// IntegerBox * FloatBox -> FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
return Some(Box::new(FloatBox::new(self.value as f64 * other_float.value)));
}
// IntegerBox * StringBox -> Repeated string
if let Some(other_str) = other.as_any().downcast_ref::<StringBox>() {
if self.value >= 0 && self.value <= 10000 { // Safety limit
@ -124,13 +134,20 @@ impl DynamicMul for IntegerBox {
impl DynamicDiv for IntegerBox {
fn try_div(&self, other: &dyn NyashBox) -> Option<Box<dyn NyashBox>> {
// IntegerBox / IntegerBox
// IntegerBox / IntegerBox -> FloatBox (for precision)
if let Some(other_int) = other.as_any().downcast_ref::<IntegerBox>() {
if other_int.value == 0 {
// Return error box or None - for now None
return None;
return None; // Division by zero
}
return Some(Box::new(IntegerBox::new(self.value / other_int.value)));
return Some(Box::new(FloatBox::new(self.value as f64 / other_int.value as f64)));
}
// IntegerBox / FloatBox -> FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
if other_float.value == 0.0 {
return None; // Division by zero
}
return Some(Box::new(FloatBox::new(self.value as f64 / other_float.value)));
}
None
@ -141,6 +158,139 @@ impl DynamicDiv for IntegerBox {
}
}
// ===== FloatBox Operator Implementations =====
/// FloatBox + FloatBox -> FloatBox
impl NyashAdd<FloatBox> for FloatBox {
type Output = FloatBox;
fn add(self, rhs: FloatBox) -> Self::Output {
FloatBox::new(self.value + rhs.value)
}
}
/// FloatBox - FloatBox -> FloatBox
impl NyashSub<FloatBox> for FloatBox {
type Output = FloatBox;
fn sub(self, rhs: FloatBox) -> Self::Output {
FloatBox::new(self.value - rhs.value)
}
}
/// FloatBox * FloatBox -> FloatBox
impl NyashMul<FloatBox> for FloatBox {
type Output = FloatBox;
fn mul(self, rhs: FloatBox) -> Self::Output {
FloatBox::new(self.value * rhs.value)
}
}
/// FloatBox / FloatBox -> FloatBox (with zero check)
impl NyashDiv<FloatBox> for FloatBox {
type Output = Result<FloatBox, OperatorError>;
fn div(self, rhs: FloatBox) -> Self::Output {
if rhs.value == 0.0 {
Err(OperatorError::DivisionByZero)
} else {
Ok(FloatBox::new(self.value / rhs.value))
}
}
}
// ===== FloatBox Dynamic Operator Implementations =====
impl DynamicAdd for FloatBox {
fn try_add(&self, other: &dyn NyashBox) -> Option<Box<dyn NyashBox>> {
// FloatBox + FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
return Some(Box::new(FloatBox::new(self.value + other_float.value)));
}
// FloatBox + IntegerBox -> FloatBox
if let Some(other_int) = other.as_any().downcast_ref::<IntegerBox>() {
return Some(Box::new(FloatBox::new(self.value + other_int.value as f64)));
}
// Fallback: Convert both to strings and concatenate
let left_str = self.to_string_box();
let right_str = other.to_string_box();
Some(Box::new(StringBox::new(format!("{}{}", left_str.value, right_str.value))))
}
fn can_add_with(&self, other_type: &str) -> bool {
matches!(other_type, "FloatBox" | "IntegerBox" | "StringBox")
}
}
impl DynamicSub for FloatBox {
fn try_sub(&self, other: &dyn NyashBox) -> Option<Box<dyn NyashBox>> {
// FloatBox - FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
return Some(Box::new(FloatBox::new(self.value - other_float.value)));
}
// FloatBox - IntegerBox -> FloatBox
if let Some(other_int) = other.as_any().downcast_ref::<IntegerBox>() {
return Some(Box::new(FloatBox::new(self.value - other_int.value as f64)));
}
None // Subtraction not supported for other types
}
fn can_sub_with(&self, other_type: &str) -> bool {
matches!(other_type, "FloatBox" | "IntegerBox")
}
}
impl DynamicMul for FloatBox {
fn try_mul(&self, other: &dyn NyashBox) -> Option<Box<dyn NyashBox>> {
// FloatBox * FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
return Some(Box::new(FloatBox::new(self.value * other_float.value)));
}
// FloatBox * IntegerBox -> FloatBox
if let Some(other_int) = other.as_any().downcast_ref::<IntegerBox>() {
return Some(Box::new(FloatBox::new(self.value * other_int.value as f64)));
}
None
}
fn can_mul_with(&self, other_type: &str) -> bool {
matches!(other_type, "FloatBox" | "IntegerBox")
}
}
impl DynamicDiv for FloatBox {
fn try_div(&self, other: &dyn NyashBox) -> Option<Box<dyn NyashBox>> {
// FloatBox / FloatBox
if let Some(other_float) = other.as_any().downcast_ref::<FloatBox>() {
if other_float.value == 0.0 {
return None; // Division by zero
}
return Some(Box::new(FloatBox::new(self.value / other_float.value)));
}
// FloatBox / IntegerBox -> FloatBox
if let Some(other_int) = other.as_any().downcast_ref::<IntegerBox>() {
if other_int.value == 0 {
return None; // Division by zero
}
return Some(Box::new(FloatBox::new(self.value / other_int.value as f64)));
}
None
}
fn can_div_with(&self, other_type: &str) -> bool {
matches!(other_type, "FloatBox" | "IntegerBox")
}
}
// ===== StringBox Operator Implementations =====
/// StringBox + StringBox -> StringBox (concatenation)

View File

@ -76,7 +76,7 @@ pub mod egui_box;
pub use string_box::StringBox;
pub use integer_box::IntegerBox;
pub use bool_box::BoolBox;
pub use math_box::MathBox;
pub use math_box::{MathBox, FloatBox};
pub use time_box::TimeBox;
pub use debug_box::DebugBox;
pub use random_box::RandomBox;

View File

@ -8,8 +8,9 @@
use super::*;
use crate::ast::UnaryOperator;
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, P2PBox};
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, P2PBox, FloatBox};
use crate::boxes::{MathBox, ConsoleBox, TimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
use crate::box_trait::BoolBox;
use crate::operator_traits::OperatorResolver;
// TODO: Fix NullBox import issue later
// use crate::NullBox;
@ -332,6 +333,21 @@ impl NyashInterpreter {
return self.execute_string_method(string_box, method, arguments);
}
// IntegerBox method calls
if let Some(integer_box) = obj_value.as_any().downcast_ref::<IntegerBox>() {
return self.execute_integer_method(integer_box, method, arguments);
}
// FloatBox method calls
if let Some(float_box) = obj_value.as_any().downcast_ref::<FloatBox>() {
return self.execute_float_method(float_box, method, arguments);
}
// BoolBox method calls
if let Some(bool_box) = obj_value.as_any().downcast_ref::<BoolBox>() {
return self.execute_bool_method(bool_box, method, arguments);
}
// ArrayBox method calls
if let Some(array_box) = obj_value.as_any().downcast_ref::<ArrayBox>() {
return self.execute_array_method(array_box, method, arguments);

View File

@ -122,6 +122,12 @@ impl OperatorResolver {
}
}
if let Some(float_box) = left.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>() {
if let Some(result) = float_box.try_add(right) {
return Ok(result);
}
}
if let Some(bool_box) = left.as_any().downcast_ref::<crate::box_trait::BoolBox>() {
if let Some(result) = bool_box.try_add(right) {
return Ok(result);
@ -148,6 +154,12 @@ impl OperatorResolver {
}
}
if let Some(float_box) = left.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>() {
if let Some(result) = float_box.try_sub(right) {
return Ok(result);
}
}
if let Some(bool_box) = left.as_any().downcast_ref::<crate::box_trait::BoolBox>() {
if let Some(result) = bool_box.try_sub(right) {
return Ok(result);
@ -179,6 +191,12 @@ impl OperatorResolver {
}
}
if let Some(float_box) = left.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>() {
if let Some(result) = float_box.try_mul(right) {
return Ok(result);
}
}
if let Some(bool_box) = left.as_any().downcast_ref::<crate::box_trait::BoolBox>() {
if let Some(result) = bool_box.try_mul(right) {
return Ok(result);
@ -207,6 +225,15 @@ impl OperatorResolver {
}
}
if let Some(float_box) = left.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>() {
if let Some(result) = float_box.try_div(right) {
return Ok(result);
} else {
// If try_div returns None, it might be division by zero
return Err(OperatorError::DivisionByZero);
}
}
if let Some(bool_box) = left.as_any().downcast_ref::<crate::box_trait::BoolBox>() {
if let Some(result) = bool_box.try_div(right) {
return Ok(result);