From c42d27e03137433f4851225e5a450da75087cb3d Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 05:41:16 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Reject=20In?= =?UTF-8?q?teger=20Operands=20for=20Float=20Arithmetic=20and=20Root=20Oper?= =?UTF-8?q?ations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../instructions/math/arithmetic/add_func.rs | 38 +++++++++++++++++ .../instructions/math/arithmetic/div_func.rs | 41 +++++++++++++++++++ .../instructions/math/arithmetic/mod_func.rs | 41 +++++++++++++++++++ .../instructions/math/arithmetic/mul_func.rs | 41 +++++++++++++++++++ .../instructions/math/arithmetic/neg_func.rs | 36 ++++++++++++++++ .../instructions/math/arithmetic/sub_func.rs | 41 +++++++++++++++++++ rust/src/instructions/math/root/cbrt_func.rs | 33 +++++++++++++-- rust/src/instructions/math/root/sqrt_func.rs | 33 +++++++++++++-- .../math/vector/arithmetic/addv_func.rs | 30 ++++++++++++++ .../math/vector/arithmetic/divv_func.rs | 30 ++++++++++++++ .../math/vector/arithmetic/modv_func.rs | 30 ++++++++++++++ .../math/vector/arithmetic/mulv_func.rs | 30 ++++++++++++++ .../math/vector/arithmetic/negv_func.rs | 29 +++++++++++++ .../math/vector/arithmetic/subv_func.rs | 30 ++++++++++++++ .../math/vector/root/cbrtv_func.rs | 28 +++++++++++-- .../math/vector/root/sqrtv_func.rs | 28 +++++++++++-- 16 files changed, 527 insertions(+), 12 deletions(-) diff --git a/rust/src/instructions/math/arithmetic/add_func.rs b/rust/src/instructions/math/arithmetic/add_func.rs index 542a55dd..eced5f50 100644 --- a/rust/src/instructions/math/arithmetic/add_func.rs +++ b/rust/src/instructions/math/arithmetic/add_func.rs @@ -56,6 +56,23 @@ pub fn add_values( } } } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) { + for operand in [&a, &b] { + if matches!( + operand, + &Value::Int16(_) | &Value::Int32(_) | &Value::Int64(_) | &Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(operand.clone()), + }); + } + } + } Ok(match num_type { PrimitiveTypes::Sht => Value::Int16(add_i16in(a.as_i16(), b.as_i16())), PrimitiveTypes::Int => Value::Int32(add_i32in(a.as_i32(), b.as_i32())), @@ -90,6 +107,27 @@ pub fn add_func(stack: &mut Stack, num_type: PrimitiveTypes, ip: usize) -> Resul mod tests { use super::*; #[test] + fn float_directive_rejects_integer_operands_without_mutating_stack() { + for (a, b, found) in [ + (Value::Int32(1), Value::Float32(2.0), "Integer"), + (Value::Float64(1.0), Value::Int64(2), "Long"), + ] { + assert!(matches!( + add_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 10), + Err(VMError::TypeMismatch { ip: 10, expected: "Float", found: actual }) + if actual == found + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + add_func(&mut stack, PrimitiveTypes::Flt, 11), + Err(VMError::TypeMismatch { ip: 11, expected: "Float", found: actual }) + if actual == found + )); + assert_eq!(stack, original); + } + } + #[test] fn integer_directive_rejects_float_operands_without_mutating_stack() { for (a, b, found) in [ (Value::Float32(1.0), Value::Int32(2), "Float"), diff --git a/rust/src/instructions/math/arithmetic/div_func.rs b/rust/src/instructions/math/arithmetic/div_func.rs index 8cfebce0..7ae129dc 100644 --- a/rust/src/instructions/math/arithmetic/div_func.rs +++ b/rust/src/instructions/math/arithmetic/div_func.rs @@ -56,6 +56,23 @@ pub fn div_values( } } } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) { + for operand in [&a, &b] { + if matches!( + operand, + &Value::Int16(_) | &Value::Int32(_) | &Value::Int64(_) | &Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(operand.clone()), + }); + } + } + } Ok(match num_type { PrimitiveTypes::Sht => Value::Int16(div_i16in(a.as_i16(), b.as_i16())), PrimitiveTypes::Int => Value::Int32(div_i32in(a.as_i32(), b.as_i32())), @@ -93,6 +110,30 @@ pub fn div_func(stack: &mut Stack, num_type: PrimitiveTypes, ip: usize) -> Resul mod tests { use super::*; #[test] + fn float_directive_rejects_integer_operands_without_mutating_stack() { + let a = Value::Float32(4.0); + let b = Value::Int64(2); + assert!(matches!( + div_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 10), + Err(VMError::TypeMismatch { + ip: 10, + expected: "Float", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + div_func(&mut stack, PrimitiveTypes::Flt, 11), + Err(VMError::TypeMismatch { + ip: 11, + expected: "Float", + found: "Long" + }) + )); + assert_eq!(stack, original); + } + #[test] fn integer_directive_rejects_float_operands_without_mutating_stack() { for (a, b, found) in [ (Value::Float32(1.0), Value::Int32(2), "Float"), diff --git a/rust/src/instructions/math/arithmetic/mod_func.rs b/rust/src/instructions/math/arithmetic/mod_func.rs index d46bcd41..ae1e7b20 100644 --- a/rust/src/instructions/math/arithmetic/mod_func.rs +++ b/rust/src/instructions/math/arithmetic/mod_func.rs @@ -56,6 +56,23 @@ pub fn mod_values( } } } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) { + for operand in [&a, &b] { + if matches!( + operand, + &Value::Int16(_) | &Value::Int32(_) | &Value::Int64(_) | &Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(operand.clone()), + }); + } + } + } Ok(match num_type { PrimitiveTypes::Sht => Value::Int16(mod_i16in(a.as_i16(), b.as_i16())), PrimitiveTypes::Int => Value::Int32(mod_i32in(a.as_i32(), b.as_i32())), @@ -93,6 +110,30 @@ pub fn mod_func(stack: &mut Stack, num_type: PrimitiveTypes, ip: usize) -> Resul mod tests { use super::*; #[test] + fn float_directive_rejects_integer_operands_without_mutating_stack() { + let a = Value::Int32(4); + let b = Value::Float32(2.0); + assert!(matches!( + mod_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 10), + Err(VMError::TypeMismatch { + ip: 10, + expected: "Float", + found: "Integer" + }) + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + mod_func(&mut stack, PrimitiveTypes::Flt, 11), + Err(VMError::TypeMismatch { + ip: 11, + expected: "Float", + found: "Integer" + }) + )); + assert_eq!(stack, original); + } + #[test] fn integer_directive_rejects_float_operands_without_mutating_stack() { for (a, b, found) in [ (Value::Float32(1.0), Value::Int32(2), "Float"), diff --git a/rust/src/instructions/math/arithmetic/mul_func.rs b/rust/src/instructions/math/arithmetic/mul_func.rs index bd75c84f..a98f8c5d 100644 --- a/rust/src/instructions/math/arithmetic/mul_func.rs +++ b/rust/src/instructions/math/arithmetic/mul_func.rs @@ -56,6 +56,23 @@ pub fn mul_values( } } } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) { + for operand in [&a, &b] { + if matches!( + operand, + &Value::Int16(_) | &Value::Int32(_) | &Value::Int64(_) | &Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(operand.clone()), + }); + } + } + } Ok(match num_type { PrimitiveTypes::Sht => Value::Int16(mul_i16in(a.as_i16(), b.as_i16())), PrimitiveTypes::Int => Value::Int32(mul_i32in(a.as_i32(), b.as_i32())), @@ -93,6 +110,30 @@ pub fn mul_func(stack: &mut Stack, num_type: PrimitiveTypes, ip: usize) -> Resul mod tests { use super::*; #[test] + fn float_directive_rejects_integer_operands_without_mutating_stack() { + let a = Value::Float64(4.0); + let b = Value::Int64(2); + assert!(matches!( + mul_values(a.clone(), b.clone(), PrimitiveTypes::Dbl, 10), + Err(VMError::TypeMismatch { + ip: 10, + expected: "Double", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + mul_func(&mut stack, PrimitiveTypes::Dbl, 11), + Err(VMError::TypeMismatch { + ip: 11, + expected: "Double", + found: "Long" + }) + )); + assert_eq!(stack, original); + } + #[test] fn integer_directive_rejects_float_operands_without_mutating_stack() { for (a, b, found) in [ (Value::Float32(1.0), Value::Int32(2), "Float"), diff --git a/rust/src/instructions/math/arithmetic/neg_func.rs b/rust/src/instructions/math/arithmetic/neg_func.rs index f724ab97..6c36c3e4 100644 --- a/rust/src/instructions/math/arithmetic/neg_func.rs +++ b/rust/src/instructions/math/arithmetic/neg_func.rs @@ -40,6 +40,19 @@ pub fn neg_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result Value::Int16(neg_i16in(a.as_i16())), PrimitiveTypes::Int => Value::Int32(neg_i32in(a.as_i32())), @@ -71,6 +84,29 @@ pub fn neg_func(stack: &mut Stack, num_type: PrimitiveTypes, ip: usize) -> Resul mod tests { use super::*; #[test] + fn float_directive_rejects_integer_operand_without_mutating_stack() { + let operand = Value::Int64(1); + assert!(matches!( + neg_values(operand.clone(), PrimitiveTypes::Dbl, 10), + Err(VMError::TypeMismatch { + ip: 10, + expected: "Double", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![operand]); + let original = stack.clone(); + assert!(matches!( + neg_func(&mut stack, PrimitiveTypes::Dbl, 11), + Err(VMError::TypeMismatch { + ip: 11, + expected: "Double", + found: "Long" + }) + )); + assert_eq!(stack, original); + } + #[test] fn integer_directive_rejects_float_operand_without_mutating_stack() { let operand = Value::Float32(1.0); assert!(matches!( diff --git a/rust/src/instructions/math/arithmetic/sub_func.rs b/rust/src/instructions/math/arithmetic/sub_func.rs index abaf858b..b99f0e7e 100644 --- a/rust/src/instructions/math/arithmetic/sub_func.rs +++ b/rust/src/instructions/math/arithmetic/sub_func.rs @@ -56,6 +56,23 @@ pub fn sub_values( } } } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) { + for operand in [&a, &b] { + if matches!( + operand, + &Value::Int16(_) | &Value::Int32(_) | &Value::Int64(_) | &Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(operand.clone()), + }); + } + } + } Ok(match num_type { PrimitiveTypes::Sht => Value::Int16(sub_i16in(a.as_i16(), b.as_i16())), PrimitiveTypes::Int => Value::Int32(sub_i32in(a.as_i32(), b.as_i32())), @@ -93,6 +110,30 @@ pub fn sub_func(stack: &mut Stack, num_type: PrimitiveTypes, ip: usize) -> Resul mod tests { use super::*; #[test] + fn float_directive_rejects_integer_operands_without_mutating_stack() { + let a = Value::Int32(4); + let b = Value::Float32(2.0); + assert!(matches!( + sub_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 10), + Err(VMError::TypeMismatch { + ip: 10, + expected: "Float", + found: "Integer" + }) + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + sub_func(&mut stack, PrimitiveTypes::Flt, 11), + Err(VMError::TypeMismatch { + ip: 11, + expected: "Float", + found: "Integer" + }) + )); + assert_eq!(stack, original); + } + #[test] fn integer_directive_rejects_float_operands_without_mutating_stack() { for (a, b, found) in [ (Value::Float32(1.0), Value::Int32(2), "Float"), diff --git a/rust/src/instructions/math/root/cbrt_func.rs b/rust/src/instructions/math/root/cbrt_func.rs index 6186969a..f2be1b2d 100644 --- a/rust/src/instructions/math/root/cbrt_func.rs +++ b/rust/src/instructions/math/root/cbrt_func.rs @@ -19,11 +19,14 @@ use crate::types::value::Value; use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn cbrt_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { - if !a.is_number() { + if !matches!( + &a, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), - found: get_type_name(a), + found: get_type_name(a.clone()), }); } Ok(match num_type { @@ -34,7 +37,7 @@ pub fn cbrt_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result Resu } #[cfg(test)] mod tests { + use super::*; + #[test] + fn rejects_integer_operands_without_mutating_stack() { + let value = Value::Int64(1); + assert!(matches!( + cbrt_values(value.clone(), PrimitiveTypes::Dbl, 21), + Err(VMError::TypeMismatch { + ip: 21, + expected: "Double", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![value]); + let original = stack.clone(); + assert!(matches!( + cbrt_func(&mut stack, PrimitiveTypes::Dbl, 22), + Err(VMError::TypeMismatch { + ip: 22, + expected: "Double", + found: "Long" + }) + )); + assert_eq!(stack, original); + } #[test] fn reports_errors_without_mutating_stack() { crate::instructions::math::assert_unary_float_errors(super::cbrt_func, "CBRT"); diff --git a/rust/src/instructions/math/root/sqrt_func.rs b/rust/src/instructions/math/root/sqrt_func.rs index 09d73af7..2a62dee7 100644 --- a/rust/src/instructions/math/root/sqrt_func.rs +++ b/rust/src/instructions/math/root/sqrt_func.rs @@ -19,11 +19,14 @@ use crate::types::value::Value; use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn sqrt_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { - if !a.is_number() { + if !matches!( + &a, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), - found: get_type_name(a), + found: get_type_name(a.clone()), }); } Ok(match num_type { @@ -34,7 +37,7 @@ pub fn sqrt_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result Resu } #[cfg(test)] mod tests { + use super::*; + #[test] + fn rejects_integer_operands_without_mutating_stack() { + let value = Value::Int32(1); + assert!(matches!( + sqrt_values(value.clone(), PrimitiveTypes::Flt, 21), + Err(VMError::TypeMismatch { + ip: 21, + expected: "Float", + found: "Integer" + }) + )); + let mut stack = Stack::from_vec(vec![value]); + let original = stack.clone(); + assert!(matches!( + sqrt_func(&mut stack, PrimitiveTypes::Flt, 22), + Err(VMError::TypeMismatch { + ip: 22, + expected: "Float", + found: "Integer" + }) + )); + assert_eq!(stack, original); + } #[test] fn reports_errors_without_mutating_stack() { crate::instructions::math::assert_unary_float_errors(super::sqrt_func, "SQRT"); diff --git a/rust/src/instructions/math/vector/arithmetic/addv_func.rs b/rust/src/instructions/math/vector/arithmetic/addv_func.rs index a83c7142..02c4cd76 100644 --- a/rust/src/instructions/math/vector/arithmetic/addv_func.rs +++ b/rust/src/instructions/math/vector/arithmetic/addv_func.rs @@ -63,6 +63,19 @@ pub fn addv_values( found: get_type_name(value.clone()), }); } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) && matches!( + value, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(value.clone()), + }); + } } Ok(match num_type { PrimitiveTypes::Sht => Value::Array(addv_i16in(&arr_a, &arr_b)), @@ -104,6 +117,23 @@ mod tests { Value::Array(Arc::new(values)) } #[test] + fn rejects_integer_elements_for_float_directives() { + let left = array(vec![Value::Int32(1)]); + let right = array(vec![Value::Float32(2.0)]); + assert!(matches!( + addv_values(left.clone(), right.clone(), PrimitiveTypes::Flt, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Float", + found: "Integer" + }) + )); + let mut stack = Stack::from_vec(vec![left, right]); + let original = stack.clone(); + assert!(addv_func(&mut stack, PrimitiveTypes::Flt, 27).is_err()); + assert_eq!(stack, original); + } + #[test] fn rejects_float_elements_for_integer_directives() { let left = array(vec![Value::Float32(1.0)]); let right = array(vec![Value::Int32(2)]); diff --git a/rust/src/instructions/math/vector/arithmetic/divv_func.rs b/rust/src/instructions/math/vector/arithmetic/divv_func.rs index 6dcc925b..e13fe724 100644 --- a/rust/src/instructions/math/vector/arithmetic/divv_func.rs +++ b/rust/src/instructions/math/vector/arithmetic/divv_func.rs @@ -61,6 +61,19 @@ pub fn divv_values( found: get_type_name(value.clone()), }); } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) && matches!( + value, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(value.clone()), + }); + } } Ok(match num_type { PrimitiveTypes::Sht => Value::Array(divv_i16in(&arr_a, &arr_b)), @@ -102,6 +115,23 @@ mod tests { Value::Array(Arc::new(values)) } #[test] + fn rejects_integer_elements_for_float_directives() { + let left = array(vec![Value::Float64(2.0)]); + let right = array(vec![Value::Int64(1)]); + assert!(matches!( + divv_values(left.clone(), right.clone(), PrimitiveTypes::Dbl, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Double", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![left, right]); + let original = stack.clone(); + assert!(divv_func(&mut stack, PrimitiveTypes::Dbl, 27).is_err()); + assert_eq!(stack, original); + } + #[test] fn rejects_float_elements_for_integer_directives() { let left = array(vec![Value::Int64(2)]); let right = array(vec![Value::Float32(1.0)]); diff --git a/rust/src/instructions/math/vector/arithmetic/modv_func.rs b/rust/src/instructions/math/vector/arithmetic/modv_func.rs index fea00077..7d942a7e 100644 --- a/rust/src/instructions/math/vector/arithmetic/modv_func.rs +++ b/rust/src/instructions/math/vector/arithmetic/modv_func.rs @@ -61,6 +61,19 @@ pub fn modv_values( found: get_type_name(value.clone()), }); } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) && matches!( + value, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(value.clone()), + }); + } } Ok(match num_type { PrimitiveTypes::Sht => Value::Array(modv_i16in(&arr_a, &arr_b)), @@ -102,6 +115,23 @@ mod tests { Value::Array(Arc::new(values)) } #[test] + fn rejects_integer_elements_for_float_directives() { + let left = array(vec![Value::Int64(2)]); + let right = array(vec![Value::Float64(1.0)]); + assert!(matches!( + modv_values(left.clone(), right.clone(), PrimitiveTypes::Dbl, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Double", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![left, right]); + let original = stack.clone(); + assert!(modv_func(&mut stack, PrimitiveTypes::Dbl, 27).is_err()); + assert_eq!(stack, original); + } + #[test] fn rejects_float_elements_for_integer_directives() { let left = array(vec![Value::Float64(2.0)]); let right = array(vec![Value::Int128(1)]); diff --git a/rust/src/instructions/math/vector/arithmetic/mulv_func.rs b/rust/src/instructions/math/vector/arithmetic/mulv_func.rs index 21e5536c..58014a05 100644 --- a/rust/src/instructions/math/vector/arithmetic/mulv_func.rs +++ b/rust/src/instructions/math/vector/arithmetic/mulv_func.rs @@ -61,6 +61,19 @@ pub fn mulv_values( found: get_type_name(value.clone()), }); } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) && matches!( + value, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(value.clone()), + }); + } } Ok(match num_type { PrimitiveTypes::Sht => Value::Array(mulv_i16in(&arr_a, &arr_b)), @@ -102,6 +115,23 @@ mod tests { Value::Array(Arc::new(values)) } #[test] + fn rejects_integer_elements_for_float_directives() { + let left = array(vec![Value::Float32(2.0)]); + let right = array(vec![Value::Int32(1)]); + assert!(matches!( + mulv_values(left.clone(), right.clone(), PrimitiveTypes::Flt, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Float", + found: "Integer" + }) + )); + let mut stack = Stack::from_vec(vec![left, right]); + let original = stack.clone(); + assert!(mulv_func(&mut stack, PrimitiveTypes::Flt, 27).is_err()); + assert_eq!(stack, original); + } + #[test] fn rejects_float_elements_for_integer_directives() { let left = array(vec![Value::Float16(half::f16::ONE)]); let right = array(vec![Value::Int16(2)]); diff --git a/rust/src/instructions/math/vector/arithmetic/negv_func.rs b/rust/src/instructions/math/vector/arithmetic/negv_func.rs index 6c924176..bf14a5ed 100644 --- a/rust/src/instructions/math/vector/arithmetic/negv_func.rs +++ b/rust/src/instructions/math/vector/arithmetic/negv_func.rs @@ -44,6 +44,19 @@ pub fn negv_values(a_val: Value, num_type: PrimitiveTypes, ip: usize) -> Result< found: get_type_name(value.clone()), }); } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) && matches!( + value, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(value.clone()), + }); + } } Ok(match num_type { PrimitiveTypes::Sht => Value::Array(negv_i16in(&arr_a)), @@ -80,6 +93,22 @@ mod tests { Value::Array(Arc::new(values)) } #[test] + fn rejects_integer_elements_for_float_directives() { + let value = array(vec![Value::Int64(1)]); + assert!(matches!( + negv_values(value.clone(), PrimitiveTypes::Dbl, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Double", + found: "Long" + }) + )); + let mut stack = Stack::from_vec(vec![value]); + let original = stack.clone(); + assert!(negv_func(&mut stack, PrimitiveTypes::Dbl, 27).is_err()); + assert_eq!(stack, original); + } + #[test] fn rejects_float_elements_for_integer_directives() { let value = array(vec![Value::Float32(1.0)]); assert!(matches!( diff --git a/rust/src/instructions/math/vector/arithmetic/subv_func.rs b/rust/src/instructions/math/vector/arithmetic/subv_func.rs index ac43e8f2..063206f8 100644 --- a/rust/src/instructions/math/vector/arithmetic/subv_func.rs +++ b/rust/src/instructions/math/vector/arithmetic/subv_func.rs @@ -63,6 +63,19 @@ pub fn subv_values( found: get_type_name(value.clone()), }); } + if matches!( + num_type, + PrimitiveTypes::Hlf | PrimitiveTypes::Flt | PrimitiveTypes::Dbl + ) && matches!( + value, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) + ) { + return Err(VMError::TypeMismatch { + ip, + expected: expected_type(num_type, ExpectedCategory::Float), + found: get_type_name(value.clone()), + }); + } } Ok(match num_type { PrimitiveTypes::Sht => Value::Array(subv_i16in(&arr_a, &arr_b)), @@ -104,6 +117,23 @@ mod tests { Value::Array(Arc::new(values)) } #[test] + fn rejects_integer_elements_for_float_directives() { + let left = array(vec![Value::Int32(2)]); + let right = array(vec![Value::Float32(1.0)]); + assert!(matches!( + subv_values(left.clone(), right.clone(), PrimitiveTypes::Flt, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Float", + found: "Integer" + }) + )); + let mut stack = Stack::from_vec(vec![left, right]); + let original = stack.clone(); + assert!(subv_func(&mut stack, PrimitiveTypes::Flt, 27).is_err()); + assert_eq!(stack, original); + } + #[test] fn rejects_float_elements_for_integer_directives() { let left = array(vec![Value::Int32(2)]); let right = array(vec![Value::Float64(1.0)]); diff --git a/rust/src/instructions/math/vector/root/cbrtv_func.rs b/rust/src/instructions/math/vector/root/cbrtv_func.rs index 9c635c4f..193f743d 100644 --- a/rust/src/instructions/math/vector/root/cbrtv_func.rs +++ b/rust/src/instructions/math/vector/root/cbrtv_func.rs @@ -25,7 +25,10 @@ pub fn cbrtv_values(value: Value, num_type: PrimitiveTypes, ip: usize) -> Result found: get_type_name(value.clone()), })?; for value in values.iter() { - if !value.is_number() { + if !matches!( + value, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -41,7 +44,7 @@ pub fn cbrtv_values(value: Value, num_type: PrimitiveTypes, ip: usize) -> Result return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), - found: expected_type(num_type, ExpectedCategory::All), + found: "unknown", }); } }) @@ -70,7 +73,26 @@ mod tests { PrimitiveTypes::Flt, PrimitiveTypes::Dbl, ] { - assert!(cbrtv_values(array(vec![Value::Int32(1)]), num_type, 0).is_ok()); + assert!(cbrtv_values(array(vec![Value::Float32(1.0)]), num_type, 0).is_ok()); + } + } + #[test] + fn rejects_integer_elements_without_mutating_stack() { + for (value, found) in [(Value::Int32(1), "Integer"), (Value::Int64(1), "Long")] { + let operand = array(vec![value]); + assert!(matches!( + cbrtv_values(operand.clone(), PrimitiveTypes::Flt, 21), + Err(VMError::TypeMismatch { ip: 21, expected: "Float", found: actual }) + if actual == found + )); + let mut stack = Stack::from_vec(vec![operand]); + let original = stack.clone(); + assert!(matches!( + cbrtv_func(&mut stack, PrimitiveTypes::Flt, 22), + Err(VMError::TypeMismatch { ip: 22, expected: "Float", found: actual }) + if actual == found + )); + assert_eq!(stack, original); } } #[test] diff --git a/rust/src/instructions/math/vector/root/sqrtv_func.rs b/rust/src/instructions/math/vector/root/sqrtv_func.rs index 5684f599..112e539d 100644 --- a/rust/src/instructions/math/vector/root/sqrtv_func.rs +++ b/rust/src/instructions/math/vector/root/sqrtv_func.rs @@ -25,7 +25,10 @@ pub fn sqrtv_values(value: Value, num_type: PrimitiveTypes, ip: usize) -> Result found: get_type_name(value.clone()), })?; for value in values.iter() { - if !value.is_number() { + if !matches!( + value, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -41,7 +44,7 @@ pub fn sqrtv_values(value: Value, num_type: PrimitiveTypes, ip: usize) -> Result return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), - found: expected_type(num_type, ExpectedCategory::All), + found: "unknown", }); } }) @@ -70,7 +73,26 @@ mod tests { PrimitiveTypes::Flt, PrimitiveTypes::Dbl, ] { - assert!(sqrtv_values(array(vec![Value::Int32(1)]), num_type, 0).is_ok()); + assert!(sqrtv_values(array(vec![Value::Float32(1.0)]), num_type, 0).is_ok()); + } + } + #[test] + fn rejects_integer_elements_without_mutating_stack() { + for (value, found) in [(Value::Int32(1), "Integer"), (Value::Int64(1), "Long")] { + let operand = array(vec![value]); + assert!(matches!( + sqrtv_values(operand.clone(), PrimitiveTypes::Flt, 21), + Err(VMError::TypeMismatch { ip: 21, expected: "Float", found: actual }) + if actual == found + )); + let mut stack = Stack::from_vec(vec![operand]); + let original = stack.clone(); + assert!(matches!( + sqrtv_func(&mut stack, PrimitiveTypes::Flt, 22), + Err(VMError::TypeMismatch { ip: 22, expected: "Float", found: actual }) + if actual == found + )); + assert_eq!(stack, original); } } #[test]