Disallow implicit comparisons between different numeric types.
This commit is contained in:
@@ -647,11 +647,9 @@ mod array_functions {
|
||||
return Ok(true.into());
|
||||
}
|
||||
|
||||
let def_value = Some(false.into());
|
||||
|
||||
for (a1, a2) in array.iter_mut().zip(array2.iter_mut()) {
|
||||
let equals = ctx
|
||||
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [a1, a2], def_value.as_ref())
|
||||
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [a1, a2])
|
||||
.map(|v| v.as_bool().unwrap_or(false))?;
|
||||
|
||||
if !equals {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::def_package;
|
||||
use crate::fn_call::run_builtin_binary_op;
|
||||
use crate::plugin::*;
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
@@ -17,30 +18,12 @@ macro_rules! gen_cmp_functions {
|
||||
|
||||
#[export_module]
|
||||
pub mod functions {
|
||||
#[rhai_fn(name = "<")]
|
||||
pub fn lt(x: $arg_type, y: $arg_type) -> bool {
|
||||
x < y
|
||||
}
|
||||
#[rhai_fn(name = "<=")]
|
||||
pub fn lte(x: $arg_type, y: $arg_type) -> bool {
|
||||
x <= y
|
||||
}
|
||||
#[rhai_fn(name = ">")]
|
||||
pub fn gt(x: $arg_type, y: $arg_type) -> bool {
|
||||
x > y
|
||||
}
|
||||
#[rhai_fn(name = ">=")]
|
||||
pub fn gte(x: $arg_type, y: $arg_type) -> bool {
|
||||
x >= y
|
||||
}
|
||||
#[rhai_fn(name = "==")]
|
||||
pub fn eq(x: $arg_type, y: $arg_type) -> bool {
|
||||
x == y
|
||||
}
|
||||
#[rhai_fn(name = "!=")]
|
||||
pub fn ne(x: $arg_type, y: $arg_type) -> bool {
|
||||
x != y
|
||||
}
|
||||
#[rhai_fn(name = "<")] pub fn lt(x: $arg_type, y: $arg_type) -> bool { x < y }
|
||||
#[rhai_fn(name = "<=")] pub fn lte(x: $arg_type, y: $arg_type) -> bool { x <= y }
|
||||
#[rhai_fn(name = ">")] pub fn gt(x: $arg_type, y: $arg_type) -> bool { x > y }
|
||||
#[rhai_fn(name = ">=")] pub fn gte(x: $arg_type, y: $arg_type) -> bool { x >= y }
|
||||
#[rhai_fn(name = "==")] pub fn eq(x: $arg_type, y: $arg_type) -> bool { x == y }
|
||||
#[rhai_fn(name = "!=")] pub fn ne(x: $arg_type, y: $arg_type) -> bool { x != y }
|
||||
}
|
||||
})* }
|
||||
};
|
||||
@@ -57,6 +40,8 @@ macro_rules! reg_functions {
|
||||
}
|
||||
|
||||
def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
||||
combine_with_exported_module!(lib, "logic", logic_functions);
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
@@ -112,6 +97,60 @@ gen_cmp_functions!(float => f64);
|
||||
#[cfg(feature = "decimal")]
|
||||
gen_cmp_functions!(decimal => Decimal);
|
||||
|
||||
#[export_module]
|
||||
mod logic_functions {
|
||||
fn is_numeric(type_id: TypeId) -> bool {
|
||||
let result = type_id == TypeId::of::<u8>()
|
||||
|| type_id == TypeId::of::<u16>()
|
||||
|| type_id == TypeId::of::<u32>()
|
||||
|| type_id == TypeId::of::<u64>()
|
||||
|| type_id == TypeId::of::<i8>()
|
||||
|| type_id == TypeId::of::<i16>()
|
||||
|| type_id == TypeId::of::<i32>()
|
||||
|| type_id == TypeId::of::<i64>();
|
||||
|
||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||
let result = result || type_id == TypeId::of::<u128>() || type_id == TypeId::of::<i128>();
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
let result = result || type_id == TypeId::of::<f32>() || type_id == TypeId::of::<f64>();
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
let result = result || type_id_x == TypeId::of::<rust_decimal::Decimal>();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[rhai_fn(
|
||||
name = "==",
|
||||
name = "!=",
|
||||
name = ">",
|
||||
name = ">=",
|
||||
name = "<",
|
||||
name = "<=",
|
||||
return_raw
|
||||
)]
|
||||
pub fn cmp(
|
||||
ctx: NativeCallContext,
|
||||
x: Dynamic,
|
||||
y: Dynamic,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let type_x = x.type_id();
|
||||
let type_y = y.type_id();
|
||||
|
||||
if type_x != type_y && is_numeric(type_x) && is_numeric(type_y) {
|
||||
// Disallow comparisons between different number types
|
||||
} else if let Some(x) = run_builtin_binary_op(ctx.fn_name(), &x, &y)? {
|
||||
return Ok(x);
|
||||
}
|
||||
|
||||
Err(Box::new(EvalAltResult::ErrorFunctionNotFound(
|
||||
format!("{} ({}, {})", ctx.fn_name(), x.type_name(), y.type_name()),
|
||||
Position::NONE,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_module]
|
||||
mod f32_functions {
|
||||
|
@@ -58,12 +58,10 @@ mod map_functions {
|
||||
return Ok(true.into());
|
||||
}
|
||||
|
||||
let def_value = Some(false.into());
|
||||
|
||||
for (m1, v1) in map.iter_mut() {
|
||||
if let Some(v2) = map2.get_mut(m1) {
|
||||
let equals = ctx
|
||||
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [v1, v2], def_value.as_ref())
|
||||
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [v1, v2])
|
||||
.map(|v| v.as_bool().unwrap_or(false))?;
|
||||
|
||||
if !equals {
|
||||
|
@@ -21,7 +21,7 @@ def_package!(crate:BasicStringPackage:"Basic string utilities, including printin
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline(always)]
|
||||
fn print_with_func(fn_name: &str, ctx: &NativeCallContext, value: &mut Dynamic) -> ImmutableString {
|
||||
match ctx.call_fn_dynamic_raw(fn_name, true, false, &mut [value], None) {
|
||||
match ctx.call_fn_dynamic_raw(fn_name, true, false, &mut [value]) {
|
||||
Ok(result) if result.is::<ImmutableString>() => result.take_immutable_string().unwrap(),
|
||||
Ok(result) => ctx.engine().map_type_name(result.type_name()).into(),
|
||||
Err(_) => ctx.engine().map_type_name(value.type_name()).into(),
|
||||
|
Reference in New Issue
Block a user