diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index b9553cd8..33b01b57 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -17,250 +17,246 @@ use crate::stdlib::format; macro_rules! gen_arithmetic_functions { ($root:ident => $($arg_type:ident),+) => { - pub mod $root { $( - pub mod $arg_type { - use super::super::*; + pub mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_module] - pub mod functions { - #[rhai_fn(name = "+", return_raw)] - #[inline] - pub fn add(x: $arg_type, y: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - x.checked_add(y).ok_or_else(|| { + #[export_module] + pub mod functions { + #[rhai_fn(name = "+", return_raw)] + #[inline] + pub fn add(x: $arg_type, y: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_add(y).ok_or_else(|| { + EvalAltResult::ErrorArithmetic( + format!("Addition overflow: {} + {}", x, y), + Position::none(), + ) + .into() + }).map(Dynamic::from) + } else { + Ok(Dynamic::from(x + y)) + } + } + #[rhai_fn(name = "-", return_raw)] + #[inline] + pub fn subtract(x: $arg_type, y: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_sub(y).ok_or_else(|| { + EvalAltResult::ErrorArithmetic( + format!("Subtraction overflow: {} - {}", x, y), + Position::none(), + ) + .into() + }).map(Dynamic::from) + } else { + Ok(Dynamic::from(x - y)) + } + } + #[rhai_fn(name = "*", return_raw)] + #[inline] + pub fn multiply(x: $arg_type, y: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_mul(y).ok_or_else(|| { + EvalAltResult::ErrorArithmetic( + format!("Multiplication overflow: {} * {}", x, y), + Position::none(), + ) + .into() + }).map(Dynamic::from) + } else { + Ok(Dynamic::from(x * y)) + } + } + #[rhai_fn(name = "/", return_raw)] + #[inline] + pub fn divide(x: $arg_type, y: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + // Detect division by zero + if y == 0 { + EvalAltResult::ErrorArithmetic( + format!("Division by zero: {} / {}", x, y), + Position::none(), + ) + .into() + } else { + x.checked_div(y).ok_or_else(|| { EvalAltResult::ErrorArithmetic( - format!("Addition overflow: {} + {}", x, y), + format!("Division overflow: {} / {}", x, y), Position::none(), ) .into() }).map(Dynamic::from) - } else { - Ok(Dynamic::from(x + y)) } + } else { + Ok(Dynamic::from(x / y)) } - #[rhai_fn(name = "-", return_raw)] - #[inline] - pub fn subtract(x: $arg_type, y: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - x.checked_sub(y).ok_or_else(|| { + } + #[rhai_fn(name = "%", return_raw)] + #[inline] + pub fn modulo(x: $arg_type, y: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_rem(y).ok_or_else(|| { + EvalAltResult::ErrorArithmetic( + format!("Modulo division by zero or overflow: {} % {}", x, y), + Position::none(), + ) + .into() + }).map(Dynamic::from) + } else { + Ok(Dynamic::from(x % y)) + } + } + #[rhai_fn(name = "~", return_raw)] + #[inline] + pub fn power(x: INT, y: INT) -> Result> { + if cfg!(not(feature = "unchecked")) { + if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) { + EvalAltResult::ErrorArithmetic( + format!("Integer raised to too large an index: {} ~ {}", x, y), + Position::none(), + ) + .into() + } else if y < 0 { + EvalAltResult::ErrorArithmetic( + format!("Integer raised to a negative index: {} ~ {}", x, y), + Position::none(), + ) + .into() + } else { + x.checked_pow(y as u32).ok_or_else(|| { EvalAltResult::ErrorArithmetic( - format!("Subtraction overflow: {} - {}", x, y), + format!("Power overflow: {} ~ {}", x, y), Position::none(), ) .into() }).map(Dynamic::from) - } else { - Ok(Dynamic::from(x - y)) - } - } - #[rhai_fn(name = "*", return_raw)] - #[inline] - pub fn multiply(x: $arg_type, y: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - x.checked_mul(y).ok_or_else(|| { - EvalAltResult::ErrorArithmetic( - format!("Multiplication overflow: {} * {}", x, y), - Position::none(), - ) - .into() - }).map(Dynamic::from) - } else { - Ok(Dynamic::from(x * y)) - } - } - #[rhai_fn(name = "/", return_raw)] - #[inline] - pub fn divide(x: $arg_type, y: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - // Detect division by zero - if y == 0 { - EvalAltResult::ErrorArithmetic( - format!("Division by zero: {} / {}", x, y), - Position::none(), - ) - .into() - } else { - x.checked_div(y).ok_or_else(|| { - EvalAltResult::ErrorArithmetic( - format!("Division overflow: {} / {}", x, y), - Position::none(), - ) - .into() - }).map(Dynamic::from) - } - } else { - Ok(Dynamic::from(x / y)) - } - } - #[rhai_fn(name = "%", return_raw)] - #[inline] - pub fn modulo(x: $arg_type, y: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - x.checked_rem(y).ok_or_else(|| { - EvalAltResult::ErrorArithmetic( - format!("Modulo division by zero or overflow: {} % {}", x, y), - Position::none(), - ) - .into() - }).map(Dynamic::from) - } else { - Ok(Dynamic::from(x % y)) - } - } - #[rhai_fn(name = "~", return_raw)] - #[inline] - pub fn power(x: INT, y: INT) -> Result> { - if cfg!(not(feature = "unchecked")) { - if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) { - EvalAltResult::ErrorArithmetic( - format!("Integer raised to too large an index: {} ~ {}", x, y), - Position::none(), - ) - .into() - } else if y < 0 { - EvalAltResult::ErrorArithmetic( - format!("Integer raised to a negative index: {} ~ {}", x, y), - Position::none(), - ) - .into() - } else { - x.checked_pow(y as u32).ok_or_else(|| { - EvalAltResult::ErrorArithmetic( - format!("Power overflow: {} ~ {}", x, y), - Position::none(), - ) - .into() - }).map(Dynamic::from) - } - } else { - Ok(Dynamic::from(x.pow(y as u32))) } + } else { + Ok(Dynamic::from(x.pow(y as u32))) } + } - #[rhai_fn(name = "<<", return_raw)] - #[inline] - pub fn shift_left(x: $arg_type, y: INT) -> Result> { - if cfg!(not(feature = "unchecked")) { - if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) { + #[rhai_fn(name = "<<", return_raw)] + #[inline] + pub fn shift_left(x: $arg_type, y: INT) -> Result> { + if cfg!(not(feature = "unchecked")) { + if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) { + EvalAltResult::ErrorArithmetic( + format!("Left-shift by too many bits: {} << {}", x, y), + Position::none(), + ) + .into() + } else if y < 0 { + EvalAltResult::ErrorArithmetic( + format!("Left-shift by a negative number: {} << {}", x, y), + Position::none(), + ) + .into() + } else { + x.checked_shl(y as u32).ok_or_else(|| { EvalAltResult::ErrorArithmetic( format!("Left-shift by too many bits: {} << {}", x, y), Position::none(), ) .into() - } else if y < 0 { - EvalAltResult::ErrorArithmetic( - format!("Left-shift by a negative number: {} << {}", x, y), - Position::none(), - ) - .into() - } else { - x.checked_shl(y as u32).ok_or_else(|| { - EvalAltResult::ErrorArithmetic( - format!("Left-shift by too many bits: {} << {}", x, y), - Position::none(), - ) - .into() - }).map(Dynamic::from) - } - } else { - Ok(Dynamic::from(x << y)) + }).map(Dynamic::from) } + } else { + Ok(Dynamic::from(x << y)) } - #[rhai_fn(name = ">>", return_raw)] - #[inline] - pub fn shift_right(x: $arg_type, y: INT) -> Result> { - if cfg!(not(feature = "unchecked")) { - if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) { + } + #[rhai_fn(name = ">>", return_raw)] + #[inline] + pub fn shift_right(x: $arg_type, y: INT) -> Result> { + if cfg!(not(feature = "unchecked")) { + if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) { + EvalAltResult::ErrorArithmetic( + format!("Right-shift by too many bits: {} >> {}", x, y), + Position::none(), + ) + .into() + } else if y < 0 { + EvalAltResult::ErrorArithmetic( + format!("Right-shift by a negative number: {} >> {}", x, y), + Position::none(), + ) + .into() + } else { + x.checked_shr(y as u32).ok_or_else(|| { EvalAltResult::ErrorArithmetic( format!("Right-shift by too many bits: {} >> {}", x, y), Position::none(), ) .into() - } else if y < 0 { - EvalAltResult::ErrorArithmetic( - format!("Right-shift by a negative number: {} >> {}", x, y), - Position::none(), - ) - .into() - } else { - x.checked_shr(y as u32).ok_or_else(|| { - EvalAltResult::ErrorArithmetic( - format!("Right-shift by too many bits: {} >> {}", x, y), - Position::none(), - ) - .into() - }).map(Dynamic::from) - } - } else { - Ok(Dynamic::from(x >> y)) + }).map(Dynamic::from) } - } - #[rhai_fn(name = "&")] - #[inline(always)] - pub fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type { - x & y - } - #[rhai_fn(name = "|")] - #[inline(always)] - pub fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type { - x | y - } - #[rhai_fn(name = "^")] - #[inline(always)] - pub fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type { - x ^ y + } else { + Ok(Dynamic::from(x >> y)) } } + #[rhai_fn(name = "&")] + #[inline(always)] + pub fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type { + x & y + } + #[rhai_fn(name = "|")] + #[inline(always)] + pub fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type { + x | y + } + #[rhai_fn(name = "^")] + #[inline(always)] + pub fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type { + x ^ y + } } - )* } + })* } } } macro_rules! gen_signed_functions { ($root:ident => $($arg_type:ident),+) => { - pub mod $root { $( - pub mod $arg_type { - use super::super::*; + pub mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_module] - pub mod functions { - #[rhai_fn(name = "-", return_raw)] - #[inline] - pub fn neg(x: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - x.checked_neg().ok_or_else(|| { - EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none()) - .into() - }).map(Dynamic::from) - } else { - Ok(Dynamic::from(-x)) - } + #[export_module] + pub mod functions { + #[rhai_fn(name = "-", return_raw)] + #[inline] + pub fn neg(x: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_neg().ok_or_else(|| { + EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none()) + .into() + }).map(Dynamic::from) + } else { + Ok(Dynamic::from(-x)) } - #[rhai_fn(return_raw)] - #[inline] - pub fn abs(x: $arg_type) -> Result> { - if cfg!(not(feature = "unchecked")) { - x.checked_abs().ok_or_else(|| { - EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none()) - .into() - }).map(Dynamic::from) - } else { - Ok(Dynamic::from(x.abs())) - } + } + #[rhai_fn(return_raw)] + #[inline] + pub fn abs(x: $arg_type) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_abs().ok_or_else(|| { + EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none()) + .into() + }).map(Dynamic::from) + } else { + Ok(Dynamic::from(x.abs())) } - #[inline] - pub fn sign(x: $arg_type) -> INT { - if x == 0 { - 0 - } else if x < 0 { - -1 - } else { - 1 - } + } + #[inline] + pub fn sign(x: $arg_type) -> INT { + if x == 0 { + 0 + } else if x < 0 { + -1 + } else { + 1 } } } - )* } + })* } } } diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index a69372ae..66c35924 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -23,30 +23,33 @@ pub type Unit = (); macro_rules! gen_array_functions { ($root:ident => $($arg_type:ident),+ ) => { - pub mod $root { $( - pub mod $arg_type { - use super::super::*; + pub mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_fn] - #[inline(always)] - pub fn push_func(list: &mut Array, item: $arg_type) { - super::super::push(list, item); - } + #[export_fn] + #[inline(always)] + pub fn push(list: &mut Array, item: $arg_type) { + list.push(Dynamic::from(item)); + } - #[export_fn] - #[inline(always)] - pub fn insert_func(list: &mut Array, len: INT, item: $arg_type) { - super::super::insert(list, len, item); + #[export_fn] + pub fn insert(list: &mut Array, position: INT, item: $arg_type) { + if position <= 0 { + list.insert(0, Dynamic::from(item)); + } else if (position as usize) >= list.len() - 1 { + push(list, item); + } else { + list.insert(position as usize, Dynamic::from(item)); } } - )* } + })* } } } macro_rules! reg_functions { ($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $( - set_exported_fn!($mod_name, "push", $root::$arg_type::push_func); - set_exported_fn!($mod_name, "insert", $root::$arg_type::insert_func); + set_exported_fn!($mod_name, "push", $root::$arg_type::push); + set_exported_fn!($mod_name, "insert", $root::$arg_type::insert); $mod_name.set_raw_fn("pad", &[TypeId::of::(), TypeId::of::(), TypeId::of::<$arg_type>()], @@ -138,20 +141,6 @@ mod array_functions { } } -// Register array utility functions -#[inline(always)] -fn push(list: &mut Array, item: T) { - list.push(Dynamic::from(item)); -} -fn insert(list: &mut Array, position: INT, item: T) { - if position <= 0 { - list.insert(0, Dynamic::from(item)); - } else if (position as usize) >= list.len() - 1 { - push(list, item); - } else { - list.insert(position as usize, Dynamic::from(item)); - } -} fn pad( _engine: &Engine, _: &Module, diff --git a/src/packages/logic.rs b/src/packages/logic.rs index e05d8515..48e46047 100644 --- a/src/packages/logic.rs +++ b/src/packages/logic.rs @@ -3,45 +3,43 @@ use crate::plugin::*; macro_rules! gen_cmp_functions { ($root:ident => $($arg_type:ident),+) => { - mod $root { $( - pub mod $arg_type { - use crate::plugin::*; + mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_module] - pub mod functions { - #[rhai_fn(name = "<")] - #[inline(always)] - pub fn lt(x: $arg_type, y: $arg_type) -> bool { - x < y - } - #[rhai_fn(name = "<=")] - #[inline(always)] - pub fn lte(x: $arg_type, y: $arg_type) -> bool { - x <= y - } - #[rhai_fn(name = ">")] - #[inline(always)] - pub fn gt(x: $arg_type, y: $arg_type) -> bool { - x > y - } - #[rhai_fn(name = ">=")] - #[inline(always)] - pub fn gte(x: $arg_type, y: $arg_type) -> bool { - x >= y - } - #[rhai_fn(name = "==")] - #[inline(always)] - pub fn eq(x: $arg_type, y: $arg_type) -> bool { - x == y - } - #[rhai_fn(name = "!=")] - #[inline(always)] - pub fn ne(x: $arg_type, y: $arg_type) -> bool { - x != y - } + #[export_module] + pub mod functions { + #[rhai_fn(name = "<")] + #[inline(always)] + pub fn lt(x: $arg_type, y: $arg_type) -> bool { + x < y + } + #[rhai_fn(name = "<=")] + #[inline(always)] + pub fn lte(x: $arg_type, y: $arg_type) -> bool { + x <= y + } + #[rhai_fn(name = ">")] + #[inline(always)] + pub fn gt(x: $arg_type, y: $arg_type) -> bool { + x > y + } + #[rhai_fn(name = ">=")] + #[inline(always)] + pub fn gte(x: $arg_type, y: $arg_type) -> bool { + x >= y + } + #[rhai_fn(name = "==")] + #[inline(always)] + pub fn eq(x: $arg_type, y: $arg_type) -> bool { + x == y + } + #[rhai_fn(name = "!=")] + #[inline(always)] + pub fn ne(x: $arg_type, y: $arg_type) -> bool { + x != y } } - )* } + })* } }; } diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index f1de6c4f..a7c17e50 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -26,17 +26,15 @@ pub const MAX_INT: INT = i64::MAX; macro_rules! gen_conversion_functions { ($root:ident => $func_name:ident ( $($arg_type:ident),+ ) -> $result_type:ty) => { - pub mod $root { $( - pub mod $arg_type { - use super::super::*; + pub mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_fn] - #[inline(always)] - pub fn $func_name(x: $arg_type) -> $result_type { - x as $result_type - } + #[export_fn] + #[inline(always)] + pub fn $func_name(x: $arg_type) -> $result_type { + x as $result_type } - )* } + })* } } } diff --git a/src/packages/string_basic.rs b/src/packages/string_basic.rs index ae5a84e0..288fc115 100644 --- a/src/packages/string_basic.rs +++ b/src/packages/string_basic.rs @@ -22,17 +22,15 @@ type Unit = (); macro_rules! gen_functions { ($root:ident => $fn_name:ident ( $($arg_type:ident),+ )) => { - pub mod $root { $( - pub mod $arg_type { - use super::super::*; + pub mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_fn] - #[inline(always)] - pub fn to_string_func(x: &mut $arg_type) -> ImmutableString { - super::super::$fn_name(x) - } + #[export_fn] + #[inline(always)] + pub fn to_string_func(x: &mut $arg_type) -> ImmutableString { + super::super::$fn_name(x) } - )* } + })* } } } @@ -128,12 +126,12 @@ gen_functions!(print_array => to_debug(Array)); #[export_fn] #[inline(always)] fn print_empty_string() -> ImmutableString { - "".to_string().into() + String::new().into() } #[export_fn] #[inline(always)] fn print_unit(_x: ()) -> ImmutableString { - "".to_string().into() + String::new().into() } #[export_fn] #[inline(always)] @@ -143,7 +141,7 @@ fn print_string(s: ImmutableString) -> ImmutableString { #[export_fn] #[inline(always)] fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString { - f.to_string().into() + to_string(f) } #[inline(always)] fn to_string(x: &mut T) -> ImmutableString { diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 883d4fec..3766d487 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -12,28 +12,26 @@ use crate::utils::StaticVec; use crate::{result::EvalAltResult, token::Position}; use crate::stdlib::{ - any::TypeId, boxed::Box, fmt::Display, format, mem, string::String, string::ToString, vec::Vec, + any::TypeId, boxed::Box, format, mem, string::String, string::ToString, vec::Vec, }; macro_rules! gen_concat_functions { ($root:ident => $($arg_type:ident),+ ) => { - pub mod $root { $( - pub mod $arg_type { - use super::super::*; + pub mod $root { $(pub mod $arg_type { + use super::super::*; - #[export_fn] - #[inline(always)] - pub fn append_func(x: &mut ImmutableString, y: $arg_type) -> String { - super::super::add_append(x, y) - } - - #[export_fn] - #[inline(always)] - pub fn prepend_func(x: &mut $arg_type, y: ImmutableString) -> String { - super::super::add_prepend(x, y) - } + #[export_fn] + #[inline] + pub fn append_func(x: &mut ImmutableString, y: $arg_type) -> String { + format!("{}{}", x, y) } - )* } + + #[export_fn] + #[inline] + pub fn prepend_func(x: &mut $arg_type, y: ImmutableString) -> String { + format!("{}{}", x, y) + } + })* } } } @@ -116,15 +114,6 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str ); }); -#[inline] -fn add_prepend(x: &mut T, y: ImmutableString) -> String { - format!("{}{}", x, y) -} -#[inline] -fn add_append(x: &mut ImmutableString, y: T) -> String { - format!("{}{}", x, y) -} - gen_concat_functions!(basic => INT, bool, char, FnPtr); #[cfg(not(feature = "only_i32"))]