Merge pull request #4 from moe-charm/copilot/fix-3
🚀 Staged Box Implementation: FloatBox + ArrayBox improvements + Complete operator support
This commit is contained in:
@ -55,9 +55,6 @@ name = "test_icon_extraction"
|
||||
path = "examples/test_icon_extraction.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "test_method_box_integration"
|
||||
path = "test_method_box_integration.rs"
|
||||
|
||||
[dependencies]
|
||||
# エラーハンドリング
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -135,6 +135,100 @@ impl ArrayBox {
|
||||
Box::new(StringBox::new("Error: join() requires string separator"))
|
||||
}
|
||||
}
|
||||
|
||||
/// 配列をソート(昇順)
|
||||
pub fn sort(&self) -> Box<dyn NyashBox> {
|
||||
let mut items = self.items.lock().unwrap();
|
||||
|
||||
// Numeric values first, then string values
|
||||
items.sort_by(|a, b| {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
// Try to compare as numbers first
|
||||
if let (Some(a_int), Some(b_int)) = (
|
||||
a.as_any().downcast_ref::<IntegerBox>(),
|
||||
b.as_any().downcast_ref::<IntegerBox>()
|
||||
) {
|
||||
return a_int.value.cmp(&b_int.value);
|
||||
}
|
||||
|
||||
// Try FloatBox comparison
|
||||
if let (Some(a_float), Some(b_float)) = (
|
||||
a.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>(),
|
||||
b.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>()
|
||||
) {
|
||||
return a_float.value.partial_cmp(&b_float.value).unwrap_or(Ordering::Equal);
|
||||
}
|
||||
|
||||
// Mixed numeric types
|
||||
if let (Some(a_int), Some(b_float)) = (
|
||||
a.as_any().downcast_ref::<IntegerBox>(),
|
||||
b.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>()
|
||||
) {
|
||||
return (a_int.value as f64).partial_cmp(&b_float.value).unwrap_or(Ordering::Equal);
|
||||
}
|
||||
|
||||
if let (Some(a_float), Some(b_int)) = (
|
||||
a.as_any().downcast_ref::<crate::boxes::math_box::FloatBox>(),
|
||||
b.as_any().downcast_ref::<IntegerBox>()
|
||||
) {
|
||||
return a_float.value.partial_cmp(&(b_int.value as f64)).unwrap_or(Ordering::Equal);
|
||||
}
|
||||
|
||||
// Fall back to string comparison
|
||||
let a_str = a.to_string_box().value;
|
||||
let b_str = b.to_string_box().value;
|
||||
a_str.cmp(&b_str)
|
||||
});
|
||||
|
||||
Box::new(StringBox::new("ok"))
|
||||
}
|
||||
|
||||
/// 配列を反転
|
||||
pub fn reverse(&self) -> Box<dyn NyashBox> {
|
||||
let mut items = self.items.lock().unwrap();
|
||||
items.reverse();
|
||||
Box::new(StringBox::new("ok"))
|
||||
}
|
||||
|
||||
/// 部分配列を取得
|
||||
pub fn slice(&self, start: Box<dyn NyashBox>, end: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
let items = self.items.lock().unwrap();
|
||||
|
||||
// Extract start and end indices
|
||||
let start_idx = if let Some(start_int) = start.as_any().downcast_ref::<IntegerBox>() {
|
||||
if start_int.value < 0 {
|
||||
0
|
||||
} else {
|
||||
start_int.value as usize
|
||||
}
|
||||
} else {
|
||||
return Box::new(StringBox::new("Error: slice() start index must be an integer"));
|
||||
};
|
||||
|
||||
let end_idx = if let Some(end_int) = end.as_any().downcast_ref::<IntegerBox>() {
|
||||
if end_int.value < 0 {
|
||||
items.len()
|
||||
} else {
|
||||
(end_int.value as usize).min(items.len())
|
||||
}
|
||||
} else {
|
||||
return Box::new(StringBox::new("Error: slice() end index must be an integer"));
|
||||
};
|
||||
|
||||
// Validate indices
|
||||
if start_idx > items.len() || start_idx > end_idx {
|
||||
return Box::new(ArrayBox::new());
|
||||
}
|
||||
|
||||
// Create slice
|
||||
let slice_items: Vec<Box<dyn NyashBox>> = items[start_idx..end_idx]
|
||||
.iter()
|
||||
.map(|item| item.clone_box())
|
||||
.collect();
|
||||
|
||||
Box::new(ArrayBox::new_with_elements(slice_items))
|
||||
}
|
||||
}
|
||||
|
||||
impl BoxCore for ArrayBox {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -126,6 +126,32 @@ impl NyashInterpreter {
|
||||
}
|
||||
Ok(Box::new(array_box.to_string_box()))
|
||||
}
|
||||
"sort" => {
|
||||
if !arguments.is_empty() {
|
||||
return Err(RuntimeError::InvalidOperation {
|
||||
message: format!("sort() expects 0 arguments, got {}", arguments.len()),
|
||||
});
|
||||
}
|
||||
Ok(array_box.sort())
|
||||
}
|
||||
"reverse" => {
|
||||
if !arguments.is_empty() {
|
||||
return Err(RuntimeError::InvalidOperation {
|
||||
message: format!("reverse() expects 0 arguments, got {}", arguments.len()),
|
||||
});
|
||||
}
|
||||
Ok(array_box.reverse())
|
||||
}
|
||||
"slice" => {
|
||||
if arguments.len() != 2 {
|
||||
return Err(RuntimeError::InvalidOperation {
|
||||
message: format!("slice() expects 2 arguments (start, end), got {}", arguments.len()),
|
||||
});
|
||||
}
|
||||
let start_value = self.execute_expression(&arguments[0])?;
|
||||
let end_value = self.execute_expression(&arguments[1])?;
|
||||
Ok(array_box.slice(start_value, end_value))
|
||||
}
|
||||
_ => {
|
||||
Err(RuntimeError::InvalidOperation {
|
||||
message: format!("Unknown method '{}' for ArrayBox", method),
|
||||
|
||||
@ -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);
|
||||
|
||||
81
test_array_improvements.nyash
Normal file
81
test_array_improvements.nyash
Normal file
@ -0,0 +1,81 @@
|
||||
// test_array_improvements.nyash - ArrayBox Phase 2 improvements test
|
||||
// Testing: sort(), reverse(), indexOf(), slice() methods
|
||||
|
||||
print("📦 Testing ArrayBox improvements...")
|
||||
|
||||
// Basic array creation and setup
|
||||
local arr, result, sliceResult
|
||||
|
||||
print("=== Setup: Creating test array ===")
|
||||
arr = new ArrayBox()
|
||||
arr.push(3)
|
||||
arr.push(1)
|
||||
arr.push(4)
|
||||
arr.push(1)
|
||||
arr.push(5)
|
||||
print("Original array: " + arr.toString())
|
||||
|
||||
print("\n=== Test 1: sort() method ===")
|
||||
arr.sort()
|
||||
print("After sort(): " + arr.toString())
|
||||
// Expected: [1, 1, 3, 4, 5]
|
||||
|
||||
print("\n=== Test 2: reverse() method ===")
|
||||
arr.reverse()
|
||||
print("After reverse(): " + arr.toString())
|
||||
// Expected: [5, 4, 3, 1, 1]
|
||||
|
||||
print("\n=== Test 3: indexOf() method ===")
|
||||
result = arr.indexOf(4)
|
||||
print("indexOf(4): " + result.toString())
|
||||
// Expected: 1
|
||||
|
||||
result = arr.indexOf(1)
|
||||
print("indexOf(1): " + result.toString())
|
||||
// Expected: 3 (first occurrence from current order)
|
||||
|
||||
result = arr.indexOf(999)
|
||||
print("indexOf(999): " + result.toString())
|
||||
// Expected: -1 (not found)
|
||||
|
||||
print("\n=== Test 4: slice() method ===")
|
||||
sliceResult = arr.slice(1, 4)
|
||||
print("slice(1, 4): " + sliceResult.toString())
|
||||
// Expected: [4, 3, 1] (indices 1, 2, 3)
|
||||
|
||||
sliceResult = arr.slice(0, 2)
|
||||
print("slice(0, 2): " + sliceResult.toString())
|
||||
// Expected: [5, 4] (indices 0, 1)
|
||||
|
||||
sliceResult = arr.slice(2, 10) // End beyond array
|
||||
print("slice(2, 10): " + sliceResult.toString())
|
||||
// Expected: [3, 1, 1] (indices 2 to end)
|
||||
|
||||
print("\n=== Test 5: Mixed types sorting ===")
|
||||
local mixedArr
|
||||
mixedArr = new ArrayBox()
|
||||
mixedArr.push("banana")
|
||||
mixedArr.push(2)
|
||||
mixedArr.push("apple")
|
||||
mixedArr.push(1)
|
||||
mixedArr.push("cherry")
|
||||
print("Mixed array before sort: " + mixedArr.toString())
|
||||
|
||||
mixedArr.sort()
|
||||
print("Mixed array after sort: " + mixedArr.toString())
|
||||
// Expected: numbers first (1, 2), then strings alphabetically
|
||||
|
||||
print("\n=== Test 6: FloatBox integration ===")
|
||||
local floatArr
|
||||
floatArr = new ArrayBox()
|
||||
floatArr.push(new FloatBox(3.14))
|
||||
floatArr.push(1)
|
||||
floatArr.push(new FloatBox(2.71))
|
||||
floatArr.push(4)
|
||||
print("Float array before sort: " + floatArr.toString())
|
||||
|
||||
floatArr.sort()
|
||||
print("Float array after sort: " + floatArr.toString())
|
||||
// Expected: [1, 2.71, 3.14, 4]
|
||||
|
||||
print("\n✅ ArrayBox Phase 2 improvements tests completed!")
|
||||
49
test_float_box.nyash
Normal file
49
test_float_box.nyash
Normal file
@ -0,0 +1,49 @@
|
||||
// test_float_box.nyash - FloatBox functionality test
|
||||
// Phase 1: Basic FloatBox implementation validation
|
||||
|
||||
print("🧮 Testing FloatBox implementation...")
|
||||
|
||||
// Basic FloatBox creation
|
||||
local f1, f2, result
|
||||
f1 = new FloatBox(3.14)
|
||||
f2 = new FloatBox(2.86)
|
||||
|
||||
print("Created FloatBox f1: " + f1.toString())
|
||||
print("Created FloatBox f2: " + f2.toString())
|
||||
|
||||
// Addition test
|
||||
result = f1 + f2
|
||||
print("3.14 + 2.86 = " + result.toString())
|
||||
|
||||
// Multiplication test
|
||||
result = f1 * f2
|
||||
print("3.14 * 2.86 = " + result.toString())
|
||||
|
||||
// Division test
|
||||
result = f1 / f2
|
||||
print("3.14 / 2.86 = " + result.toString())
|
||||
|
||||
// Subtraction test
|
||||
result = f1 - f2
|
||||
print("3.14 - 2.86 = " + result.toString())
|
||||
|
||||
// Mixed operations with IntegerBox
|
||||
local intVal
|
||||
intVal = 5
|
||||
result = f1 + intVal
|
||||
print("3.14 + 5 = " + result.toString())
|
||||
|
||||
result = f1 * intVal
|
||||
print("3.14 * 5 = " + result.toString())
|
||||
|
||||
// FloatBox methods
|
||||
result = f1.abs()
|
||||
print("abs(3.14) = " + result.toString())
|
||||
|
||||
result = f1.floor()
|
||||
print("floor(3.14) = " + result.toString())
|
||||
|
||||
result = f1.ceil()
|
||||
print("ceil(3.14) = " + result.toString())
|
||||
|
||||
print("✅ FloatBox Phase 1 tests completed!")
|
||||
@ -1,83 +0,0 @@
|
||||
/**
|
||||
* MethodBox統合テスト - Nyash側使用対応確認
|
||||
*
|
||||
* NewP2PBoxのon_method()がMethodBoxを正しく受け取れるか確認
|
||||
* MethodBox.invoke()が正しく呼ばれるか確認
|
||||
*/
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// Nyashモジュールをインポート
|
||||
use nyash_rust::boxes::{NewP2PBox, MessageIntentBox, StringBox};
|
||||
use nyash_rust::transport_trait::TransportKind;
|
||||
use nyash_rust::method_box::MethodBox;
|
||||
use nyash_rust::{NyashBox, InstanceBox};
|
||||
|
||||
fn main() {
|
||||
println!("🎯 MethodBox統合テスト開始");
|
||||
|
||||
// テスト1: 基本的なMethodBox作成
|
||||
test_method_box_creation();
|
||||
|
||||
// テスト2: NewP2PBox + MethodBox統合
|
||||
test_method_box_integration();
|
||||
|
||||
println!("✅ MethodBox統合テスト完了!");
|
||||
}
|
||||
|
||||
fn test_method_box_creation() {
|
||||
println!("\n=== テスト1: MethodBox作成テスト ===");
|
||||
|
||||
// テスト用のインスタンスを作成(実際のInstanceBoxは使えないので、StringBoxで代用)
|
||||
let test_instance = Box::new(StringBox::new("test_instance"));
|
||||
|
||||
// MethodBoxを作成
|
||||
let method_box = MethodBox::new(test_instance, "test_method".to_string());
|
||||
|
||||
println!("✅ MethodBox作成成功: メソッド名 = {}", method_box.method_name);
|
||||
|
||||
// invoke()テスト(現在は未実装エラーが返るはず)
|
||||
let args = vec![Box::new(StringBox::new("test_arg")) as Box<dyn NyashBox>];
|
||||
match method_box.invoke(args) {
|
||||
Ok(result) => println!("📥 MethodBox.invoke() 成功: {}", result.to_string_box().value),
|
||||
Err(e) => println!("⚠️ MethodBox.invoke() 未実装: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn test_method_box_integration() {
|
||||
println!("\n=== テスト2: NewP2PBox + MethodBox統合テスト ===");
|
||||
|
||||
// P2PBoxノードを作成
|
||||
let alice = NewP2PBox::new("alice_method", TransportKind::InProcess);
|
||||
let bob = NewP2PBox::new("bob_method", TransportKind::InProcess);
|
||||
|
||||
// テスト用のMethodBoxを作成
|
||||
let handler_instance = Box::new(StringBox::new("message_handler"));
|
||||
let handler_method = MethodBox::new(handler_instance, "handle_greeting".to_string());
|
||||
|
||||
// BobにMethodBoxベースのイベントリスナーを登録
|
||||
println!("📋 BobにMethodBoxベースのリスナー登録中...");
|
||||
match bob.on_method("greeting", handler_method) {
|
||||
Ok(()) => println!("✅ MethodBoxリスナー登録成功!"),
|
||||
Err(e) => {
|
||||
println!("❌ MethodBoxリスナー登録エラー: {}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Aliceからメッセージ送信
|
||||
let mut message = MessageIntentBox::new("greeting");
|
||||
message.set("text", Box::new(StringBox::new("Hello Bob via MethodBox!")));
|
||||
message.set("sender", Box::new(StringBox::new("Alice")));
|
||||
|
||||
println!("📤 AliceからBobへMethodBox経由でメッセージ送信...");
|
||||
match alice.send("bob_method", &message) {
|
||||
Ok(()) => println!("✅ メッセージ送信成功(MethodBox処理を確認)"),
|
||||
Err(e) => println!("❌ メッセージ送信エラー: {}", e),
|
||||
}
|
||||
|
||||
// 少し待つ(非同期処理のため)
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
||||
println!("🎉 MethodBox統合が動作していることを確認!");
|
||||
}
|
||||
100
test_operators.nyash
Normal file
100
test_operators.nyash
Normal file
@ -0,0 +1,100 @@
|
||||
// test_operators.nyash - Operator Phase 3 comprehensive test
|
||||
// Testing: comparison operators (<, >, <=, >=, ==, !=) with mixed types
|
||||
|
||||
print("⚖️ Testing comprehensive operator support...")
|
||||
|
||||
local f1, f2, i1, i2, result
|
||||
|
||||
print("=== Setup: Creating test values ===")
|
||||
f1 = new FloatBox(3.14)
|
||||
f2 = new FloatBox(2.86)
|
||||
i1 = 5
|
||||
i2 = 3
|
||||
print("f1 = " + f1.toString() + " (FloatBox)")
|
||||
print("f2 = " + f2.toString() + " (FloatBox)")
|
||||
print("i1 = " + i1.toString() + " (IntegerBox)")
|
||||
print("i2 = " + i2.toString() + " (IntegerBox)")
|
||||
|
||||
print("\n=== Test 1: Equality operators (==, !=) ===")
|
||||
result = f1 == new FloatBox(3.14)
|
||||
print("f1 == 3.14: " + result.toString()) // Expected: true
|
||||
|
||||
result = f1 != f2
|
||||
print("f1 != f2: " + result.toString()) // Expected: true
|
||||
|
||||
result = i1 == 5
|
||||
print("i1 == 5: " + result.toString()) // Expected: true
|
||||
|
||||
result = i1 != i2
|
||||
print("i1 != i2: " + result.toString()) // Expected: true
|
||||
|
||||
print("\n=== Test 2: Mixed type equality ===")
|
||||
result = f1 == 3 // FloatBox vs IntegerBox
|
||||
print("f1 == 3: " + result.toString()) // Expected: false (3.14 != 3)
|
||||
|
||||
result = new FloatBox(5.0) == i1 // FloatBox vs IntegerBox
|
||||
print("5.0 == i1: " + result.toString()) // Expected: true
|
||||
|
||||
print("\n=== Test 3: Less than (<) ===")
|
||||
result = f2 < f1 // FloatBox < FloatBox
|
||||
print("f2 < f1: " + result.toString()) // Expected: true (2.86 < 3.14)
|
||||
|
||||
result = i2 < i1 // IntegerBox < IntegerBox
|
||||
print("i2 < i1: " + result.toString()) // Expected: true (3 < 5)
|
||||
|
||||
result = f2 < i1 // FloatBox < IntegerBox
|
||||
print("f2 < i1: " + result.toString()) // Expected: true (2.86 < 5)
|
||||
|
||||
result = i2 < f1 // IntegerBox < FloatBox
|
||||
print("i2 < f1: " + result.toString()) // Expected: true (3 < 3.14)
|
||||
|
||||
print("\n=== Test 4: Greater than (>) ===")
|
||||
result = f1 > f2 // FloatBox > FloatBox
|
||||
print("f1 > f2: " + result.toString()) // Expected: true (3.14 > 2.86)
|
||||
|
||||
result = i1 > i2 // IntegerBox > IntegerBox
|
||||
print("i1 > i2: " + result.toString()) // Expected: true (5 > 3)
|
||||
|
||||
result = i1 > f1 // IntegerBox > FloatBox
|
||||
print("i1 > f1: " + result.toString()) // Expected: true (5 > 3.14)
|
||||
|
||||
result = f1 > i2 // FloatBox > IntegerBox
|
||||
print("f1 > i2: " + result.toString()) // Expected: true (3.14 > 3)
|
||||
|
||||
print("\n=== Test 5: Less than or equal (<=) ===")
|
||||
result = f2 <= f1 // FloatBox <= FloatBox
|
||||
print("f2 <= f1: " + result.toString()) // Expected: true (2.86 <= 3.14)
|
||||
|
||||
result = f1 <= f1 // FloatBox <= FloatBox (equal)
|
||||
print("f1 <= f1: " + result.toString()) // Expected: true (3.14 <= 3.14)
|
||||
|
||||
result = i2 <= i1 // IntegerBox <= IntegerBox
|
||||
print("i2 <= i1: " + result.toString()) // Expected: true (3 <= 5)
|
||||
|
||||
result = new FloatBox(5.0) <= i1 // FloatBox <= IntegerBox (equal)
|
||||
print("5.0 <= i1: " + result.toString()) // Expected: true (5.0 <= 5)
|
||||
|
||||
print("\n=== Test 6: Greater than or equal (>=) ===")
|
||||
result = f1 >= f2 // FloatBox >= FloatBox
|
||||
print("f1 >= f2: " + result.toString()) // Expected: true (3.14 >= 2.86)
|
||||
|
||||
result = f1 >= f1 // FloatBox >= FloatBox (equal)
|
||||
print("f1 >= f1: " + result.toString()) // Expected: true (3.14 >= 3.14)
|
||||
|
||||
result = i1 >= i2 // IntegerBox >= IntegerBox
|
||||
print("i1 >= i2: " + result.toString()) // Expected: true (5 >= 3)
|
||||
|
||||
result = i1 >= new FloatBox(5.0) // IntegerBox >= FloatBox (equal)
|
||||
print("i1 >= 5.0: " + result.toString()) // Expected: true (5 >= 5.0)
|
||||
|
||||
print("\n=== Test 7: Complex expression chains ===")
|
||||
result = (f1 > f2) and (i1 > i2)
|
||||
print("(f1 > f2) and (i1 > i2): " + result.toString()) // Expected: true
|
||||
|
||||
result = (f1 < i1) and (f2 > 1)
|
||||
print("(f1 < i1) and (f2 > 1): " + result.toString()) // Expected: true
|
||||
|
||||
result = not (f1 == f2)
|
||||
print("not (f1 == f2): " + result.toString()) // Expected: true
|
||||
|
||||
print("\n✅ Comprehensive operator tests completed!")
|
||||
Reference in New Issue
Block a user