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.
|
* 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.
|
* 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`.
|
* Error position in `eval` statements is now wrapped in an `EvalAltResult::ErrorInFunctionCall`.
|
||||||
* `Position` now implements `Add` and `AddAssign`.
|
* `Position` now implements `Add` and `AddAssign`.
|
||||||
* `Scope` now implements `IntoIterator`.
|
* `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"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
|
#[cfg(feature = "decimal")]
|
||||||
|
use rust_decimal::Decimal;
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use num_traits::float::Float;
|
use num_traits::float::Float;
|
||||||
@ -1347,33 +1350,115 @@ pub fn run_builtin_binary_op(
|
|||||||
x: &Dynamic,
|
x: &Dynamic,
|
||||||
y: &Dynamic,
|
y: &Dynamic,
|
||||||
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
||||||
let args_type = x.type_id();
|
let first_type = x.type_id();
|
||||||
let second_type = y.type_id();
|
let second_type = y.type_id();
|
||||||
|
|
||||||
if second_type != args_type {
|
let type_id = (first_type, second_type);
|
||||||
if args_type == TypeId::of::<char>() && second_type == TypeId::of::<ImmutableString>() {
|
|
||||||
|
#[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 x = x.clone().cast::<char>();
|
||||||
let y = &*y.read_lock::<ImmutableString>().unwrap();
|
let y = &*y.read_lock::<ImmutableString>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+" => return Ok(Some(format!("{}{}", x, y).into())),
|
"+" => 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 x = &*x.read_lock::<ImmutableString>().unwrap();
|
||||||
let y = y.clone().cast::<char>();
|
let y = y.clone().cast::<char>();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+" => return Ok(Some((x + y).into())),
|
"+" => return Ok(Some((x + y).into())),
|
||||||
_ => (),
|
_ => return Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 x = x.clone().cast::<INT>();
|
||||||
let y = y.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(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 x = x.clone().cast::<bool>();
|
||||||
let y = y.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(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 x = &*x.read_lock::<ImmutableString>().unwrap();
|
||||||
let y = &*y.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(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 x = x.clone().cast::<char>();
|
||||||
let y = y.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(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 {
|
match op {
|
||||||
"==" => return Ok(Some(true.into())),
|
"==" => return Ok(Some(true.into())),
|
||||||
"!=" | ">" | ">=" | "<" | "<=" => return Ok(Some(false.into())),
|
"!=" | ">" | ">=" | "<" | "<=" => return Ok(Some(false.into())),
|
||||||
_ => (),
|
_ => return Ok(None),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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())),
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1534,24 +1567,80 @@ pub fn run_builtin_op_assignment(
|
|||||||
x: &mut Dynamic,
|
x: &mut Dynamic,
|
||||||
y: &Dynamic,
|
y: &Dynamic,
|
||||||
) -> Result<Option<()>, Box<EvalAltResult>> {
|
) -> Result<Option<()>, Box<EvalAltResult>> {
|
||||||
let args_type = x.type_id();
|
let first_type = x.type_id();
|
||||||
let second_type = y.type_id();
|
let second_type = y.type_id();
|
||||||
|
|
||||||
if second_type != args_type {
|
let type_id = (first_type, second_type);
|
||||||
if args_type == TypeId::of::<ImmutableString>() && second_type == TypeId::of::<char>() {
|
|
||||||
|
#[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 y = y.read_lock::<char>().unwrap().deref().clone();
|
||||||
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+=" => return Ok(Some(*x += y)),
|
"+=" => return Ok(Some(*x += y)),
|
||||||
_ => (),
|
_ => return Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 y = y.clone().cast::<INT>();
|
||||||
let mut x = x.write_lock::<INT>().unwrap();
|
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(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 y = y.clone().cast::<bool>();
|
||||||
let mut x = x.write_lock::<bool>().unwrap();
|
let mut x = x.write_lock::<bool>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"&=" => return Ok(Some(*x = *x && y)),
|
"&=" => return Ok(Some(*x = *x && y)),
|
||||||
"|=" => 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 y = y.read_lock::<char>().unwrap().deref().clone();
|
||||||
let mut x = x.write_lock::<Dynamic>().unwrap();
|
let mut x = x.write_lock::<Dynamic>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+=" => return Ok(Some(*x = format!("{}{}", *x, y).into())),
|
"+=" => 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 y = y.read_lock::<ImmutableString>().unwrap().deref().clone();
|
||||||
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+=" => return Ok(Some(*x += y)),
|
"+=" => return Ok(Some(*x += y)),
|
||||||
_ => (),
|
_ => return Ok(None),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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)),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +254,6 @@ mod f32_functions {
|
|||||||
pub fn pow_f_f(x: f32, y: f32) -> f32 {
|
pub fn pow_f_f(x: f32, y: f32) -> f32 {
|
||||||
x.powf(y)
|
x.powf(y)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn add_if(x: INT, y: f32) -> f32 {
|
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 {
|
pub fn modulo_fi(x: f32, y: INT) -> f32 {
|
||||||
(x as f32) % (y as f32)
|
(x as f32) % (y as f32)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "-")]
|
#[rhai_fn(name = "-")]
|
||||||
pub fn neg(x: f32) -> f32 {
|
pub fn neg(x: f32) -> f32 {
|
||||||
@ -359,7 +359,6 @@ mod f64_functions {
|
|||||||
pub fn pow_f_f(x: f64, y: f64) -> f64 {
|
pub fn pow_f_f(x: f64, y: f64) -> f64 {
|
||||||
x.powf(y)
|
x.powf(y)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn add_if(x: INT, y: f64) -> f64 {
|
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 {
|
pub fn modulo_fi(x: f64, y: INT) -> f64 {
|
||||||
(x as f64) % (y as f64)
|
(x as f64) % (y as f64)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "-")]
|
#[rhai_fn(name = "-")]
|
||||||
pub fn neg(x: f64) -> f64 {
|
pub fn neg(x: f64) -> f64 {
|
||||||
@ -440,61 +440,37 @@ mod f64_functions {
|
|||||||
mod decimal_functions {
|
mod decimal_functions {
|
||||||
use rust_decimal::{prelude::Zero, Decimal};
|
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>> {
|
pub fn add(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_add(y)
|
x.checked_add(y)
|
||||||
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
|
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
|
||||||
.map(Dynamic::from)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x + y))
|
Ok(Dynamic::from(x + y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+", return_raw)]
|
#[rhai_fn(skip, 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)]
|
|
||||||
pub fn subtract(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_sub(y)
|
x.checked_sub(y)
|
||||||
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
|
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
|
||||||
.map(Dynamic::from)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x - y))
|
Ok(Dynamic::from(x - y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "-", return_raw)]
|
#[rhai_fn(skip, 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)]
|
|
||||||
pub fn multiply(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn multiply(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_mul(y)
|
x.checked_mul(y)
|
||||||
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
|
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
|
||||||
.map(Dynamic::from)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x * y))
|
Ok(Dynamic::from(x * y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "*", return_raw)]
|
#[rhai_fn(skip, 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)]
|
|
||||||
pub fn divide(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn divide(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
// Detect division by zero
|
// Detect division by zero
|
||||||
@ -503,21 +479,13 @@ mod decimal_functions {
|
|||||||
} else {
|
} else {
|
||||||
x.checked_div(y)
|
x.checked_div(y)
|
||||||
.ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y)))
|
.ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y)))
|
||||||
.map(Dynamic::from)
|
.map(Into::<Dynamic>::into)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x / y))
|
Ok(Dynamic::from(x / y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "/", return_raw)]
|
#[rhai_fn(skip, 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)]
|
|
||||||
pub fn modulo(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn modulo(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_rem(y)
|
x.checked_rem(y)
|
||||||
@ -527,19 +495,11 @@ mod decimal_functions {
|
|||||||
x, y
|
x, y
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.map(Dynamic::from)
|
.map(Into::<Dynamic>::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(x % y))
|
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 = "-")]
|
#[rhai_fn(name = "-")]
|
||||||
pub fn neg(x: Decimal) -> Decimal {
|
pub fn neg(x: Decimal) -> Decimal {
|
||||||
-x
|
-x
|
||||||
|
@ -3167,48 +3167,20 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Union::Float(value, _) => Some(Expr::FloatConstant(value, pos)),
|
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::Unit(_, _) => Some(Expr::Unit(pos)),
|
||||||
Union::Int(value, _) => Some(Expr::IntegerConstant(value, pos)),
|
Union::Int(value, _) => Some(Expr::IntegerConstant(value, pos)),
|
||||||
Union::Char(value, _) => Some(Expr::CharConstant(value, pos)),
|
Union::Char(value, _) => Some(Expr::CharConstant(value, pos)),
|
||||||
Union::Str(value, _) => Some(Expr::StringConstant(value, pos)),
|
Union::Str(value, _) => Some(Expr::StringConstant(value, pos)),
|
||||||
Union::Bool(value, _) => Some(Expr::BoolConstant(value, pos)),
|
Union::Bool(value, _) => Some(Expr::BoolConstant(value, pos)),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(array, _) => {
|
Union::Array(array, _) => Some(Expr::DynamicConstant(Box::new((*array).into()), pos)),
|
||||||
let items: Vec<_> = array
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| map_dynamic_to_expr(x, pos))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
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"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(map, _) => {
|
Union::Map(map, _) => Some(Expr::DynamicConstant(Box::new((*map).into()), pos)),
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user