Built-in interop between FLOAT/Decimal and INT.
This commit is contained in:
parent
7b8322b6e1
commit
bd5ff457d2
@ -9,10 +9,15 @@ Bug fixes
|
||||
|
||||
* Bug in `Position::is_beginning_of_line` is fixed.
|
||||
|
||||
Enhancements
|
||||
New features
|
||||
------------
|
||||
|
||||
* Comparisons between `FLOAT`/[`Decimal`](https://crates.io/crates/rust_decimal) and `INT` are now built in.
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
|
||||
* Built-in operators between `FLOAT`/[`Decimal`](https://crates.io/crates/rust_decimal) and `INT` are now implemented for more speed under those cases.
|
||||
* Error position in `eval` statements is now wrapped in an `EvalAltResult::ErrorInFunctionCall`.
|
||||
* `Position` now implements `Add` and `AddAssign`.
|
||||
* `Scope` now implements `IntoIterator`.
|
||||
|
319
src/fn_call.rs
319
src/fn_call.rs
@ -32,6 +32,9 @@ use crate::FLOAT;
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
use crate::Map;
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
use rust_decimal::Decimal;
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
use num_traits::float::Float;
|
||||
@ -1347,33 +1350,115 @@ pub fn run_builtin_binary_op(
|
||||
x: &Dynamic,
|
||||
y: &Dynamic,
|
||||
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
||||
let args_type = x.type_id();
|
||||
let first_type = x.type_id();
|
||||
let second_type = y.type_id();
|
||||
|
||||
if second_type != args_type {
|
||||
if args_type == TypeId::of::<char>() && second_type == TypeId::of::<ImmutableString>() {
|
||||
let type_id = (first_type, second_type);
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if let Some((x, y)) = if type_id == (TypeId::of::<FLOAT>(), TypeId::of::<FLOAT>()) {
|
||||
Some((x.clone().cast::<FLOAT>(), y.clone().cast::<FLOAT>()))
|
||||
} else if type_id == (TypeId::of::<FLOAT>(), TypeId::of::<INT>()) {
|
||||
Some((x.clone().cast::<FLOAT>(), y.clone().cast::<INT>() as FLOAT))
|
||||
} else if type_id == (TypeId::of::<INT>(), TypeId::of::<FLOAT>()) {
|
||||
Some((x.clone().cast::<INT>() as FLOAT, y.clone().cast::<FLOAT>()))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
match op {
|
||||
"+" => return Ok(Some((x + y).into())),
|
||||
"-" => return Ok(Some((x - y).into())),
|
||||
"*" => return Ok(Some((x * y).into())),
|
||||
"/" => return Ok(Some((x / y).into())),
|
||||
"%" => return Ok(Some((x % y).into())),
|
||||
"**" => return Ok(Some(x.powf(y).into())),
|
||||
"==" => return Ok(Some((x == y).into())),
|
||||
"!=" => return Ok(Some((x != y).into())),
|
||||
">" => return Ok(Some((x > y).into())),
|
||||
">=" => return Ok(Some((x >= y).into())),
|
||||
"<" => return Ok(Some((x < y).into())),
|
||||
"<=" => return Ok(Some((x <= y).into())),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
if let Some((x, y)) = if type_id == (TypeId::of::<Decimal>(), TypeId::of::<Decimal>()) {
|
||||
Some((
|
||||
*x.read_lock::<Decimal>().unwrap(),
|
||||
*y.read_lock::<Decimal>().unwrap(),
|
||||
))
|
||||
} else if type_id == (TypeId::of::<Decimal>(), TypeId::of::<INT>()) {
|
||||
Some((
|
||||
*x.read_lock::<Decimal>().unwrap(),
|
||||
y.clone().cast::<INT>().into(),
|
||||
))
|
||||
} else if type_id == (TypeId::of::<INT>(), TypeId::of::<Decimal>()) {
|
||||
Some((
|
||||
x.clone().cast::<INT>().into(),
|
||||
*y.read_lock::<Decimal>().unwrap(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
use crate::packages::arithmetic::decimal_functions::*;
|
||||
|
||||
match op {
|
||||
"+" => return add(x, y).map(Some),
|
||||
"-" => return subtract(x, y).map(Some),
|
||||
"*" => return multiply(x, y).map(Some),
|
||||
"/" => return divide(x, y).map(Some),
|
||||
"%" => return modulo(x, y).map(Some),
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
match op {
|
||||
"+" => return Ok(Some((x + y).into())),
|
||||
"-" => return Ok(Some((x - y).into())),
|
||||
"*" => return Ok(Some((x * y).into())),
|
||||
"/" => return Ok(Some((x / y).into())),
|
||||
"%" => return Ok(Some((x % y).into())),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
match op {
|
||||
"==" => return Ok(Some((x == y).into())),
|
||||
"!=" => return Ok(Some((x != y).into())),
|
||||
">" => return Ok(Some((x > y).into())),
|
||||
">=" => return Ok(Some((x >= y).into())),
|
||||
"<" => return Ok(Some((x < y).into())),
|
||||
"<=" => return Ok(Some((x <= y).into())),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
if second_type != first_type {
|
||||
if type_id == (TypeId::of::<char>(), TypeId::of::<ImmutableString>()) {
|
||||
let x = x.clone().cast::<char>();
|
||||
let y = &*y.read_lock::<ImmutableString>().unwrap();
|
||||
|
||||
match op {
|
||||
"+" => return Ok(Some(format!("{}{}", x, y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<ImmutableString>()
|
||||
&& second_type == TypeId::of::<char>()
|
||||
{
|
||||
}
|
||||
|
||||
if type_id == (TypeId::of::<ImmutableString>(), TypeId::of::<char>()) {
|
||||
let x = &*x.read_lock::<ImmutableString>().unwrap();
|
||||
let y = y.clone().cast::<char>();
|
||||
|
||||
match op {
|
||||
"+" => return Ok(Some((x + y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if args_type == TypeId::of::<INT>() {
|
||||
if first_type == TypeId::of::<INT>() {
|
||||
let x = x.clone().cast::<INT>();
|
||||
let y = y.clone().cast::<INT>();
|
||||
|
||||
@ -1415,9 +1500,11 @@ pub fn run_builtin_binary_op(
|
||||
"&" => return Ok(Some((x & y).into())),
|
||||
"|" => return Ok(Some((x | y).into())),
|
||||
"^" => return Ok(Some((x ^ y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<bool>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<bool>() {
|
||||
let x = x.clone().cast::<bool>();
|
||||
let y = y.clone().cast::<bool>();
|
||||
|
||||
@ -1427,9 +1514,11 @@ pub fn run_builtin_binary_op(
|
||||
"^" => return Ok(Some((x ^ y).into())),
|
||||
"==" => return Ok(Some((x == y).into())),
|
||||
"!=" => return Ok(Some((x != y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<ImmutableString>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<ImmutableString>() {
|
||||
let x = &*x.read_lock::<ImmutableString>().unwrap();
|
||||
let y = &*y.read_lock::<ImmutableString>().unwrap();
|
||||
|
||||
@ -1441,9 +1530,11 @@ pub fn run_builtin_binary_op(
|
||||
">=" => return Ok(Some((x >= y).into())),
|
||||
"<" => return Ok(Some((x < y).into())),
|
||||
"<=" => return Ok(Some((x <= y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<char>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<char>() {
|
||||
let x = x.clone().cast::<char>();
|
||||
let y = y.clone().cast::<char>();
|
||||
|
||||
@ -1455,73 +1546,15 @@ pub fn run_builtin_binary_op(
|
||||
">=" => return Ok(Some((x >= y).into())),
|
||||
"<" => return Ok(Some((x < y).into())),
|
||||
"<=" => return Ok(Some((x <= y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<()>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<()>() {
|
||||
match op {
|
||||
"==" => return Ok(Some(true.into())),
|
||||
"!=" | ">" | ">=" | "<" | "<=" => return Ok(Some(false.into())),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if args_type == TypeId::of::<FLOAT>() {
|
||||
let x = x.clone().cast::<FLOAT>();
|
||||
let y = y.clone().cast::<FLOAT>();
|
||||
|
||||
match op {
|
||||
"+" => return Ok(Some((x + y).into())),
|
||||
"-" => return Ok(Some((x - y).into())),
|
||||
"*" => return Ok(Some((x * y).into())),
|
||||
"/" => return Ok(Some((x / y).into())),
|
||||
"%" => return Ok(Some((x % y).into())),
|
||||
"**" => return Ok(Some(x.powf(y).into())),
|
||||
"==" => return Ok(Some((x == y).into())),
|
||||
"!=" => return Ok(Some((x != y).into())),
|
||||
">" => return Ok(Some((x > y).into())),
|
||||
">=" => return Ok(Some((x >= y).into())),
|
||||
"<" => return Ok(Some((x < y).into())),
|
||||
"<=" => return Ok(Some((x <= y).into())),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
if args_type == TypeId::of::<rust_decimal::Decimal>() {
|
||||
let x = x.clone().cast::<rust_decimal::Decimal>();
|
||||
let y = y.clone().cast::<rust_decimal::Decimal>();
|
||||
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
use crate::packages::arithmetic::decimal_functions::*;
|
||||
|
||||
match op {
|
||||
"+" => return add(x, y).map(Some),
|
||||
"-" => return subtract(x, y).map(Some),
|
||||
"*" => return multiply(x, y).map(Some),
|
||||
"/" => return divide(x, y).map(Some),
|
||||
"%" => return modulo(x, y).map(Some),
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
match op {
|
||||
"+" => return Ok(Some((x + y).into())),
|
||||
"-" => return Ok(Some((x - y).into())),
|
||||
"*" => return Ok(Some((x * y).into())),
|
||||
"/" => return Ok(Some((x / y).into())),
|
||||
"%" => return Ok(Some((x % y).into())),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
match op {
|
||||
"==" => return Ok(Some((x == y).into())),
|
||||
"!=" => return Ok(Some((x != y).into())),
|
||||
">" => return Ok(Some((x > y).into())),
|
||||
">=" => return Ok(Some((x >= y).into())),
|
||||
"<" => return Ok(Some((x < y).into())),
|
||||
"<=" => return Ok(Some((x <= y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1534,24 +1567,80 @@ pub fn run_builtin_op_assignment(
|
||||
x: &mut Dynamic,
|
||||
y: &Dynamic,
|
||||
) -> Result<Option<()>, Box<EvalAltResult>> {
|
||||
let args_type = x.type_id();
|
||||
let first_type = x.type_id();
|
||||
let second_type = y.type_id();
|
||||
|
||||
if second_type != args_type {
|
||||
if args_type == TypeId::of::<ImmutableString>() && second_type == TypeId::of::<char>() {
|
||||
let type_id = (first_type, second_type);
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if let Some((mut x, y)) = if type_id == (TypeId::of::<FLOAT>(), TypeId::of::<FLOAT>()) {
|
||||
let y = y.clone().cast::<FLOAT>();
|
||||
Some((x.write_lock::<FLOAT>().unwrap(), y))
|
||||
} else if type_id == (TypeId::of::<FLOAT>(), TypeId::of::<INT>()) {
|
||||
let y = y.clone().cast::<INT>() as FLOAT;
|
||||
Some((x.write_lock::<FLOAT>().unwrap(), y))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
"-=" => return Ok(Some(*x -= y)),
|
||||
"*=" => return Ok(Some(*x *= y)),
|
||||
"/=" => return Ok(Some(*x /= y)),
|
||||
"%=" => return Ok(Some(*x %= y)),
|
||||
"**=" => return Ok(Some(*x = x.powf(y))),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
if let Some((mut x, y)) = if type_id == (TypeId::of::<Decimal>(), TypeId::of::<Decimal>()) {
|
||||
let y = *y.read_lock::<Decimal>().unwrap();
|
||||
Some((x.write_lock::<Decimal>().unwrap(), y))
|
||||
} else if type_id == (TypeId::of::<Decimal>(), TypeId::of::<INT>()) {
|
||||
let y = y.clone().cast::<INT>().into();
|
||||
Some((x.write_lock::<Decimal>().unwrap(), y))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
use crate::packages::arithmetic::decimal_functions::*;
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x = add(*x, y)?.as_decimal().unwrap())),
|
||||
"-=" => return Ok(Some(*x = subtract(*x, y)?.as_decimal().unwrap())),
|
||||
"*=" => return Ok(Some(*x = multiply(*x, y)?.as_decimal().unwrap())),
|
||||
"/=" => return Ok(Some(*x = divide(*x, y)?.as_decimal().unwrap())),
|
||||
"%=" => return Ok(Some(*x = modulo(*x, y)?.as_decimal().unwrap())),
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
"-=" => return Ok(Some(*x -= y)),
|
||||
"*=" => return Ok(Some(*x *= y)),
|
||||
"/=" => return Ok(Some(*x /= y)),
|
||||
"%=" => return Ok(Some(*x %= y)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if second_type != first_type {
|
||||
if type_id == (TypeId::of::<ImmutableString>(), TypeId::of::<char>()) {
|
||||
let y = y.read_lock::<char>().unwrap().deref().clone();
|
||||
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if args_type == TypeId::of::<INT>() {
|
||||
if first_type == TypeId::of::<INT>() {
|
||||
let y = y.clone().cast::<INT>();
|
||||
let mut x = x.write_lock::<INT>().unwrap();
|
||||
|
||||
@ -1587,76 +1676,38 @@ pub fn run_builtin_op_assignment(
|
||||
"&=" => return Ok(Some(*x &= y)),
|
||||
"|=" => return Ok(Some(*x |= y)),
|
||||
"^=" => return Ok(Some(*x ^= y)),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<bool>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<bool>() {
|
||||
let y = y.clone().cast::<bool>();
|
||||
let mut x = x.write_lock::<bool>().unwrap();
|
||||
|
||||
match op {
|
||||
"&=" => return Ok(Some(*x = *x && y)),
|
||||
"|=" => return Ok(Some(*x = *x || y)),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<char>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<char>() {
|
||||
let y = y.read_lock::<char>().unwrap().deref().clone();
|
||||
let mut x = x.write_lock::<Dynamic>().unwrap();
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x = format!("{}{}", *x, y).into())),
|
||||
_ => (),
|
||||
_ => return Ok(None),
|
||||
}
|
||||
} else if args_type == TypeId::of::<ImmutableString>() {
|
||||
}
|
||||
|
||||
if first_type == TypeId::of::<ImmutableString>() {
|
||||
let y = y.read_lock::<ImmutableString>().unwrap().deref().clone();
|
||||
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if args_type == TypeId::of::<FLOAT>() {
|
||||
let y = y.clone().cast::<FLOAT>();
|
||||
let mut x = x.write_lock::<FLOAT>().unwrap();
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
"-=" => return Ok(Some(*x -= y)),
|
||||
"*=" => return Ok(Some(*x *= y)),
|
||||
"/=" => return Ok(Some(*x /= y)),
|
||||
"%=" => return Ok(Some(*x %= y)),
|
||||
"**=" => return Ok(Some(*x = x.powf(y))),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
if args_type == TypeId::of::<rust_decimal::Decimal>() {
|
||||
let y = y.clone().cast::<rust_decimal::Decimal>();
|
||||
let mut x = x.write_lock::<rust_decimal::Decimal>().unwrap();
|
||||
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
use crate::packages::arithmetic::decimal_functions::*;
|
||||
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x = add(*x, y)?.as_decimal().unwrap())),
|
||||
"-=" => return Ok(Some(*x = subtract(*x, y)?.as_decimal().unwrap())),
|
||||
"*=" => return Ok(Some(*x = multiply(*x, y)?.as_decimal().unwrap())),
|
||||
"/=" => return Ok(Some(*x = divide(*x, y)?.as_decimal().unwrap())),
|
||||
"%=" => return Ok(Some(*x = modulo(*x, y)?.as_decimal().unwrap())),
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
match op {
|
||||
"+=" => return Ok(Some(*x += y)),
|
||||
"-=" => return Ok(Some(*x -= y)),
|
||||
"*=" => return Ok(Some(*x *= y)),
|
||||
"/=" => return Ok(Some(*x /= y)),
|
||||
"%=" => return Ok(Some(*x %= y)),
|
||||
_ => (),
|
||||
}
|
||||
_ => return Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,6 @@ mod f32_functions {
|
||||
pub fn pow_f_f(x: f32, y: f32) -> f32 {
|
||||
x.powf(y)
|
||||
}
|
||||
}
|
||||
|
||||
#[rhai_fn(name = "+")]
|
||||
pub fn add_if(x: INT, y: f32) -> f32 {
|
||||
@ -296,6 +295,7 @@ mod f32_functions {
|
||||
pub fn modulo_fi(x: f32, y: INT) -> f32 {
|
||||
(x as f32) % (y as f32)
|
||||
}
|
||||
}
|
||||
|
||||
#[rhai_fn(name = "-")]
|
||||
pub fn neg(x: f32) -> f32 {
|
||||
@ -359,7 +359,6 @@ mod f64_functions {
|
||||
pub fn pow_f_f(x: f64, y: f64) -> f64 {
|
||||
x.powf(y)
|
||||
}
|
||||
}
|
||||
|
||||
#[rhai_fn(name = "+")]
|
||||
pub fn add_if(x: INT, y: f64) -> f64 {
|
||||
@ -401,6 +400,7 @@ mod f64_functions {
|
||||
pub fn modulo_fi(x: f64, y: INT) -> f64 {
|
||||
(x as f64) % (y as f64)
|
||||
}
|
||||
}
|
||||
|
||||
#[rhai_fn(name = "-")]
|
||||
pub fn neg(x: f64) -> f64 {
|
||||
@ -440,61 +440,37 @@ mod f64_functions {
|
||||
mod decimal_functions {
|
||||
use rust_decimal::{prelude::Zero, Decimal};
|
||||
|
||||
#[rhai_fn(name = "+", return_raw)]
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn add(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
x.checked_add(y)
|
||||
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
|
||||
.map(Dynamic::from)
|
||||
.map(Into::<Dynamic>::into)
|
||||
} else {
|
||||
Ok(Dynamic::from(x + y))
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "+", return_raw)]
|
||||
pub fn add_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
add(x.into(), y)
|
||||
}
|
||||
#[rhai_fn(name = "+", return_raw)]
|
||||
pub fn add_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
add(x, y.into())
|
||||
}
|
||||
#[rhai_fn(name = "-", return_raw)]
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn subtract(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
x.checked_sub(y)
|
||||
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
|
||||
.map(Dynamic::from)
|
||||
.map(Into::<Dynamic>::into)
|
||||
} else {
|
||||
Ok(Dynamic::from(x - y))
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "-", return_raw)]
|
||||
pub fn subtract_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
subtract(x.into(), y)
|
||||
}
|
||||
#[rhai_fn(name = "-", return_raw)]
|
||||
pub fn subtract_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
subtract(x, y.into())
|
||||
}
|
||||
#[rhai_fn(name = "*", return_raw)]
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn multiply(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
x.checked_mul(y)
|
||||
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
|
||||
.map(Dynamic::from)
|
||||
.map(Into::<Dynamic>::into)
|
||||
} else {
|
||||
Ok(Dynamic::from(x * y))
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "*", return_raw)]
|
||||
pub fn multiply_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
multiply(x.into(), y)
|
||||
}
|
||||
#[rhai_fn(name = "*", return_raw)]
|
||||
pub fn multiply_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
multiply(x, y.into())
|
||||
}
|
||||
#[rhai_fn(name = "/", return_raw)]
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn divide(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
// Detect division by zero
|
||||
@ -503,21 +479,13 @@ mod decimal_functions {
|
||||
} else {
|
||||
x.checked_div(y)
|
||||
.ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y)))
|
||||
.map(Dynamic::from)
|
||||
.map(Into::<Dynamic>::into)
|
||||
}
|
||||
} else {
|
||||
Ok(Dynamic::from(x / y))
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "/", return_raw)]
|
||||
pub fn divide_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
divide(x.into(), y)
|
||||
}
|
||||
#[rhai_fn(name = "/", return_raw)]
|
||||
pub fn divide_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
divide(x, y.into())
|
||||
}
|
||||
#[rhai_fn(name = "%", return_raw)]
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn modulo(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
x.checked_rem(y)
|
||||
@ -527,19 +495,11 @@ mod decimal_functions {
|
||||
x, y
|
||||
))
|
||||
})
|
||||
.map(Dynamic::from)
|
||||
.map(Into::<Dynamic>::into)
|
||||
} else {
|
||||
Ok(Dynamic::from(x % y))
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "%", return_raw)]
|
||||
pub fn modulo_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
modulo(x.into(), y)
|
||||
}
|
||||
#[rhai_fn(name = "%", return_raw)]
|
||||
pub fn modulo_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
modulo(x, y.into())
|
||||
}
|
||||
#[rhai_fn(name = "-")]
|
||||
pub fn neg(x: Decimal) -> Decimal {
|
||||
-x
|
||||
|
@ -3167,48 +3167,20 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Union::Float(value, _) => Some(Expr::FloatConstant(value, pos)),
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
Union::Decimal(value, _) => Some(Expr::DynamicConstant(Box::new((*value).into()), pos)),
|
||||
|
||||
Union::Unit(_, _) => Some(Expr::Unit(pos)),
|
||||
Union::Int(value, _) => Some(Expr::IntegerConstant(value, pos)),
|
||||
Union::Char(value, _) => Some(Expr::CharConstant(value, pos)),
|
||||
Union::Str(value, _) => Some(Expr::StringConstant(value, pos)),
|
||||
Union::Bool(value, _) => Some(Expr::BoolConstant(value, pos)),
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Union::Array(array, _) => {
|
||||
let items: Vec<_> = array
|
||||
.into_iter()
|
||||
.map(|x| map_dynamic_to_expr(x, pos))
|
||||
.collect();
|
||||
Union::Array(array, _) => Some(Expr::DynamicConstant(Box::new((*array).into()), pos)),
|
||||
|
||||
if items.iter().all(Option::is_some) {
|
||||
Some(Expr::Array(
|
||||
Box::new(items.into_iter().map(Option::unwrap).collect()),
|
||||
pos,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Union::Map(map, _) => {
|
||||
let items: Vec<_> = map
|
||||
.into_iter()
|
||||
.map(|(name, value)| (Ident { name, pos }, map_dynamic_to_expr(value, pos)))
|
||||
.collect();
|
||||
|
||||
if items.iter().all(|(_, expr)| expr.is_some()) {
|
||||
Some(Expr::Map(
|
||||
Box::new(
|
||||
items
|
||||
.into_iter()
|
||||
.map(|(k, expr)| (k, expr.unwrap()))
|
||||
.collect(),
|
||||
),
|
||||
pos,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Union::Map(map, _) => Some(Expr::DynamicConstant(Box::new((*map).into()), pos)),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user