Refine packages plumbing.
This commit is contained in:
parent
e394824bf3
commit
0a75479637
@ -1,7 +1,7 @@
|
|||||||
//! Module that defines the extern API of `Engine`.
|
//! Module that defines the extern API of `Engine`.
|
||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::{calc_fn_spec, make_getter, make_setter, Engine, FnAny, Map};
|
use crate::engine::{make_getter, make_setter, Engine, Map};
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::fn_call::FuncArgs;
|
use crate::fn_call::FuncArgs;
|
||||||
use crate::fn_register::RegisterFn;
|
use crate::fn_register::RegisterFn;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Main module defining the script evaluation `Engine`.
|
//! Main module defining the script evaluation `Engine`.
|
||||||
|
|
||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
|
use crate::calc_fn_hash;
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{CorePackage, Package, PackageLibrary, StandardPackage};
|
use crate::packages::{CorePackage, Package, PackageLibrary, StandardPackage};
|
||||||
@ -121,16 +122,12 @@ impl<'a> From<&'a mut Dynamic> for Target<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that holds a library of script-defined functions.
|
/// A type that holds a library (`HashMap`) of script-defined functions.
|
||||||
///
|
///
|
||||||
/// Since script-defined functions have `Dynamic` parameters, functions with the same name
|
/// Since script-defined functions have `Dynamic` parameters, functions with the same name
|
||||||
/// and number of parameters are considered equivalent.
|
/// and number of parameters are considered equivalent.
|
||||||
///
|
///
|
||||||
/// Since the key is a combination of the function name (a String) plus the number of parameters,
|
/// The key of the `HashMap` is a `u64` hash calculated by the function `calc_fn_def`.
|
||||||
/// we cannot use a `HashMap` because we don't want to clone the function name string just
|
|
||||||
/// to search for it.
|
|
||||||
///
|
|
||||||
/// So instead this is implemented as a sorted list and binary searched.
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FunctionsLib(
|
pub struct FunctionsLib(
|
||||||
#[cfg(feature = "sync")] HashMap<u64, Arc<FnDef>>,
|
#[cfg(feature = "sync")] HashMap<u64, Arc<FnDef>>,
|
||||||
@ -224,7 +221,9 @@ impl DerefMut for FunctionsLib {
|
|||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
/// A collection of all library packages loaded into the engine.
|
/// A collection of all library packages loaded into the engine.
|
||||||
pub(crate) packages: Vec<PackageLibrary>,
|
pub(crate) packages: Vec<PackageLibrary>,
|
||||||
/// A hashmap containing all compiled functions known to the engine.
|
/// A `HashMap` containing all compiled functions known to the engine.
|
||||||
|
///
|
||||||
|
/// The key of the `HashMap` is a `u64` hash calculated by the function `crate::calc_fn_hash`.
|
||||||
pub(crate) functions: HashMap<u64, Box<FnAny>>,
|
pub(crate) functions: HashMap<u64, Box<FnAny>>,
|
||||||
|
|
||||||
/// A hashmap containing all iterators known to the engine.
|
/// A hashmap containing all iterators known to the engine.
|
||||||
@ -335,13 +334,18 @@ fn extract_prop_from_setter(fn_name: &str) -> Option<&str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn calc_fn_spec(fn_name: &str, params: impl Iterator<Item = TypeId>) -> u64 {
|
/// Calculate a `u64` hash key from a function name and parameter types.
|
||||||
|
///
|
||||||
|
/// Parameter types are passed in via `TypeId` values from an iterator
|
||||||
|
/// which can come from any source.
|
||||||
|
pub fn calc_fn_spec(fn_name: &str, params: impl Iterator<Item = TypeId>) -> u64 {
|
||||||
let mut s = DefaultHasher::new();
|
let mut s = DefaultHasher::new();
|
||||||
fn_name.hash(&mut s);
|
fn_name.hash(&mut s);
|
||||||
params.for_each(|t| t.hash(&mut s));
|
params.for_each(|t| t.hash(&mut s));
|
||||||
s.finish()
|
s.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate a `u64` hash key from a function name and number of parameters (without regard to types).
|
||||||
pub(crate) fn calc_fn_def(fn_name: &str, params: usize) -> u64 {
|
pub(crate) fn calc_fn_def(fn_name: &str, params: usize) -> u64 {
|
||||||
let mut s = DefaultHasher::new();
|
let mut s = DefaultHasher::new();
|
||||||
fn_name.hash(&mut s);
|
fn_name.hash(&mut s);
|
||||||
@ -473,7 +477,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load a new package into the `Engine`.
|
||||||
|
///
|
||||||
|
/// When searching for functions, packages loaded later are preferred.
|
||||||
|
/// In other words, loaded packages are searched in reverse order.
|
||||||
pub fn load_package(&mut self, package: PackageLibrary) {
|
pub fn load_package(&mut self, package: PackageLibrary) {
|
||||||
|
// Push the package to the top - packages are searched in reverse order
|
||||||
self.packages.insert(0, package);
|
self.packages.insert(0, package);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,13 +585,13 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
let fn_spec = calc_fn_spec(fn_name, args.iter().map(|a| a.type_id()));
|
let fn_spec = calc_fn_hash(fn_name, args.iter().map(|a| a.type_id()));
|
||||||
|
|
||||||
if let Some(func) = self.functions.get(&fn_spec).or_else(|| {
|
if let Some(func) = self.functions.get(&fn_spec).or_else(|| {
|
||||||
self.packages
|
self.packages
|
||||||
.iter()
|
.iter()
|
||||||
.find(|p| p.0.contains_key(&fn_spec))
|
.find(|pkg| pkg.functions.contains_key(&fn_spec))
|
||||||
.and_then(|p| p.0.get(&fn_spec))
|
.and_then(|pkg| pkg.functions.get(&fn_spec))
|
||||||
}) {
|
}) {
|
||||||
// Run external function
|
// Run external function
|
||||||
let result = func(args, pos)?;
|
let result = func(args, pos)?;
|
||||||
@ -1343,7 +1352,7 @@ impl Engine {
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
engine
|
engine
|
||||||
.functions
|
.functions
|
||||||
.contains_key(&calc_fn_spec(name, once(TypeId::of::<String>())))
|
.contains_key(&calc_fn_hash(name, once(TypeId::of::<String>())))
|
||||||
|| fn_lib.map_or(false, |lib| lib.has_function(name, 1))
|
|| fn_lib.map_or(false, |lib| lib.has_function(name, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1555,8 +1564,8 @@ impl Engine {
|
|||||||
if let Some(iter_fn) = self.type_iterators.get(&tid).or_else(|| {
|
if let Some(iter_fn) = self.type_iterators.get(&tid).or_else(|| {
|
||||||
self.packages
|
self.packages
|
||||||
.iter()
|
.iter()
|
||||||
.find(|p| p.1.contains_key(&tid))
|
.find(|pkg| pkg.type_iterators.contains_key(&tid))
|
||||||
.and_then(|p| p.1.get(&tid))
|
.and_then(|pkg| pkg.type_iterators.get(&tid))
|
||||||
}) {
|
}) {
|
||||||
// Add the loop variable - variable name is copied
|
// Add the loop variable - variable name is copied
|
||||||
// TODO - avoid copying variable name
|
// TODO - avoid copying variable name
|
||||||
|
@ -5,15 +5,15 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::stdlib::vec::Vec;
|
use crate::stdlib::vec::Vec;
|
||||||
|
|
||||||
/// Trait that represent arguments to a function call.
|
/// Trait that represents arguments to a function call.
|
||||||
/// Any data type that can be converted into a `Vec` of `Dynamic` values can be used
|
/// Any data type that can be converted into a `Vec<Dynamic>` can be used
|
||||||
/// as arguments to a function call.
|
/// as arguments to a function call.
|
||||||
pub trait FuncArgs {
|
pub trait FuncArgs {
|
||||||
/// Convert to a `Vec` of `Dynamic` arguments.
|
/// Convert to a `Vec<Dynamic>` of the function call arguments.
|
||||||
fn into_vec(self) -> Vec<Dynamic>;
|
fn into_vec(self) -> Vec<Dynamic>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Macro to implement `FuncArgs` for tuples of standard types (each can be
|
/// Macro to implement `FuncArgs` for tuples of standard types (each can be
|
||||||
/// converted into `Dynamic`).
|
/// converted into `Dynamic`).
|
||||||
macro_rules! impl_args {
|
macro_rules! impl_args {
|
||||||
($($p:ident),*) => {
|
($($p:ident),*) => {
|
||||||
|
@ -86,7 +86,7 @@ mod stdlib;
|
|||||||
mod token;
|
mod token;
|
||||||
|
|
||||||
pub use any::Dynamic;
|
pub use any::Dynamic;
|
||||||
pub use engine::Engine;
|
pub use engine::{calc_fn_spec as calc_fn_hash, Engine};
|
||||||
pub use error::{ParseError, ParseErrorType};
|
pub use error::{ParseError, ParseErrorType};
|
||||||
pub use fn_call::FuncArgs;
|
pub use fn_call::FuncArgs;
|
||||||
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
calc_fn_spec, Engine, FnAny, FnCallArgs, FunctionsLib, KEYWORD_DEBUG, KEYWORD_EVAL,
|
Engine, FnAny, FnCallArgs, FunctionsLib, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT,
|
||||||
KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
use crate::packages::PackageLibrary;
|
use crate::packages::PackageLibrary;
|
||||||
use crate::parser::{map_dynamic_to_expr, Expr, FnDef, ReturnType, Stmt, AST};
|
use crate::parser::{map_dynamic_to_expr, Expr, FnDef, ReturnType, Stmt, AST};
|
||||||
@ -118,15 +119,15 @@ fn call_fn(
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
let hash = calc_fn_spec(fn_name, args.iter().map(|a| a.type_id()));
|
let hash = calc_fn_hash(fn_name, args.iter().map(|a| a.type_id()));
|
||||||
|
|
||||||
functions
|
functions
|
||||||
.get(&hash)
|
.get(&hash)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
packages
|
packages
|
||||||
.iter()
|
.iter()
|
||||||
.find(|p| p.0.contains_key(&hash))
|
.find(|p| p.functions.contains_key(&hash))
|
||||||
.and_then(|p| p.0.get(&hash))
|
.and_then(|p| p.functions.get(&hash))
|
||||||
})
|
})
|
||||||
.map(|func| func(args, pos))
|
.map(|func| func(args, pos))
|
||||||
.transpose()
|
.transpose()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_unary};
|
||||||
create_new_package, reg_binary, reg_unary, Package, PackageLibrary, PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::fn_register::{map_dynamic as map, map_result as result};
|
use crate::fn_register::{map_dynamic as map, map_result as result};
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
@ -18,7 +17,7 @@ use num_traits::{
|
|||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
format,
|
format,
|
||||||
ops::{Add, BitAnd, BitOr, BitXor, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub},
|
ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub},
|
||||||
{i32, i64, u32},
|
{i32, i64, u32},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -254,16 +253,6 @@ fn pow_f_i_u(x: FLOAT, y: INT) -> FLOAT {
|
|||||||
x.powi(y as i32)
|
x.powi(y as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ArithmeticPackage(PackageLibrary);
|
|
||||||
|
|
||||||
impl Deref for ArithmeticPackage {
|
|
||||||
type Target = PackageLibrary;
|
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! reg_unary_x { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
macro_rules! reg_unary_x { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
||||||
$(reg_unary($lib, $op, $func::<$par>, result);)* };
|
$(reg_unary($lib, $op, $func::<$par>, result);)* };
|
||||||
}
|
}
|
||||||
@ -277,166 +266,154 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
|||||||
$(reg_binary($lib, $op, $func::<$par>, map);)* };
|
$(reg_binary($lib, $op, $func::<$par>, map);)* };
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package for ArithmeticPackage {
|
def_package!(ArithmeticPackage:"Basic arithmetic", lib, {
|
||||||
fn new() -> Self {
|
// Checked basic arithmetic
|
||||||
let mut pkg = create_new_package();
|
#[cfg(not(feature = "unchecked"))]
|
||||||
Self::init(&mut pkg);
|
{
|
||||||
Self(pkg.into())
|
reg_op_x!(lib, "+", add, INT);
|
||||||
}
|
reg_op_x!(lib, "-", sub, INT);
|
||||||
|
reg_op_x!(lib, "*", mul, INT);
|
||||||
fn get(&self) -> PackageLibrary {
|
reg_op_x!(lib, "/", div, INT);
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
|
||||||
// Checked basic arithmetic
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
reg_op_x!(lib, "+", add, INT);
|
|
||||||
reg_op_x!(lib, "-", sub, INT);
|
|
||||||
reg_op_x!(lib, "*", mul, INT);
|
|
||||||
reg_op_x!(lib, "/", div, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op_x!(lib, "+", add, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op_x!(lib, "-", sub, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op_x!(lib, "*", mul, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op_x!(lib, "/", div, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unchecked basic arithmetic
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "+", add_u, INT);
|
|
||||||
reg_op!(lib, "-", sub_u, INT);
|
|
||||||
reg_op!(lib, "*", mul_u, INT);
|
|
||||||
reg_op!(lib, "/", div_u, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "+", add_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "-", sub_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "*", mul_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "/", div_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic arithmetic for floating-point - no need to check
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "+", add_u, f32, f64);
|
|
||||||
reg_op!(lib, "-", sub_u, f32, f64);
|
|
||||||
reg_op!(lib, "*", mul_u, f32, f64);
|
|
||||||
reg_op!(lib, "/", div_u, f32, f64);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bit operations
|
|
||||||
reg_op!(lib, "|", binary_or, INT);
|
|
||||||
reg_op!(lib, "&", binary_and, INT);
|
|
||||||
reg_op!(lib, "^", binary_xor, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
{
|
{
|
||||||
reg_op!(lib, "|", binary_or, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
reg_op_x!(lib, "+", add, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
reg_op!(lib, "&", binary_and, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
reg_op_x!(lib, "-", sub, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
reg_op!(lib, "^", binary_xor, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
reg_op_x!(lib, "*", mul, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
}
|
reg_op_x!(lib, "/", div, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
|
||||||
// Checked bit shifts
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
reg_op_x!(lib, "<<", shl, INT);
|
|
||||||
reg_op_x!(lib, ">>", shr, INT);
|
|
||||||
reg_op_x!(lib, "%", modulo, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op_x!(lib, "<<", shl, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op_x!(lib, ">>", shr, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op_x!(lib, "%", modulo, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unchecked bit shifts
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "<<", shl_u, INT, INT);
|
|
||||||
reg_op!(lib, ">>", shr_u, INT, INT);
|
|
||||||
reg_op!(lib, "%", modulo_u, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "<<", shl_u, i64, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, ">>", shr_u, i64, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "%", modulo_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checked power
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
reg_binary(lib, "~", pow_i_i, result);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
reg_binary(lib, "~", pow_f_i, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unchecked power
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
{
|
|
||||||
reg_binary(lib, "~", pow_i_i_u, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
reg_binary(lib, "~", pow_f_i_u, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Floating-point modulo and power
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "%", modulo_u, f32, f64);
|
|
||||||
reg_binary(lib, "~", pow_f_f, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checked unary
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
reg_unary_x!(lib, "-", neg, INT);
|
|
||||||
reg_unary_x!(lib, "abs", abs, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_unary_x!(lib, "-", neg, i8, i16, i32, i64, i128);
|
|
||||||
reg_unary_x!(lib, "abs", abs, i8, i16, i32, i64, i128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unchecked unary
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
{
|
|
||||||
reg_unary!(lib, "-", neg_u, INT);
|
|
||||||
reg_unary!(lib, "abs", abs_u, INT);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_unary!(lib, "-", neg_u, i8, i16, i32, i64, i128);
|
|
||||||
reg_unary!(lib, "abs", abs_u, i8, i16, i32, i64, i128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Floating-point unary
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
reg_unary!(lib, "-", neg_u, f32, f64);
|
|
||||||
reg_unary!(lib, "abs", abs_u, f32, f64);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Unchecked basic arithmetic
|
||||||
|
#[cfg(feature = "unchecked")]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "+", add_u, INT);
|
||||||
|
reg_op!(lib, "-", sub_u, INT);
|
||||||
|
reg_op!(lib, "*", mul_u, INT);
|
||||||
|
reg_op!(lib, "/", div_u, INT);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "+", add_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "-", sub_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "*", mul_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "/", div_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic arithmetic for floating-point - no need to check
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "+", add_u, f32, f64);
|
||||||
|
reg_op!(lib, "-", sub_u, f32, f64);
|
||||||
|
reg_op!(lib, "*", mul_u, f32, f64);
|
||||||
|
reg_op!(lib, "/", div_u, f32, f64);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit operations
|
||||||
|
reg_op!(lib, "|", binary_or, INT);
|
||||||
|
reg_op!(lib, "&", binary_and, INT);
|
||||||
|
reg_op!(lib, "^", binary_xor, INT);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "|", binary_or, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "&", binary_and, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "^", binary_xor, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checked bit shifts
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
{
|
||||||
|
reg_op_x!(lib, "<<", shl, INT);
|
||||||
|
reg_op_x!(lib, ">>", shr, INT);
|
||||||
|
reg_op_x!(lib, "%", modulo, INT);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_op_x!(lib, "<<", shl, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op_x!(lib, ">>", shr, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op_x!(lib, "%", modulo, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unchecked bit shifts
|
||||||
|
#[cfg(feature = "unchecked")]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "<<", shl_u, INT, INT);
|
||||||
|
reg_op!(lib, ">>", shr_u, INT, INT);
|
||||||
|
reg_op!(lib, "%", modulo_u, INT);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "<<", shl_u, i64, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, ">>", shr_u, i64, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "%", modulo_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checked power
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
{
|
||||||
|
reg_binary(lib, "~", pow_i_i, result);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
reg_binary(lib, "~", pow_f_i, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unchecked power
|
||||||
|
#[cfg(feature = "unchecked")]
|
||||||
|
{
|
||||||
|
reg_binary(lib, "~", pow_i_i_u, map);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
reg_binary(lib, "~", pow_f_i_u, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floating-point modulo and power
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "%", modulo_u, f32, f64);
|
||||||
|
reg_binary(lib, "~", pow_f_f, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checked unary
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
{
|
||||||
|
reg_unary_x!(lib, "-", neg, INT);
|
||||||
|
reg_unary_x!(lib, "abs", abs, INT);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_unary_x!(lib, "-", neg, i8, i16, i32, i64, i128);
|
||||||
|
reg_unary_x!(lib, "abs", abs, i8, i16, i32, i64, i128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unchecked unary
|
||||||
|
#[cfg(feature = "unchecked")]
|
||||||
|
{
|
||||||
|
reg_unary!(lib, "-", neg_u, INT);
|
||||||
|
reg_unary!(lib, "abs", abs_u, INT);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_unary!(lib, "-", neg_u, i8, i16, i32, i64, i128);
|
||||||
|
reg_unary!(lib, "abs", abs_u, i8, i16, i32, i64, i128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floating-point unary
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
{
|
||||||
|
reg_unary!(lib, "-", neg_u, f32, f64);
|
||||||
|
reg_unary!(lib, "abs", abs_u, f32, f64);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_binary_mut, reg_trinary_mut, reg_unary_mut};
|
||||||
create_new_package, reg_binary, reg_binary_mut, reg_trinary_mut, reg_unary_mut, Package,
|
|
||||||
PackageLibrary, PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::Array;
|
use crate::engine::Array;
|
||||||
use crate::fn_register::{map_dynamic as map, map_identity as copy};
|
use crate::fn_register::{map_dynamic as map, map_identity as pass};
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
|
|
||||||
use crate::stdlib::ops::Deref;
|
use crate::stdlib::any::TypeId;
|
||||||
|
|
||||||
// Register array utility functions
|
// Register array utility functions
|
||||||
fn push<T: Variant + Clone>(list: &mut Array, item: T) {
|
fn push<T: Variant + Clone>(list: &mut Array, item: T) {
|
||||||
@ -31,16 +29,6 @@ fn pad<T: Variant + Clone>(list: &mut Array, len: INT, item: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BasicArrayPackage(PackageLibrary);
|
|
||||||
|
|
||||||
impl Deref for BasicArrayPackage {
|
|
||||||
type Target = PackageLibrary;
|
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
||||||
$(reg_binary_mut($lib, $op, $func::<$par>, map);)* };
|
$(reg_binary_mut($lib, $op, $func::<$par>, map);)* };
|
||||||
}
|
}
|
||||||
@ -48,92 +36,87 @@ macro_rules! reg_tri { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
|||||||
$(reg_trinary_mut($lib, $op, $func::<$par>, map);)* };
|
$(reg_trinary_mut($lib, $op, $func::<$par>, map);)* };
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package for BasicArrayPackage {
|
#[cfg(not(feature = "no_index"))]
|
||||||
fn new() -> Self {
|
def_package!(BasicArrayPackage:"Basic array utilities.", lib, {
|
||||||
let mut pkg = create_new_package();
|
reg_op!(lib, "push", push, INT, bool, char, String, Array, ());
|
||||||
Self::init(&mut pkg);
|
reg_tri!(lib, "pad", pad, INT, bool, char, String, Array, ());
|
||||||
Self(pkg.into())
|
reg_tri!(lib, "insert", ins, INT, bool, char, String, Array, ());
|
||||||
|
|
||||||
|
reg_binary_mut(lib, "append", |x: &mut Array, y: Array| x.extend(y), map);
|
||||||
|
reg_binary(
|
||||||
|
lib,
|
||||||
|
"+",
|
||||||
|
|mut x: Array, y: Array| {
|
||||||
|
x.extend(y);
|
||||||
|
x
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "push", push, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_tri!(lib, "pad", pad, i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
|
||||||
|
reg_tri!(lib, "insert", ins, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
#[cfg(not(feature = "no_float"))]
|
||||||
self.0.clone()
|
{
|
||||||
|
reg_op!(lib, "push", push, f32, f64);
|
||||||
|
reg_tri!(lib, "pad", pad, f32, f64);
|
||||||
|
reg_tri!(lib, "insert", ins, f32, f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
reg_unary_mut(
|
||||||
#[cfg(not(feature = "no_index"))]
|
lib,
|
||||||
{
|
"pop",
|
||||||
reg_op!(lib, "push", push, INT, bool, char, String, Array, ());
|
|list: &mut Array| list.pop().unwrap_or_else(|| Dynamic::from_unit()),
|
||||||
reg_tri!(lib, "pad", pad, INT, bool, char, String, Array, ());
|
pass,
|
||||||
reg_tri!(lib, "insert", ins, INT, bool, char, String, Array, ());
|
);
|
||||||
|
reg_unary_mut(
|
||||||
reg_binary_mut(lib, "append", |x: &mut Array, y: Array| x.extend(y), map);
|
lib,
|
||||||
reg_binary(
|
"shift",
|
||||||
lib,
|
|list: &mut Array| {
|
||||||
"+",
|
if !list.is_empty() {
|
||||||
|mut x: Array, y: Array| {
|
Dynamic::from_unit()
|
||||||
x.extend(y);
|
} else {
|
||||||
x
|
list.remove(0)
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "push", push, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_tri!(lib, "pad", pad, i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
|
|
||||||
reg_tri!(lib, "insert", ins, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
#[cfg(not(feature = "no_float"))]
|
pass,
|
||||||
{
|
);
|
||||||
reg_op!(lib, "push", push, f32, f64);
|
reg_binary_mut(
|
||||||
reg_tri!(lib, "pad", pad, f32, f64);
|
lib,
|
||||||
reg_tri!(lib, "insert", ins, f32, f64);
|
"remove",
|
||||||
|
|list: &mut Array, len: INT| {
|
||||||
|
if len < 0 || (len as usize) >= list.len() {
|
||||||
|
Dynamic::from_unit()
|
||||||
|
} else {
|
||||||
|
list.remove(len as usize)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
pass,
|
||||||
|
);
|
||||||
|
reg_unary_mut(lib, "len", |list: &mut Array| list.len() as INT, map);
|
||||||
|
reg_unary_mut(lib, "clear", |list: &mut Array| list.clear(), map);
|
||||||
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"truncate",
|
||||||
|
|list: &mut Array, len: INT| {
|
||||||
|
if len >= 0 {
|
||||||
|
list.truncate(len as usize);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
|
||||||
reg_unary_mut(
|
// Register array iterator
|
||||||
lib,
|
lib.type_iterators.insert(
|
||||||
"pop",
|
TypeId::of::<Array>(),
|
||||||
|list: &mut Array| list.pop().unwrap_or_else(|| Dynamic::from_unit()),
|
Box::new(|a: &Dynamic| {
|
||||||
copy,
|
Box::new(a.downcast_ref::<Array>().unwrap().clone().into_iter())
|
||||||
);
|
as Box<dyn Iterator<Item = Dynamic>>
|
||||||
reg_unary_mut(
|
}),
|
||||||
lib,
|
);
|
||||||
"shift",
|
});
|
||||||
|list: &mut Array| {
|
|
||||||
if !list.is_empty() {
|
|
||||||
Dynamic::from_unit()
|
|
||||||
} else {
|
|
||||||
list.remove(0)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
copy,
|
|
||||||
);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"remove",
|
|
||||||
|list: &mut Array, len: INT| {
|
|
||||||
if len < 0 || (len as usize) >= list.len() {
|
|
||||||
Dynamic::from_unit()
|
|
||||||
} else {
|
|
||||||
list.remove(len as usize)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
copy,
|
|
||||||
);
|
|
||||||
reg_unary_mut(lib, "len", |list: &mut Array| list.len() as INT, map);
|
|
||||||
reg_unary_mut(lib, "clear", |list: &mut Array| list.clear(), map);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"truncate",
|
|
||||||
|list: &mut Array, len: INT| {
|
|
||||||
if len >= 0 {
|
|
||||||
list.truncate(len as usize);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
use super::{
|
|
||||||
create_new_package, reg_binary, reg_binary_mut, reg_unary, Package, PackageLibrary,
|
|
||||||
PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::fn_register::map_dynamic as map;
|
|
||||||
use crate::parser::INT;
|
|
||||||
|
|
||||||
use crate::stdlib::ops::Deref;
|
|
||||||
|
|
||||||
pub struct BasicPackage(PackageLibrary);
|
|
||||||
|
|
||||||
impl Deref for BasicPackage {
|
|
||||||
type Target = PackageLibrary;
|
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package for BasicPackage {
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {}
|
|
||||||
}
|
|
@ -1,8 +1,6 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_trinary, reg_unary_mut, PackageStore};
|
||||||
create_new_package, reg_binary, reg_trinary, reg_unary_mut, Package, PackageLibrary,
|
|
||||||
PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::any::{Dynamic, Union, Variant};
|
use crate::any::{Dynamic, Union, Variant};
|
||||||
use crate::engine::{Array, Map};
|
use crate::engine::{Array, Map};
|
||||||
use crate::fn_register::map_dynamic as map;
|
use crate::fn_register::map_dynamic as map;
|
||||||
@ -10,15 +8,15 @@ use crate::parser::INT;
|
|||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
ops::{Add, Deref, Range},
|
ops::{Add, Range},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register range function
|
// Register range function
|
||||||
fn reg_range<T: Variant + Clone>(lib: &mut PackageLibraryStore)
|
fn reg_range<T: Variant + Clone>(lib: &mut PackageStore)
|
||||||
where
|
where
|
||||||
Range<T>: Iterator<Item = T>,
|
Range<T>: Iterator<Item = T>,
|
||||||
{
|
{
|
||||||
lib.1.insert(
|
lib.type_iterators.insert(
|
||||||
TypeId::of::<Range<T>>(),
|
TypeId::of::<Range<T>>(),
|
||||||
Box::new(|source: &Dynamic| {
|
Box::new(|source: &Dynamic| {
|
||||||
Box::new(
|
Box::new(
|
||||||
@ -57,13 +55,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reg_step<T>(lib: &mut PackageLibraryStore)
|
fn reg_step<T>(lib: &mut PackageStore)
|
||||||
where
|
where
|
||||||
for<'a> &'a T: Add<&'a T, Output = T>,
|
for<'a> &'a T: Add<&'a T, Output = T>,
|
||||||
T: Variant + Clone + PartialOrd,
|
T: Variant + Clone + PartialOrd,
|
||||||
StepRange<T>: Iterator<Item = T>,
|
StepRange<T>: Iterator<Item = T>,
|
||||||
{
|
{
|
||||||
lib.1.insert(
|
lib.type_iterators.insert(
|
||||||
TypeId::of::<StepRange<T>>(),
|
TypeId::of::<StepRange<T>>(),
|
||||||
Box::new(|source: &Dynamic| {
|
Box::new(|source: &Dynamic| {
|
||||||
Box::new(
|
Box::new(
|
||||||
@ -77,97 +75,44 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BasicIteratorPackage(PackageLibrary);
|
def_package!(BasicIteratorPackage:"Basic range iterators.", lib, {
|
||||||
|
fn get_range<T>(from: T, to: T) -> Range<T> {
|
||||||
impl Deref for BasicIteratorPackage {
|
from..to
|
||||||
type Target = PackageLibrary;
|
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package for BasicIteratorPackage {
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
reg_range::<INT>(lib);
|
||||||
self.0.clone()
|
reg_binary(lib, "range", get_range::<INT>, map);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
macro_rules! reg_range {
|
||||||
|
($self:expr, $x:expr, $( $y:ty ),*) => (
|
||||||
|
$(
|
||||||
|
reg_range::<$y>($self);
|
||||||
|
reg_binary($self, $x, get_range::<$y>, map);
|
||||||
|
)*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_range!(lib, "range", i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
reg_step::<INT>(lib);
|
||||||
#[cfg(not(feature = "no_index"))]
|
reg_trinary(lib, "range", StepRange::<INT>, map);
|
||||||
{
|
|
||||||
// Register array iterator
|
#[cfg(not(feature = "only_i32"))]
|
||||||
lib.1.insert(
|
#[cfg(not(feature = "only_i64"))]
|
||||||
TypeId::of::<Array>(),
|
{
|
||||||
Box::new(|a: &Dynamic| {
|
macro_rules! reg_step {
|
||||||
Box::new(a.downcast_ref::<Array>().unwrap().clone().into_iter())
|
($self:expr, $x:expr, $( $y:ty ),*) => (
|
||||||
as Box<dyn Iterator<Item = Dynamic>>
|
$(
|
||||||
}),
|
reg_step::<$y>($self);
|
||||||
);
|
reg_trinary($self, $x, StepRange::<$y>, map);
|
||||||
|
)*
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register map access functions
|
reg_step!(lib, "range", i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
{
|
|
||||||
fn map_get_keys(map: &mut Map) -> Vec<Dynamic> {
|
|
||||||
map.iter()
|
|
||||||
.map(|(k, _)| Dynamic(Union::Str(Box::new(k.to_string()))))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
fn map_get_values(map: &mut Map) -> Vec<Dynamic> {
|
|
||||||
map.iter().map(|(_, v)| v.clone()).collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
reg_unary_mut(lib, "keys", map_get_keys, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
reg_unary_mut(lib, "values", map_get_values, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_range<T>(from: T, to: T) -> Range<T> {
|
|
||||||
from..to
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_range::<INT>(lib);
|
|
||||||
reg_binary(lib, "range", get_range::<INT>, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
macro_rules! reg_range {
|
|
||||||
($self:expr, $x:expr, $( $y:ty ),*) => (
|
|
||||||
$(
|
|
||||||
reg_range::<$y>($self);
|
|
||||||
reg_binary($self, $x, get_range::<$y>, map);
|
|
||||||
)*
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_range!(lib, "range", i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_step::<INT>(lib);
|
|
||||||
reg_trinary(lib, "range", StepRange::<INT>, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
macro_rules! reg_step {
|
|
||||||
($self:expr, $x:expr, $( $y:ty ),*) => (
|
|
||||||
$(
|
|
||||||
reg_step::<$y>($self);
|
|
||||||
reg_trinary($self, $x, StepRange::<$y>, map);
|
|
||||||
)*
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_step!(lib, "range", i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
use super::{
|
use super::utils::reg_test;
|
||||||
create_new_package, reg_binary, reg_binary_mut, reg_unary, Package, PackageLibrary,
|
use super::{reg_binary, reg_binary_mut, reg_unary};
|
||||||
PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::fn_register::map_dynamic as map;
|
use crate::fn_register::map_dynamic as map;
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
|
|
||||||
use crate::stdlib::ops::Deref;
|
|
||||||
|
|
||||||
// Comparison operators
|
// Comparison operators
|
||||||
pub fn lt<T: PartialOrd>(x: T, y: T) -> bool {
|
pub fn lt<T: PartialOrd>(x: T, y: T) -> bool {
|
||||||
x < y
|
x < y
|
||||||
@ -43,71 +40,50 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
|||||||
$(reg_binary($lib, $op, $func::<$par>, map);)* };
|
$(reg_binary($lib, $op, $func::<$par>, map);)* };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LogicPackage(PackageLibrary);
|
def_package!(LogicPackage:"Logical operators.", lib, {
|
||||||
|
reg_op!(lib, "<", lt, INT, char);
|
||||||
|
reg_op!(lib, "<=", lte, INT, char);
|
||||||
|
reg_op!(lib, ">", gt, INT, char);
|
||||||
|
reg_op!(lib, ">=", gte, INT, char);
|
||||||
|
reg_op!(lib, "==", eq, INT, char, bool, ());
|
||||||
|
reg_op!(lib, "!=", ne, INT, char, bool, ());
|
||||||
|
|
||||||
impl Deref for LogicPackage {
|
// Special versions for strings - at least avoid copying the first string
|
||||||
type Target = PackageLibrary;
|
//reg_test(lib, "<", |x: &mut String, y: String| *x < y, |v| v, map);
|
||||||
|
reg_binary_mut(lib, "<", |x: &mut String, y: String| *x < y, map);
|
||||||
|
reg_binary_mut(lib, "<=", |x: &mut String, y: String| *x <= y, map);
|
||||||
|
reg_binary_mut(lib, ">", |x: &mut String, y: String| *x > y, map);
|
||||||
|
reg_binary_mut(lib, ">=", |x: &mut String, y: String| *x >= y, map);
|
||||||
|
reg_binary_mut(lib, "==", |x: &mut String, y: String| *x == y, map);
|
||||||
|
reg_binary_mut(lib, "!=", |x: &mut String, y: String| *x != y, map);
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
#[cfg(not(feature = "only_i32"))]
|
||||||
&self.0
|
#[cfg(not(feature = "only_i64"))]
|
||||||
}
|
{
|
||||||
}
|
reg_op!(lib, "<", lt, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "<=", lte, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
impl Package for LogicPackage {
|
reg_op!(lib, ">", gt, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
fn new() -> Self {
|
reg_op!(lib, ">=", gte, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
let mut pkg = create_new_package();
|
reg_op!(lib, "==", eq, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
Self::init(&mut pkg);
|
reg_op!(lib, "!=", ne, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
Self(pkg.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
#[cfg(not(feature = "no_float"))]
|
||||||
self.0.clone()
|
{
|
||||||
|
reg_op!(lib, "<", lt, f32, f64);
|
||||||
|
reg_op!(lib, "<=", lte, f32, f64);
|
||||||
|
reg_op!(lib, ">", gt, f32, f64);
|
||||||
|
reg_op!(lib, ">=", gte, f32, f64);
|
||||||
|
reg_op!(lib, "==", eq, f32, f64);
|
||||||
|
reg_op!(lib, "!=", ne, f32, f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
// `&&` and `||` are treated specially as they short-circuit.
|
||||||
reg_op!(lib, "<", lt, INT, char);
|
// They are implemented as special `Expr` instances, not function calls.
|
||||||
reg_op!(lib, "<=", lte, INT, char);
|
//reg_op!(lib, "||", or, bool);
|
||||||
reg_op!(lib, ">", gt, INT, char);
|
//reg_op!(lib, "&&", and, bool);
|
||||||
reg_op!(lib, ">=", gte, INT, char);
|
|
||||||
reg_op!(lib, "==", eq, INT, char, bool, ());
|
|
||||||
reg_op!(lib, "!=", ne, INT, char, bool, ());
|
|
||||||
|
|
||||||
// Special versions for strings - at least avoid copying the first string
|
reg_binary(lib, "|", or, map);
|
||||||
reg_binary_mut(lib, "<", |x: &mut String, y: String| *x < y, map);
|
reg_binary(lib, "&", and, map);
|
||||||
reg_binary_mut(lib, "<=", |x: &mut String, y: String| *x <= y, map);
|
reg_unary(lib, "!", not, map);
|
||||||
reg_binary_mut(lib, ">", |x: &mut String, y: String| *x > y, map);
|
});
|
||||||
reg_binary_mut(lib, ">=", |x: &mut String, y: String| *x >= y, map);
|
|
||||||
reg_binary_mut(lib, "==", |x: &mut String, y: String| *x == y, map);
|
|
||||||
reg_binary_mut(lib, "!=", |x: &mut String, y: String| *x != y, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "<", lt, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "<=", lte, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, ">", gt, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, ">=", gte, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "==", eq, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
reg_op!(lib, "!=", ne, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, "<", lt, f32, f64);
|
|
||||||
reg_op!(lib, "<=", lte, f32, f64);
|
|
||||||
reg_op!(lib, ">", gt, f32, f64);
|
|
||||||
reg_op!(lib, ">=", gte, f32, f64);
|
|
||||||
reg_op!(lib, "==", eq, f32, f64);
|
|
||||||
reg_op!(lib, "!=", ne, f32, f64);
|
|
||||||
}
|
|
||||||
|
|
||||||
// `&&` and `||` are treated specially as they short-circuit.
|
|
||||||
// They are implemented as special `Expr` instances, not function calls.
|
|
||||||
//reg_op!(lib, "||", or, bool);
|
|
||||||
//reg_op!(lib, "&&", and, bool);
|
|
||||||
|
|
||||||
reg_binary(lib, "|", or, map);
|
|
||||||
reg_binary(lib, "&", and, map);
|
|
||||||
reg_unary(lib, "!", not, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,75 +1,62 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_binary_mut, reg_unary_mut};
|
||||||
create_new_package, reg_binary, reg_binary_mut, reg_unary_mut, Package, PackageLibrary,
|
|
||||||
PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::engine::Map;
|
use crate::engine::Map;
|
||||||
use crate::fn_register::map_dynamic as map;
|
use crate::fn_register::map_dynamic as map;
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
|
|
||||||
use crate::stdlib::ops::Deref;
|
fn map_get_keys(map: &mut Map) -> Vec<Dynamic> {
|
||||||
|
map.iter()
|
||||||
pub struct BasicMapPackage(PackageLibrary);
|
.map(|(k, _)| Dynamic::from_string(k.to_string()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
impl Deref for BasicMapPackage {
|
}
|
||||||
type Target = PackageLibrary;
|
fn map_get_values(map: &mut Map) -> Vec<Dynamic> {
|
||||||
|
map.iter().map(|(_, v)| v.clone()).collect::<Vec<_>>()
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package for BasicMapPackage {
|
#[cfg(not(feature = "no_object"))]
|
||||||
fn new() -> Self {
|
def_package!(BasicMapPackage:"Basic object map utilities.", lib, {
|
||||||
let mut pkg = create_new_package();
|
reg_binary_mut(
|
||||||
Self::init(&mut pkg);
|
lib,
|
||||||
Self(pkg.into())
|
"has",
|
||||||
}
|
|map: &mut Map, prop: String| map.contains_key(&prop),
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_unary_mut(lib, "len", |map: &mut Map| map.len() as INT, map);
|
||||||
|
reg_unary_mut(lib, "clear", |map: &mut Map| map.clear(), map);
|
||||||
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"remove",
|
||||||
|
|x: &mut Map, name: String| x.remove(&name).unwrap_or_else(|| Dynamic::from_unit()),
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"mixin",
|
||||||
|
|map1: &mut Map, map2: Map| {
|
||||||
|
map2.into_iter().for_each(|(key, value)| {
|
||||||
|
map1.insert(key, value);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_binary(
|
||||||
|
lib,
|
||||||
|
"+",
|
||||||
|
|mut map1: Map, map2: Map| {
|
||||||
|
map2.into_iter().for_each(|(key, value)| {
|
||||||
|
map1.insert(key, value);
|
||||||
|
});
|
||||||
|
map1
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
// Register map access functions
|
||||||
self.0.clone()
|
#[cfg(not(feature = "no_index"))]
|
||||||
}
|
reg_unary_mut(lib, "keys", map_get_keys, map);
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
#[cfg(not(feature = "no_index"))]
|
||||||
// Register map functions
|
reg_unary_mut(lib, "values", map_get_values, map);
|
||||||
#[cfg(not(feature = "no_object"))]
|
});
|
||||||
{
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"has",
|
|
||||||
|map: &mut Map, prop: String| map.contains_key(&prop),
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_unary_mut(lib, "len", |map: &mut Map| map.len() as INT, map);
|
|
||||||
reg_unary_mut(lib, "clear", |map: &mut Map| map.clear(), map);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"remove",
|
|
||||||
|x: &mut Map, name: String| x.remove(&name).unwrap_or_else(|| Dynamic::from_unit()),
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"mixin",
|
|
||||||
|map1: &mut Map, map2: Map| {
|
|
||||||
map2.into_iter().for_each(|(key, value)| {
|
|
||||||
map1.insert(key, value);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_binary(
|
|
||||||
lib,
|
|
||||||
"+",
|
|
||||||
|mut map1: Map, map2: Map| {
|
|
||||||
map2.into_iter().for_each(|(key, value)| {
|
|
||||||
map1.insert(key, value);
|
|
||||||
});
|
|
||||||
map1
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_unary};
|
||||||
create_new_package, reg_binary, reg_unary, Package, PackageLibrary, PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::fn_register::{map_dynamic as map, map_result as result};
|
use crate::fn_register::{map_dynamic as map, map_result as result};
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
@ -10,145 +9,123 @@ use crate::token::Position;
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::parser::FLOAT;
|
use crate::parser::FLOAT;
|
||||||
|
|
||||||
use crate::stdlib::{i32, i64, ops::Deref};
|
use crate::stdlib::{i32, i64};
|
||||||
|
|
||||||
#[cfg(feature = "only_i32")]
|
#[cfg(feature = "only_i32")]
|
||||||
pub const MAX_INT: INT = i32::MAX;
|
pub const MAX_INT: INT = i32::MAX;
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
pub const MAX_INT: INT = i64::MAX;
|
pub const MAX_INT: INT = i64::MAX;
|
||||||
|
|
||||||
pub struct BasicMathPackage(PackageLibrary);
|
def_package!(BasicMathPackage:"Basic mathematic functions.", lib, {
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
{
|
||||||
|
// Advanced math functions
|
||||||
|
reg_unary(lib, "sin", |x: FLOAT| x.to_radians().sin(), map);
|
||||||
|
reg_unary(lib, "cos", |x: FLOAT| x.to_radians().cos(), map);
|
||||||
|
reg_unary(lib, "tan", |x: FLOAT| x.to_radians().tan(), map);
|
||||||
|
reg_unary(lib, "sinh", |x: FLOAT| x.to_radians().sinh(), map);
|
||||||
|
reg_unary(lib, "cosh", |x: FLOAT| x.to_radians().cosh(), map);
|
||||||
|
reg_unary(lib, "tanh", |x: FLOAT| x.to_radians().tanh(), map);
|
||||||
|
reg_unary(lib, "asin", |x: FLOAT| x.asin().to_degrees(), map);
|
||||||
|
reg_unary(lib, "acos", |x: FLOAT| x.acos().to_degrees(), map);
|
||||||
|
reg_unary(lib, "atan", |x: FLOAT| x.atan().to_degrees(), map);
|
||||||
|
reg_unary(lib, "asinh", |x: FLOAT| x.asinh().to_degrees(), map);
|
||||||
|
reg_unary(lib, "acosh", |x: FLOAT| x.acosh().to_degrees(), map);
|
||||||
|
reg_unary(lib, "atanh", |x: FLOAT| x.atanh().to_degrees(), map);
|
||||||
|
reg_unary(lib, "sqrt", |x: FLOAT| x.sqrt(), map);
|
||||||
|
reg_unary(lib, "exp", |x: FLOAT| x.exp(), map);
|
||||||
|
reg_unary(lib, "ln", |x: FLOAT| x.ln(), map);
|
||||||
|
reg_binary(lib, "log", |x: FLOAT, base: FLOAT| x.log(base), map);
|
||||||
|
reg_unary(lib, "log10", |x: FLOAT| x.log10(), map);
|
||||||
|
reg_unary(lib, "floor", |x: FLOAT| x.floor(), map);
|
||||||
|
reg_unary(lib, "ceiling", |x: FLOAT| x.ceil(), map);
|
||||||
|
reg_unary(lib, "round", |x: FLOAT| x.ceil(), map);
|
||||||
|
reg_unary(lib, "int", |x: FLOAT| x.trunc(), map);
|
||||||
|
reg_unary(lib, "fraction", |x: FLOAT| x.fract(), map);
|
||||||
|
reg_unary(lib, "is_nan", |x: FLOAT| x.is_nan(), map);
|
||||||
|
reg_unary(lib, "is_finite", |x: FLOAT| x.is_finite(), map);
|
||||||
|
reg_unary(lib, "is_infinite", |x: FLOAT| x.is_infinite(), map);
|
||||||
|
|
||||||
impl Deref for BasicMathPackage {
|
// Register conversion functions
|
||||||
type Target = PackageLibrary;
|
reg_unary(lib, "to_float", |x: INT| x as FLOAT, map);
|
||||||
|
reg_unary(lib, "to_float", |x: f32| x as FLOAT, map);
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package for BasicMathPackage {
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
// Advanced math functions
|
|
||||||
reg_unary(lib, "sin", |x: FLOAT| x.to_radians().sin(), map);
|
|
||||||
reg_unary(lib, "cos", |x: FLOAT| x.to_radians().cos(), map);
|
|
||||||
reg_unary(lib, "tan", |x: FLOAT| x.to_radians().tan(), map);
|
|
||||||
reg_unary(lib, "sinh", |x: FLOAT| x.to_radians().sinh(), map);
|
|
||||||
reg_unary(lib, "cosh", |x: FLOAT| x.to_radians().cosh(), map);
|
|
||||||
reg_unary(lib, "tanh", |x: FLOAT| x.to_radians().tanh(), map);
|
|
||||||
reg_unary(lib, "asin", |x: FLOAT| x.asin().to_degrees(), map);
|
|
||||||
reg_unary(lib, "acos", |x: FLOAT| x.acos().to_degrees(), map);
|
|
||||||
reg_unary(lib, "atan", |x: FLOAT| x.atan().to_degrees(), map);
|
|
||||||
reg_unary(lib, "asinh", |x: FLOAT| x.asinh().to_degrees(), map);
|
|
||||||
reg_unary(lib, "acosh", |x: FLOAT| x.acosh().to_degrees(), map);
|
|
||||||
reg_unary(lib, "atanh", |x: FLOAT| x.atanh().to_degrees(), map);
|
|
||||||
reg_unary(lib, "sqrt", |x: FLOAT| x.sqrt(), map);
|
|
||||||
reg_unary(lib, "exp", |x: FLOAT| x.exp(), map);
|
|
||||||
reg_unary(lib, "ln", |x: FLOAT| x.ln(), map);
|
|
||||||
reg_binary(lib, "log", |x: FLOAT, base: FLOAT| x.log(base), map);
|
|
||||||
reg_unary(lib, "log10", |x: FLOAT| x.log10(), map);
|
|
||||||
reg_unary(lib, "floor", |x: FLOAT| x.floor(), map);
|
|
||||||
reg_unary(lib, "ceiling", |x: FLOAT| x.ceil(), map);
|
|
||||||
reg_unary(lib, "round", |x: FLOAT| x.ceil(), map);
|
|
||||||
reg_unary(lib, "int", |x: FLOAT| x.trunc(), map);
|
|
||||||
reg_unary(lib, "fraction", |x: FLOAT| x.fract(), map);
|
|
||||||
reg_unary(lib, "is_nan", |x: FLOAT| x.is_nan(), map);
|
|
||||||
reg_unary(lib, "is_finite", |x: FLOAT| x.is_finite(), map);
|
|
||||||
reg_unary(lib, "is_infinite", |x: FLOAT| x.is_infinite(), map);
|
|
||||||
|
|
||||||
// Register conversion functions
|
|
||||||
reg_unary(lib, "to_float", |x: INT| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: f32| x as FLOAT, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_unary(lib, "to_float", |x: i8| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: u8| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: i16| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: u16| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: i32| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: u32| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: i64| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: u64| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: i128| x as FLOAT, map);
|
|
||||||
reg_unary(lib, "to_float", |x: u128| x as FLOAT, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_unary(lib, "to_int", |ch: char| ch as INT, map);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
{
|
{
|
||||||
reg_unary(lib, "to_int", |x: i8| x as INT, map);
|
reg_unary(lib, "to_float", |x: i8| x as FLOAT, map);
|
||||||
reg_unary(lib, "to_int", |x: u8| x as INT, map);
|
reg_unary(lib, "to_float", |x: u8| x as FLOAT, map);
|
||||||
reg_unary(lib, "to_int", |x: i16| x as INT, map);
|
reg_unary(lib, "to_float", |x: i16| x as FLOAT, map);
|
||||||
reg_unary(lib, "to_int", |x: u16| x as INT, map);
|
reg_unary(lib, "to_float", |x: u16| x as FLOAT, map);
|
||||||
}
|
reg_unary(lib, "to_float", |x: i32| x as FLOAT, map);
|
||||||
|
reg_unary(lib, "to_float", |x: u32| x as FLOAT, map);
|
||||||
#[cfg(not(feature = "only_i32"))]
|
reg_unary(lib, "to_float", |x: i64| x as FLOAT, map);
|
||||||
{
|
reg_unary(lib, "to_float", |x: u64| x as FLOAT, map);
|
||||||
reg_unary(lib, "to_int", |x: i32| x as INT, map);
|
reg_unary(lib, "to_float", |x: i128| x as FLOAT, map);
|
||||||
reg_unary(lib, "to_int", |x: u64| x as INT, map);
|
reg_unary(lib, "to_float", |x: u128| x as FLOAT, map);
|
||||||
|
|
||||||
#[cfg(feature = "only_i64")]
|
|
||||||
reg_unary(lib, "to_int", |x: u32| x as INT, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
reg_unary(
|
|
||||||
lib,
|
|
||||||
"to_int",
|
|
||||||
|x: f32| {
|
|
||||||
if x > (MAX_INT as f32) {
|
|
||||||
return Err(EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Integer overflow: to_int({})", x),
|
|
||||||
Position::none(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(x.trunc() as INT)
|
|
||||||
},
|
|
||||||
result,
|
|
||||||
);
|
|
||||||
reg_unary(
|
|
||||||
lib,
|
|
||||||
"to_int",
|
|
||||||
|x: FLOAT| {
|
|
||||||
if x > (MAX_INT as FLOAT) {
|
|
||||||
return Err(EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Integer overflow: to_int({})", x),
|
|
||||||
Position::none(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(x.trunc() as INT)
|
|
||||||
},
|
|
||||||
result,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
{
|
|
||||||
reg_unary(lib, "to_int", |x: f32| x as INT, map);
|
|
||||||
reg_unary(lib, "to_int", |x: f64| x as INT, map);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
reg_unary(lib, "to_int", |ch: char| ch as INT, map);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_unary(lib, "to_int", |x: i8| x as INT, map);
|
||||||
|
reg_unary(lib, "to_int", |x: u8| x as INT, map);
|
||||||
|
reg_unary(lib, "to_int", |x: i16| x as INT, map);
|
||||||
|
reg_unary(lib, "to_int", |x: u16| x as INT, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
{
|
||||||
|
reg_unary(lib, "to_int", |x: i32| x as INT, map);
|
||||||
|
reg_unary(lib, "to_int", |x: u64| x as INT, map);
|
||||||
|
|
||||||
|
#[cfg(feature = "only_i64")]
|
||||||
|
reg_unary(lib, "to_int", |x: u32| x as INT, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
{
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
{
|
||||||
|
reg_unary(
|
||||||
|
lib,
|
||||||
|
"to_int",
|
||||||
|
|x: f32| {
|
||||||
|
if x > (MAX_INT as f32) {
|
||||||
|
return Err(EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Integer overflow: to_int({})", x),
|
||||||
|
Position::none(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(x.trunc() as INT)
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
reg_unary(
|
||||||
|
lib,
|
||||||
|
"to_int",
|
||||||
|
|x: FLOAT| {
|
||||||
|
if x > (MAX_INT as FLOAT) {
|
||||||
|
return Err(EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Integer overflow: to_int({})", x),
|
||||||
|
Position::none(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(x.trunc() as INT)
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unchecked")]
|
||||||
|
{
|
||||||
|
reg_unary(lib, "to_int", |x: f32| x as INT, map);
|
||||||
|
reg_unary(lib, "to_int", |x: f64| x as INT, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
//! This module contains all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
||||||
use crate::engine::{calc_fn_spec, FnAny, FnCallArgs, IteratorFn};
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::engine::{FnAny, IteratorFn};
|
||||||
any::{type_name, TypeId},
|
|
||||||
boxed::Box,
|
use crate::stdlib::{any::TypeId, boxed::Box, collections::HashMap, rc::Rc, sync::Arc};
|
||||||
collections::HashMap,
|
|
||||||
ops::Deref,
|
|
||||||
rc::Rc,
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod arithmetic;
|
mod arithmetic;
|
||||||
mod array_basic;
|
mod array_basic;
|
||||||
@ -23,6 +15,7 @@ mod pkg_std;
|
|||||||
mod string_basic;
|
mod string_basic;
|
||||||
mod string_more;
|
mod string_more;
|
||||||
mod time_basic;
|
mod time_basic;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
pub use arithmetic::ArithmeticPackage;
|
pub use arithmetic::ArithmeticPackage;
|
||||||
pub use array_basic::BasicArrayPackage;
|
pub use array_basic::BasicArrayPackage;
|
||||||
@ -36,272 +29,43 @@ pub use string_basic::BasicStringPackage;
|
|||||||
pub use string_more::MoreStringPackage;
|
pub use string_more::MoreStringPackage;
|
||||||
pub use time_basic::BasicTimePackage;
|
pub use time_basic::BasicTimePackage;
|
||||||
|
|
||||||
pub trait Package: Deref {
|
pub use utils::*;
|
||||||
|
|
||||||
|
/// Trait that all packages must implement.
|
||||||
|
pub trait Package {
|
||||||
|
/// Create a new instance of a package.
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn init(lib: &mut PackageLibraryStore);
|
|
||||||
|
/// Register all the functions in a package into a store.
|
||||||
|
fn init(lib: &mut PackageStore);
|
||||||
|
|
||||||
|
/// Retrieve the generic package library from this package.
|
||||||
fn get(&self) -> PackageLibrary;
|
fn get(&self) -> PackageLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PackageLibraryStore = (HashMap<u64, Box<FnAny>>, HashMap<TypeId, Box<IteratorFn>>);
|
/// Type to store all functions in the package.
|
||||||
|
pub struct PackageStore {
|
||||||
|
/// All functions, keyed by a hash created from the function name and parameter types.
|
||||||
|
pub functions: HashMap<u64, Box<FnAny>>,
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
/// All iterator functions, keyed by the type producing the iterator.
|
||||||
pub type PackageLibrary = Rc<PackageLibraryStore>;
|
pub type_iterators: HashMap<TypeId, Box<IteratorFn>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
impl PackageStore {
|
||||||
pub type PackageLibrary = Arc<PackageLibraryStore>;
|
/// Create a new `PackageStore`.
|
||||||
|
pub fn new() -> Self {
|
||||||
fn check_num_args(
|
Self {
|
||||||
name: &str,
|
functions: HashMap::new(),
|
||||||
num_args: usize,
|
type_iterators: HashMap::new(),
|
||||||
args: &mut FnCallArgs,
|
}
|
||||||
pos: Position,
|
|
||||||
) -> Result<(), Box<EvalAltResult>> {
|
|
||||||
if args.len() != num_args {
|
|
||||||
Err(Box::new(EvalAltResult::ErrorFunctionArgsMismatch(
|
|
||||||
name.to_string(),
|
|
||||||
num_args,
|
|
||||||
args.len(),
|
|
||||||
pos,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_new_package() -> PackageLibraryStore {
|
/// Type which `Rc`-wraps a `PackageStore` to facilitate sharing library instances.
|
||||||
(HashMap::new(), HashMap::new())
|
#[cfg(not(feature = "sync"))]
|
||||||
}
|
pub type PackageLibrary = Rc<PackageStore>;
|
||||||
|
|
||||||
fn reg_none<R>(
|
/// Type which `Arc`-wraps a `PackageStore` to facilitate sharing library instances.
|
||||||
lib: &mut PackageLibraryStore,
|
#[cfg(feature = "sync")]
|
||||||
fn_name: &'static str,
|
pub type PackageLibrary = Arc<PackageStore>;
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn() -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn() -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
let hash = calc_fn_spec(fn_name, ([] as [TypeId; 0]).iter().cloned());
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 0, args, pos)?;
|
|
||||||
|
|
||||||
let r = func();
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reg_unary<T: Variant + Clone, R>(
|
|
||||||
lib: &mut PackageLibraryStore,
|
|
||||||
fn_name: &'static str,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(T) -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(T) -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
//println!("register {}({})", fn_name, type_name::<T>());
|
|
||||||
|
|
||||||
let hash = calc_fn_spec(fn_name, [TypeId::of::<T>()].iter().cloned());
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 1, args, pos)?;
|
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
|
||||||
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
|
|
||||||
let r = func(x.clone());
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reg_unary_mut<T: Variant + Clone, R>(
|
|
||||||
lib: &mut PackageLibraryStore,
|
|
||||||
fn_name: &'static str,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&mut T) -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&mut T) -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
//println!("register {}(&mut {})", fn_name, type_name::<T>());
|
|
||||||
|
|
||||||
let hash = calc_fn_spec(fn_name, [TypeId::of::<T>()].iter().cloned());
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 1, args, pos)?;
|
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
|
||||||
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
|
|
||||||
let r = func(x);
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reg_binary<A: Variant + Clone, B: Variant + Clone, R>(
|
|
||||||
lib: &mut PackageLibraryStore,
|
|
||||||
fn_name: &'static str,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(A, B) -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
//println!("register {}({}, {})", fn_name, type_name::<A>(), type_name::<B>());
|
|
||||||
|
|
||||||
let hash = calc_fn_spec(
|
|
||||||
fn_name,
|
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 2, args, pos)?;
|
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
|
|
||||||
let r = func(x.clone(), y.clone());
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reg_binary_mut<A: Variant + Clone, B: Variant + Clone, R>(
|
|
||||||
lib: &mut PackageLibraryStore,
|
|
||||||
fn_name: &'static str,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
//println!("register {}(&mut {}, {})", fn_name, type_name::<A>(), type_name::<B>());
|
|
||||||
|
|
||||||
let hash = calc_fn_spec(
|
|
||||||
fn_name,
|
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 2, args, pos)?;
|
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
|
|
||||||
let r = func(x, y.clone());
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R>(
|
|
||||||
lib: &mut PackageLibraryStore,
|
|
||||||
fn_name: &'static str,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(A, B, C) -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
//println!("register {}({}, {}, {})", fn_name, type_name::<A>(), type_name::<B>(), type_name::<C>());
|
|
||||||
|
|
||||||
let hash = calc_fn_spec(
|
|
||||||
fn_name,
|
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
|
||||||
.iter()
|
|
||||||
.cloned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 3, args, pos)?;
|
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
|
|
||||||
let r = func(x.clone(), y.clone(), z.clone());
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R>(
|
|
||||||
lib: &mut PackageLibraryStore,
|
|
||||||
fn_name: &'static str,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> R + 'static,
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> R + Send + Sync + 'static,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ 'static,
|
|
||||||
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
|
||||||
+ Send
|
|
||||||
+ Sync
|
|
||||||
+ 'static,
|
|
||||||
) {
|
|
||||||
//println!("register {}(&mut {}, {}, {})", fn_name, type_name::<A>(), type_name::<B>(), type_name::<C>());
|
|
||||||
|
|
||||||
let hash = calc_fn_spec(
|
|
||||||
fn_name,
|
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
|
||||||
.iter()
|
|
||||||
.cloned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
|
||||||
check_num_args(fn_name, 3, args, pos)?;
|
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
|
||||||
|
|
||||||
let r = func(x, y.clone(), z.clone());
|
|
||||||
map_result(r, pos)
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.0.insert(hash, f);
|
|
||||||
}
|
|
||||||
|
@ -1,37 +1,13 @@
|
|||||||
use super::arithmetic::ArithmeticPackage;
|
use super::arithmetic::ArithmeticPackage;
|
||||||
use super::create_new_package;
|
|
||||||
use super::iter_basic::BasicIteratorPackage;
|
use super::iter_basic::BasicIteratorPackage;
|
||||||
use super::logic::LogicPackage;
|
use super::logic::LogicPackage;
|
||||||
use super::string_basic::BasicStringPackage;
|
use super::string_basic::BasicStringPackage;
|
||||||
use super::{Package, PackageLibrary, PackageLibraryStore};
|
|
||||||
|
|
||||||
use crate::stdlib::ops::Deref;
|
use crate::def_package;
|
||||||
|
|
||||||
pub struct CorePackage(PackageLibrary);
|
def_package!(CorePackage:"_Core_ package containing basic facilities.", lib, {
|
||||||
|
ArithmeticPackage::init(lib);
|
||||||
impl Deref for CorePackage {
|
LogicPackage::init(lib);
|
||||||
type Target = PackageLibrary;
|
BasicStringPackage::init(lib);
|
||||||
|
BasicIteratorPackage::init(lib);
|
||||||
fn deref(&self) -> &PackageLibrary {
|
});
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package for CorePackage {
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
|
||||||
ArithmeticPackage::init(lib);
|
|
||||||
LogicPackage::init(lib);
|
|
||||||
BasicStringPackage::init(lib);
|
|
||||||
BasicIteratorPackage::init(lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,37 +4,16 @@ use super::math_basic::BasicMathPackage;
|
|||||||
use super::pkg_core::CorePackage;
|
use super::pkg_core::CorePackage;
|
||||||
use super::string_more::MoreStringPackage;
|
use super::string_more::MoreStringPackage;
|
||||||
use super::time_basic::BasicTimePackage;
|
use super::time_basic::BasicTimePackage;
|
||||||
use super::{create_new_package, Package, PackageLibrary, PackageLibraryStore};
|
|
||||||
|
|
||||||
use crate::stdlib::ops::Deref;
|
use crate::def_package;
|
||||||
|
|
||||||
pub struct StandardPackage(PackageLibrary);
|
def_package!(StandardPackage:"_Standard_ package containing all built-in features.", lib, {
|
||||||
|
CorePackage::init(lib);
|
||||||
impl Deref for StandardPackage {
|
BasicMathPackage::init(lib);
|
||||||
type Target = PackageLibrary;
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
BasicArrayPackage::init(lib);
|
||||||
fn deref(&self) -> &PackageLibrary {
|
#[cfg(not(feature = "no_object"))]
|
||||||
&self.0
|
BasicMapPackage::init(lib);
|
||||||
}
|
BasicTimePackage::init(lib);
|
||||||
}
|
MoreStringPackage::init(lib);
|
||||||
|
});
|
||||||
impl Package for StandardPackage {
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
|
||||||
CorePackage::init(lib);
|
|
||||||
BasicMathPackage::init(lib);
|
|
||||||
BasicArrayPackage::init(lib);
|
|
||||||
BasicMapPackage::init(lib);
|
|
||||||
BasicTimePackage::init(lib);
|
|
||||||
MoreStringPackage::init(lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_binary_mut, reg_none, reg_unary, reg_unary_mut};
|
||||||
create_new_package, reg_binary, reg_binary_mut, reg_none, reg_unary, reg_unary_mut, Package,
|
|
||||||
PackageLibrary, PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::engine::{Array, Map, FUNC_TO_STRING, KEYWORD_DEBUG, KEYWORD_PRINT};
|
use crate::engine::{Array, Map, FUNC_TO_STRING, KEYWORD_DEBUG, KEYWORD_PRINT};
|
||||||
use crate::fn_register::map_dynamic as map;
|
use crate::fn_register::map_dynamic as map;
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
@ -10,7 +8,6 @@ use crate::parser::INT;
|
|||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
format,
|
format,
|
||||||
ops::Deref,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register print and debug
|
// Register print and debug
|
||||||
@ -28,97 +25,74 @@ macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
|||||||
$(reg_unary_mut($lib, $op, $func::<$par>, map);)* };
|
$(reg_unary_mut($lib, $op, $func::<$par>, map);)* };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BasicStringPackage(PackageLibrary);
|
def_package!(BasicStringPackage:"Basic string utilities, including printing.", lib, {
|
||||||
|
reg_op!(lib, KEYWORD_PRINT, to_string, INT, bool, char);
|
||||||
|
reg_op!(lib, FUNC_TO_STRING, to_string, INT, bool, char);
|
||||||
|
|
||||||
impl Deref for BasicStringPackage {
|
reg_none(lib, KEYWORD_PRINT, || "".to_string(), map);
|
||||||
type Target = PackageLibrary;
|
reg_unary(lib, KEYWORD_PRINT, |_: ()| "".to_string(), map);
|
||||||
|
reg_unary(lib, FUNC_TO_STRING, |_: ()| "".to_string(), map);
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
reg_unary_mut(lib, KEYWORD_PRINT, |s: &mut String| s.clone(), map);
|
||||||
&self.0
|
reg_unary_mut(lib, FUNC_TO_STRING, |s: &mut String| s.clone(), map);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package for BasicStringPackage {
|
reg_op!(lib, KEYWORD_DEBUG, to_debug, INT, bool, (), char, String);
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
#[cfg(not(feature = "only_i32"))]
|
||||||
Self::init(&mut pkg);
|
#[cfg(not(feature = "only_i64"))]
|
||||||
Self(pkg.into())
|
{
|
||||||
|
reg_op!(lib, KEYWORD_PRINT, to_string, i8, u8, i16, u16, i32, u32);
|
||||||
|
reg_op!(lib, FUNC_TO_STRING, to_string, i8, u8, i16, u16, i32, u32);
|
||||||
|
reg_op!(lib, KEYWORD_DEBUG, to_debug, i8, u8, i16, u16, i32, u32);
|
||||||
|
reg_op!(lib, KEYWORD_PRINT, to_string, i64, u64, i128, u128);
|
||||||
|
reg_op!(lib, FUNC_TO_STRING, to_string, i64, u64, i128, u128);
|
||||||
|
reg_op!(lib, KEYWORD_DEBUG, to_debug, i64, u64, i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
#[cfg(not(feature = "no_float"))]
|
||||||
self.0.clone()
|
{
|
||||||
|
reg_op!(lib, KEYWORD_PRINT, to_string, f32, f64);
|
||||||
|
reg_op!(lib, FUNC_TO_STRING, to_string, f32, f64);
|
||||||
|
reg_op!(lib, KEYWORD_DEBUG, to_debug, f32, f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
#[cfg(not(feature = "no_index"))]
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_string, String, INT, bool);
|
{
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_string, String, INT, bool);
|
reg_op!(lib, KEYWORD_PRINT, to_debug, Array);
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_string, String, char, String);
|
reg_op!(lib, FUNC_TO_STRING, to_debug, Array);
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_string, String, char, String);
|
reg_op!(lib, KEYWORD_DEBUG, to_debug, Array);
|
||||||
reg_none(lib, KEYWORD_PRINT, || "".to_string(), map);
|
|
||||||
reg_unary(lib, KEYWORD_PRINT, |_: ()| "".to_string(), map);
|
|
||||||
reg_unary(lib, FUNC_TO_STRING, |_: ()| "".to_string(), map);
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, INT, bool, ());
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, char, String);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_string, String, i8, u8, i16, u16);
|
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_string, String, i8, u8, i16, u16);
|
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_string, String, i32, u32, i64, u64);
|
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_string, String, i32, u32, i64, u64);
|
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_string, String, i128, u128);
|
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_string, String, i128, u128);
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, i8, u8, i16, u16);
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, i32, u32, i64, u64);
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, i128, u128);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_string, String, f32, f64);
|
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_string, String, f32, f64);
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, f32, f64);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
{
|
|
||||||
reg_op!(lib, KEYWORD_PRINT, to_debug, String, Array);
|
|
||||||
reg_op!(lib, FUNC_TO_STRING, to_debug, String, Array);
|
|
||||||
reg_op!(lib, KEYWORD_DEBUG, to_debug, String, Array);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
{
|
|
||||||
reg_unary_mut(lib, KEYWORD_PRINT, format_map, map);
|
|
||||||
reg_unary_mut(lib, FUNC_TO_STRING, format_map, map);
|
|
||||||
reg_unary_mut(lib, KEYWORD_DEBUG, format_map, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_binary(
|
|
||||||
lib,
|
|
||||||
"+",
|
|
||||||
|mut s: String, ch: char| {
|
|
||||||
s.push(ch);
|
|
||||||
s
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_binary(
|
|
||||||
lib,
|
|
||||||
"+",
|
|
||||||
|mut s: String, s2: String| {
|
|
||||||
s.push_str(&s2);
|
|
||||||
s
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_binary_mut(lib, "append", |s: &mut String, ch: char| s.push(ch), map);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"append",
|
|
||||||
|s: &mut String, add: String| s.push_str(&add),
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
{
|
||||||
|
reg_unary_mut(lib, KEYWORD_PRINT, format_map, map);
|
||||||
|
reg_unary_mut(lib, FUNC_TO_STRING, format_map, map);
|
||||||
|
reg_unary_mut(lib, KEYWORD_DEBUG, format_map, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_binary(
|
||||||
|
lib,
|
||||||
|
"+",
|
||||||
|
|mut s: String, ch: char| {
|
||||||
|
s.push(ch);
|
||||||
|
s
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_binary(
|
||||||
|
lib,
|
||||||
|
"+",
|
||||||
|
|mut s: String, s2: String| {
|
||||||
|
s.push_str(&s2);
|
||||||
|
s
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_binary_mut(lib, "append", |s: &mut String, ch: char| s.push(ch), map);
|
||||||
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"append",
|
||||||
|
|s: &mut String, s2: String| s.push_str(&s2),
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
use super::{
|
use super::{reg_binary, reg_binary_mut, reg_trinary_mut, reg_unary_mut};
|
||||||
create_new_package, reg_binary, reg_binary_mut, reg_trinary_mut, reg_unary, reg_unary_mut,
|
|
||||||
Package, PackageLibrary, PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::engine::Array;
|
use crate::engine::Array;
|
||||||
use crate::fn_register::map_dynamic as map;
|
use crate::fn_register::map_dynamic as map;
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
|
|
||||||
use crate::stdlib::{fmt::Display, ops::Deref};
|
use crate::stdlib::fmt::Display;
|
||||||
|
|
||||||
// Register string concatenate functions
|
|
||||||
fn prepend<T: Display>(x: T, y: String) -> String {
|
fn prepend<T: Display>(x: T, y: String) -> String {
|
||||||
format!("{}{}", x, y)
|
format!("{}{}", x, y)
|
||||||
}
|
}
|
||||||
@ -65,195 +62,173 @@ fn crop_string(s: &mut String, start: INT, len: INT) {
|
|||||||
.for_each(|&ch| s.push(ch));
|
.for_each(|&ch| s.push(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MoreStringPackage(PackageLibrary);
|
|
||||||
|
|
||||||
impl Deref for MoreStringPackage {
|
|
||||||
type Target = PackageLibrary;
|
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
macro_rules! reg_op { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
||||||
$(reg_binary($lib, $op, $func::<$par>, map);)* };
|
$(reg_binary($lib, $op, $func::<$par>, map);)* };
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package for MoreStringPackage {
|
def_package!(MoreStringPackage:"Additional string utilities, including string building.", lib, {
|
||||||
fn new() -> Self {
|
reg_op!(lib, "+", append, INT, bool, char);
|
||||||
let mut pkg = create_new_package();
|
reg_binary_mut(lib, "+", |x: &mut String, _: ()| x.clone(), map);
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
reg_op!(lib, "+", prepend, INT, bool, char);
|
||||||
|
reg_binary(lib, "+", |_: (), y: String| y, map);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
{
|
||||||
|
reg_op!(lib, "+", append, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
|
reg_op!(lib, "+", prepend, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
#[cfg(not(feature = "no_float"))]
|
||||||
self.0.clone()
|
{
|
||||||
|
reg_op!(lib, "+", append, f32, f64);
|
||||||
|
reg_op!(lib, "+", prepend, f32, f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
#[cfg(not(feature = "no_index"))]
|
||||||
reg_op!(lib, "+", append, INT, bool, char);
|
{
|
||||||
reg_binary_mut(lib, "+", |x: &mut String, _: ()| x.clone(), map);
|
reg_binary(lib, "+", |x: String, y: Array| format!("{}{:?}", x, y), map);
|
||||||
|
reg_binary(lib, "+", |x: Array, y: String| format!("{:?}{}", x, y), map);
|
||||||
|
}
|
||||||
|
|
||||||
reg_op!(lib, "+", prepend, INT, bool, char);
|
reg_unary_mut(lib, "len", |s: &mut String| s.chars().count() as INT, map);
|
||||||
reg_binary(lib, "+", |_: (), y: String| y, map);
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"contains",
|
||||||
|
|s: &mut String, ch: char| s.contains(ch),
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"contains",
|
||||||
|
|s: &mut String, find: String| s.contains(&find),
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_trinary_mut(
|
||||||
|
lib,
|
||||||
|
"index_of",
|
||||||
|
|s: &mut String, ch: char, start: INT| {
|
||||||
|
let start = if start < 0 {
|
||||||
|
0
|
||||||
|
} else if (start as usize) >= s.chars().count() {
|
||||||
|
return -1 as INT;
|
||||||
|
} else {
|
||||||
|
s.chars().take(start as usize).collect::<String>().len()
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
s[start..]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
.find(ch)
|
||||||
{
|
.map(|index| s[0..start + index].chars().count() as INT)
|
||||||
reg_op!(lib, "+", append, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
.unwrap_or(-1 as INT)
|
||||||
reg_op!(lib, "+", prepend, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
},
|
||||||
}
|
map,
|
||||||
|
);
|
||||||
|
reg_binary_mut(
|
||||||
|
lib,
|
||||||
|
"index_of",
|
||||||
|
|s: &mut String, ch: char| {
|
||||||
|
s.find(ch)
|
||||||
|
.map(|index| s[0..index].chars().count() as INT)
|
||||||
|
.unwrap_or(-1 as INT)
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_trinary_mut(
|
||||||
|
lib,
|
||||||
|
"index_of",
|
||||||
|
|s: &mut String, find: String, start: INT| {
|
||||||
|
let start = if start < 0 {
|
||||||
|
0
|
||||||
|
} else if (start as usize) >= s.chars().count() {
|
||||||
|
return -1 as INT;
|
||||||
|
} else {
|
||||||
|
s.chars().take(start as usize).collect::<String>().len()
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
s[start..]
|
||||||
{
|
.find(&find)
|
||||||
reg_op!(lib, "+", append, f32, f64);
|
.map(|index| s[0..start + index].chars().count() as INT)
|
||||||
reg_op!(lib, "+", prepend, f32, f64);
|
.unwrap_or(-1 as INT)
|
||||||
}
|
},
|
||||||
|
map,
|
||||||
#[cfg(not(feature = "no_index"))]
|
);
|
||||||
{
|
reg_binary_mut(
|
||||||
reg_binary(lib, "+", |x: String, y: Array| format!("{}{:?}", x, y), map);
|
lib,
|
||||||
reg_binary(lib, "+", |x: Array, y: String| format!("{:?}{}", x, y), map);
|
"index_of",
|
||||||
}
|
|s: &mut String, find: String| {
|
||||||
|
s.find(&find)
|
||||||
reg_unary_mut(lib, "len", |s: &mut String| s.chars().count() as INT, map);
|
.map(|index| s[0..index].chars().count() as INT)
|
||||||
reg_binary_mut(
|
.unwrap_or(-1 as INT)
|
||||||
lib,
|
},
|
||||||
"contains",
|
map,
|
||||||
|s: &mut String, ch: char| s.contains(ch),
|
);
|
||||||
map,
|
reg_unary_mut(lib, "clear", |s: &mut String| s.clear(), map);
|
||||||
);
|
reg_binary_mut(lib, "append", |s: &mut String, ch: char| s.push(ch), map);
|
||||||
reg_binary_mut(
|
reg_binary_mut(
|
||||||
lib,
|
lib,
|
||||||
"contains",
|
"append",
|
||||||
|s: &mut String, find: String| s.contains(&find),
|
|s: &mut String, add: String| s.push_str(&add),
|
||||||
map,
|
map,
|
||||||
);
|
);
|
||||||
reg_trinary_mut(
|
reg_trinary_mut(lib, "sub_string", sub_string, map);
|
||||||
lib,
|
reg_binary_mut(
|
||||||
"index_of",
|
lib,
|
||||||
|s: &mut String, ch: char, start: INT| {
|
"sub_string",
|
||||||
let start = if start < 0 {
|
|s: &mut String, start: INT| sub_string(s, start, s.len() as INT),
|
||||||
0
|
map,
|
||||||
} else if (start as usize) >= s.chars().count() {
|
);
|
||||||
return -1 as INT;
|
reg_trinary_mut(lib, "crop", crop_string, map);
|
||||||
} else {
|
reg_binary_mut(
|
||||||
s.chars().take(start as usize).collect::<String>().len()
|
lib,
|
||||||
};
|
"crop",
|
||||||
|
|s: &mut String, start: INT| crop_string(s, start, s.len() as INT),
|
||||||
s[start..]
|
map,
|
||||||
.find(ch)
|
);
|
||||||
.map(|index| s[0..start + index].chars().count() as INT)
|
reg_binary_mut(
|
||||||
.unwrap_or(-1 as INT)
|
lib,
|
||||||
},
|
"truncate",
|
||||||
map,
|
|s: &mut String, len: INT| {
|
||||||
);
|
if len >= 0 {
|
||||||
reg_binary_mut(
|
let chars: Vec<_> = s.chars().take(len as usize).collect();
|
||||||
lib,
|
|
||||||
"index_of",
|
|
||||||
|s: &mut String, ch: char| {
|
|
||||||
s.find(ch)
|
|
||||||
.map(|index| s[0..index].chars().count() as INT)
|
|
||||||
.unwrap_or(-1 as INT)
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_trinary_mut(
|
|
||||||
lib,
|
|
||||||
"index_of",
|
|
||||||
|s: &mut String, find: String, start: INT| {
|
|
||||||
let start = if start < 0 {
|
|
||||||
0
|
|
||||||
} else if (start as usize) >= s.chars().count() {
|
|
||||||
return -1 as INT;
|
|
||||||
} else {
|
|
||||||
s.chars().take(start as usize).collect::<String>().len()
|
|
||||||
};
|
|
||||||
|
|
||||||
s[start..]
|
|
||||||
.find(&find)
|
|
||||||
.map(|index| s[0..start + index].chars().count() as INT)
|
|
||||||
.unwrap_or(-1 as INT)
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"index_of",
|
|
||||||
|s: &mut String, find: String| {
|
|
||||||
s.find(&find)
|
|
||||||
.map(|index| s[0..index].chars().count() as INT)
|
|
||||||
.unwrap_or(-1 as INT)
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_unary_mut(lib, "clear", |s: &mut String| s.clear(), map);
|
|
||||||
reg_binary_mut(lib, "append", |s: &mut String, ch: char| s.push(ch), map);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"append",
|
|
||||||
|s: &mut String, add: String| s.push_str(&add),
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_trinary_mut(lib, "sub_string", sub_string, map);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"sub_string",
|
|
||||||
|s: &mut String, start: INT| sub_string(s, start, s.len() as INT),
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_trinary_mut(lib, "crop", crop_string, map);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"crop",
|
|
||||||
|s: &mut String, start: INT| crop_string(s, start, s.len() as INT),
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_binary_mut(
|
|
||||||
lib,
|
|
||||||
"truncate",
|
|
||||||
|s: &mut String, len: INT| {
|
|
||||||
if len >= 0 {
|
|
||||||
let chars: Vec<_> = s.chars().take(len as usize).collect();
|
|
||||||
s.clear();
|
|
||||||
chars.into_iter().for_each(|ch| s.push(ch));
|
|
||||||
} else {
|
|
||||||
s.clear();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_trinary_mut(
|
|
||||||
lib,
|
|
||||||
"pad",
|
|
||||||
|s: &mut String, len: INT, ch: char| {
|
|
||||||
for _ in 0..s.chars().count() - len as usize {
|
|
||||||
s.push(ch);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
reg_trinary_mut(
|
|
||||||
lib,
|
|
||||||
"replace",
|
|
||||||
|s: &mut String, find: String, sub: String| {
|
|
||||||
let new_str = s.replace(&find, &sub);
|
|
||||||
s.clear();
|
s.clear();
|
||||||
s.push_str(&new_str);
|
chars.into_iter().for_each(|ch| s.push(ch));
|
||||||
},
|
} else {
|
||||||
map,
|
s.clear();
|
||||||
);
|
}
|
||||||
reg_unary_mut(
|
},
|
||||||
lib,
|
map,
|
||||||
"trim",
|
);
|
||||||
|s: &mut String| {
|
reg_trinary_mut(
|
||||||
let trimmed = s.trim();
|
lib,
|
||||||
|
"pad",
|
||||||
|
|s: &mut String, len: INT, ch: char| {
|
||||||
|
for _ in 0..s.chars().count() - len as usize {
|
||||||
|
s.push(ch);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_trinary_mut(
|
||||||
|
lib,
|
||||||
|
"replace",
|
||||||
|
|s: &mut String, find: String, sub: String| {
|
||||||
|
let new_str = s.replace(&find, &sub);
|
||||||
|
s.clear();
|
||||||
|
s.push_str(&new_str);
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
);
|
||||||
|
reg_unary_mut(
|
||||||
|
lib,
|
||||||
|
"trim",
|
||||||
|
|s: &mut String| {
|
||||||
|
let trimmed = s.trim();
|
||||||
|
|
||||||
if trimmed.len() < s.len() {
|
if trimmed.len() < s.len() {
|
||||||
*s = trimmed.to_string();
|
*s = trimmed.to_string();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
@ -1,129 +1,102 @@
|
|||||||
use super::logic::{eq, gt, gte, lt, lte, ne};
|
use super::logic::{eq, gt, gte, lt, lte, ne};
|
||||||
use super::math_basic::MAX_INT;
|
use super::math_basic::MAX_INT;
|
||||||
use super::{
|
use super::{reg_binary, reg_none, reg_unary};
|
||||||
create_new_package, reg_binary, reg_none, reg_unary, Package, PackageLibrary,
|
|
||||||
PackageLibraryStore,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use crate::def_package;
|
||||||
use crate::fn_register::{map_dynamic as map, map_result as result};
|
use crate::fn_register::{map_dynamic as map, map_result as result};
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
|
||||||
use crate::stdlib::{ops::Deref, time::Instant};
|
use crate::stdlib::time::Instant;
|
||||||
|
|
||||||
pub struct BasicTimePackage(PackageLibrary);
|
def_package!(BasicTimePackage:"Basic timing utilities.", lib, {
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
{
|
||||||
|
// Register date/time functions
|
||||||
|
reg_none(lib, "timestamp", || Instant::now(), map);
|
||||||
|
|
||||||
impl Deref for BasicTimePackage {
|
reg_binary(
|
||||||
type Target = PackageLibrary;
|
|
||||||
|
|
||||||
fn deref(&self) -> &PackageLibrary {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package for BasicTimePackage {
|
|
||||||
fn new() -> Self {
|
|
||||||
let mut pkg = create_new_package();
|
|
||||||
Self::init(&mut pkg);
|
|
||||||
Self(pkg.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self) -> PackageLibrary {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(lib: &mut PackageLibraryStore) {
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
{
|
|
||||||
// Register date/time functions
|
|
||||||
reg_none(lib, "timestamp", || Instant::now(), map);
|
|
||||||
|
|
||||||
reg_binary(
|
|
||||||
lib,
|
|
||||||
"-",
|
|
||||||
|ts1: Instant, ts2: Instant| {
|
|
||||||
if ts2 > ts1 {
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
return Ok(-(ts2 - ts1).as_secs_f64());
|
|
||||||
|
|
||||||
#[cfg(feature = "no_float")]
|
|
||||||
{
|
|
||||||
let seconds = (ts2 - ts1).as_secs();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
if seconds > (MAX_INT as u64) {
|
|
||||||
return Err(EvalAltResult::ErrorArithmetic(
|
|
||||||
format!(
|
|
||||||
"Integer overflow for timestamp duration: {}",
|
|
||||||
-(seconds as i64)
|
|
||||||
),
|
|
||||||
Position::none(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(-(seconds as INT));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
return Ok((ts1 - ts2).as_secs_f64());
|
|
||||||
|
|
||||||
#[cfg(feature = "no_float")]
|
|
||||||
{
|
|
||||||
let seconds = (ts1 - ts2).as_secs();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
|
||||||
if seconds > (MAX_INT as u64) {
|
|
||||||
return Err(EvalAltResult::ErrorArithmetic(
|
|
||||||
format!(
|
|
||||||
"Integer overflow for timestamp duration: {}",
|
|
||||||
seconds
|
|
||||||
),
|
|
||||||
Position::none(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(seconds as INT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
result,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_binary(lib, "<", lt::<Instant>, map);
|
|
||||||
reg_binary(lib, "<=", lte::<Instant>, map);
|
|
||||||
reg_binary(lib, ">", gt::<Instant>, map);
|
|
||||||
reg_binary(lib, ">=", gte::<Instant>, map);
|
|
||||||
reg_binary(lib, "==", eq::<Instant>, map);
|
|
||||||
reg_binary(lib, "!=", ne::<Instant>, map);
|
|
||||||
|
|
||||||
reg_unary(
|
|
||||||
lib,
|
lib,
|
||||||
"elapsed",
|
"-",
|
||||||
|timestamp: Instant| {
|
|ts1: Instant, ts2: Instant| {
|
||||||
#[cfg(not(feature = "no_float"))]
|
if ts2 > ts1 {
|
||||||
return Ok(timestamp.elapsed().as_secs_f64());
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
return Ok(-(ts2 - ts1).as_secs_f64());
|
||||||
|
|
||||||
#[cfg(feature = "no_float")]
|
#[cfg(feature = "no_float")]
|
||||||
{
|
|
||||||
let seconds = timestamp.elapsed().as_secs();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
{
|
{
|
||||||
if seconds > (MAX_INT as u64) {
|
let seconds = (ts2 - ts1).as_secs();
|
||||||
return Err(EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Integer overflow for timestamp.elapsed(): {}", seconds),
|
#[cfg(not(feature = "unchecked"))]
|
||||||
Position::none(),
|
{
|
||||||
));
|
if seconds > (MAX_INT as u64) {
|
||||||
|
return Err(EvalAltResult::ErrorArithmetic(
|
||||||
|
format!(
|
||||||
|
"Integer overflow for timestamp duration: {}",
|
||||||
|
-(seconds as i64)
|
||||||
|
),
|
||||||
|
Position::none(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return Ok(-(seconds as INT));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
return Ok((ts1 - ts2).as_secs_f64());
|
||||||
|
|
||||||
|
#[cfg(feature = "no_float")]
|
||||||
|
{
|
||||||
|
let seconds = (ts1 - ts2).as_secs();
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
{
|
||||||
|
if seconds > (MAX_INT as u64) {
|
||||||
|
return Err(EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Integer overflow for timestamp duration: {}", seconds),
|
||||||
|
Position::none(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(seconds as INT);
|
||||||
}
|
}
|
||||||
return Ok(seconds as INT);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result,
|
result,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
reg_binary(lib, "<", lt::<Instant>, map);
|
||||||
|
reg_binary(lib, "<=", lte::<Instant>, map);
|
||||||
|
reg_binary(lib, ">", gt::<Instant>, map);
|
||||||
|
reg_binary(lib, ">=", gte::<Instant>, map);
|
||||||
|
reg_binary(lib, "==", eq::<Instant>, map);
|
||||||
|
reg_binary(lib, "!=", ne::<Instant>, map);
|
||||||
|
|
||||||
|
reg_unary(
|
||||||
|
lib,
|
||||||
|
"elapsed",
|
||||||
|
|timestamp: Instant| {
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
return Ok(timestamp.elapsed().as_secs_f64());
|
||||||
|
|
||||||
|
#[cfg(feature = "no_float")]
|
||||||
|
{
|
||||||
|
let seconds = timestamp.elapsed().as_secs();
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
{
|
||||||
|
if seconds > (MAX_INT as u64) {
|
||||||
|
return Err(EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Integer overflow for timestamp.elapsed(): {}", seconds),
|
||||||
|
Position::none(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(seconds as INT);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
363
src/packages/utils.rs
Normal file
363
src/packages/utils.rs
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
use super::PackageStore;
|
||||||
|
|
||||||
|
use crate::any::{Dynamic, Variant};
|
||||||
|
use crate::calc_fn_hash;
|
||||||
|
use crate::engine::FnCallArgs;
|
||||||
|
use crate::result::EvalAltResult;
|
||||||
|
use crate::token::Position;
|
||||||
|
|
||||||
|
use crate::stdlib::{any::TypeId, boxed::Box};
|
||||||
|
|
||||||
|
/// This macro makes it easy to define a _package_ and register functions into it.
|
||||||
|
///
|
||||||
|
/// Functions can be added to the package using a number of helper functions under the `packages` module,
|
||||||
|
/// such as `reg_unary`, `reg_binary_mut`, `reg_trinary_mut` etc.
|
||||||
|
///
|
||||||
|
/// ```,ignore
|
||||||
|
/// use rhai::def_package;
|
||||||
|
/// use rhai::packages::reg_binary;
|
||||||
|
///
|
||||||
|
/// fn add(x: i64, y: i64) { x + y }
|
||||||
|
///
|
||||||
|
/// def_package!(MyPackage:"My super-duper package", lib,
|
||||||
|
/// {
|
||||||
|
/// reg_binary(lib, "my_add", add, |v| Ok(v.into_dynamic()));
|
||||||
|
/// // ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
/// // map into Result<Dynamic, EvalAltResult>
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The above defines a package named 'MyPackage' with a single function named 'my_add'.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! def_package {
|
||||||
|
($package:ident : $comment:expr , $lib:ident , $block:stmt) => {
|
||||||
|
#[doc=$comment]
|
||||||
|
pub struct $package(super::PackageLibrary);
|
||||||
|
|
||||||
|
impl crate::packages::Package for $package {
|
||||||
|
fn new() -> Self {
|
||||||
|
let mut pkg = crate::packages::PackageStore::new();
|
||||||
|
Self::init(&mut pkg);
|
||||||
|
Self(pkg.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self) -> crate::packages::PackageLibrary {
|
||||||
|
self.0.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init($lib: &mut crate::packages::PackageStore) {
|
||||||
|
$block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_num_args(
|
||||||
|
name: &str,
|
||||||
|
num_args: usize,
|
||||||
|
args: &mut FnCallArgs,
|
||||||
|
pos: Position,
|
||||||
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
if args.len() != num_args {
|
||||||
|
Err(Box::new(EvalAltResult::ErrorFunctionArgsMismatch(
|
||||||
|
name.to_string(),
|
||||||
|
num_args,
|
||||||
|
args.len(),
|
||||||
|
pos,
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with no parameters to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_none<R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn() -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn() -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
let hash = calc_fn_hash(fn_name, ([] as [TypeId; 0]).iter().cloned());
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 0, args, pos)?;
|
||||||
|
|
||||||
|
let r = func();
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with one parameter to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_unary<T: Variant + Clone, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(T) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(T) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}({})", fn_name, crate::std::any::type_name::<T>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(fn_name, [TypeId::of::<T>()].iter().cloned());
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 1, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
|
let r = func(x.clone());
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with one mutable reference parameter to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_unary_mut<T: Variant + Clone, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(&mut T) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(&mut T) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}(&mut {})", fn_name, crate::std::any::type_name::<T>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(fn_name, [TypeId::of::<T>()].iter().cloned());
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 1, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
|
let r = func(x);
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn reg_test<'a, A: Variant + Clone, B: Variant + Clone, X, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(X, B) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(X, B) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
map: impl Fn(&mut A) -> X + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}({}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(
|
||||||
|
fn_name,
|
||||||
|
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 2, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: X = map(drain.next().unwrap().downcast_mut::<A>().unwrap());
|
||||||
|
let y: B = drain.next().unwrap().downcast_mut::<B>().unwrap().clone();
|
||||||
|
|
||||||
|
let r = func(x, y);
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with two parameters to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_binary<A: Variant + Clone, B: Variant + Clone, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(A, B) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}({}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(
|
||||||
|
fn_name,
|
||||||
|
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 2, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
|
let r = func(x.clone(), y.clone());
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with two parameters (the first one being a mutable reference) to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_binary_mut<A: Variant + Clone, B: Variant + Clone, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}(&mut {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(
|
||||||
|
fn_name,
|
||||||
|
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 2, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
|
let r = func(x, y.clone());
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with three parameters to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(A, B, C) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}({}, {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>(), crate::std::any::type_name::<C>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(
|
||||||
|
fn_name,
|
||||||
|
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
||||||
|
.iter()
|
||||||
|
.cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 3, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
|
let r = func(x.clone(), y.clone(), z.clone());
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a function with three parameters (the first one is a mutable reference) to the package.
|
||||||
|
///
|
||||||
|
/// `map_result` is a function that maps the return type of the function to `Result<Dynamic, EvalAltResult>`.
|
||||||
|
pub fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R>(
|
||||||
|
lib: &mut PackageStore,
|
||||||
|
fn_name: &'static str,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> R + 'static,
|
||||||
|
#[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> R + Send + Sync + 'static,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ 'static,
|
||||||
|
#[cfg(feature = "sync")] map_result: impl Fn(R, Position) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
//println!("register {}(&mut {}, {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>(), crate::std::any::type_name::<C>());
|
||||||
|
|
||||||
|
let hash = calc_fn_hash(
|
||||||
|
fn_name,
|
||||||
|
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
||||||
|
.iter()
|
||||||
|
.cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
|
check_num_args(fn_name, 3, args, pos)?;
|
||||||
|
|
||||||
|
let mut drain = args.iter_mut();
|
||||||
|
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
|
let r = func(x, y.clone(), z.clone());
|
||||||
|
map_result(r, pos)
|
||||||
|
});
|
||||||
|
|
||||||
|
lib.functions.insert(hash, f);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user