Convert some packages into plugins.
This commit is contained in:
parent
2495b367e5
commit
c0dc47c9db
93
src/any.rs
93
src/any.rs
@ -535,45 +535,47 @@ impl Dynamic {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn from<T: Variant + Clone>(value: T) -> Self {
|
||||
let type_id = TypeId::of::<T>();
|
||||
|
||||
if type_id == TypeId::of::<INT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
||||
return <dyn Any>::downcast_ref::<INT>(&value)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into();
|
||||
}
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if type_id == TypeId::of::<FLOAT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
||||
return <dyn Any>::downcast_ref::<FLOAT>(&value)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into();
|
||||
}
|
||||
if type_id == TypeId::of::<bool>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
||||
return <dyn Any>::downcast_ref::<bool>(&value)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into();
|
||||
}
|
||||
if type_id == TypeId::of::<char>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<char>() {
|
||||
return <dyn Any>::downcast_ref::<char>(&value)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into();
|
||||
}
|
||||
if type_id == TypeId::of::<ImmutableString>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
||||
return <dyn Any>::downcast_ref::<ImmutableString>(&value)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into();
|
||||
}
|
||||
if type_id == TypeId::of::<()>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||
return ().into();
|
||||
}
|
||||
|
||||
let mut boxed = Box::new(value);
|
||||
|
||||
boxed = match unsafe_cast_box::<_, Dynamic>(boxed) {
|
||||
Ok(d) => return *d,
|
||||
Err(val) => val,
|
||||
};
|
||||
boxed = match unsafe_cast_box::<_, String>(boxed) {
|
||||
Ok(s) => return (*s).into(),
|
||||
Err(val) => val,
|
||||
@ -599,11 +601,6 @@ impl Dynamic {
|
||||
Err(val) => val,
|
||||
};
|
||||
|
||||
boxed = match unsafe_cast_box::<_, Dynamic>(boxed) {
|
||||
Ok(d) => return *d,
|
||||
Err(val) => val,
|
||||
};
|
||||
|
||||
Self(Union::Variant(Box::new(boxed)))
|
||||
}
|
||||
|
||||
@ -660,8 +657,6 @@ impl Dynamic {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn try_cast<T: Variant>(self) -> Option<T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
|
||||
match self.0 {
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
#[cfg(not(feature = "sync"))]
|
||||
@ -673,11 +668,11 @@ impl Dynamic {
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<Dynamic>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
||||
return unsafe_cast_box::<_, T>(Box::new(self)).ok().map(|v| *v);
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<INT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
||||
return match self.0 {
|
||||
Union::Int(value) => unsafe_try_cast(value),
|
||||
_ => None,
|
||||
@ -685,35 +680,35 @@ impl Dynamic {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if type_id == TypeId::of::<FLOAT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
||||
return match self.0 {
|
||||
Union::Float(value) => unsafe_try_cast(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<bool>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
||||
return match self.0 {
|
||||
Union::Bool(value) => unsafe_try_cast(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<ImmutableString>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
||||
return match self.0 {
|
||||
Union::Str(value) => unsafe_try_cast(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<String>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<String>() {
|
||||
return match self.0 {
|
||||
Union::Str(value) => unsafe_try_cast(value.into_owned()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<char>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<char>() {
|
||||
return match self.0 {
|
||||
Union::Char(value) => unsafe_try_cast(value),
|
||||
_ => None,
|
||||
@ -721,7 +716,7 @@ impl Dynamic {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if type_id == TypeId::of::<Array>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||
return match self.0 {
|
||||
Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
||||
_ => None,
|
||||
@ -729,21 +724,21 @@ impl Dynamic {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
if type_id == TypeId::of::<Map>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Map>() {
|
||||
return match self.0 {
|
||||
Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<FnPtr>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
|
||||
return match self.0 {
|
||||
Union::FnPtr(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if type_id == TypeId::of::<()>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||
return match self.0 {
|
||||
Union::Unit(value) => unsafe_try_cast(value),
|
||||
_ => None,
|
||||
@ -928,72 +923,70 @@ impl Dynamic {
|
||||
/// Returns `None` if the cast fails, or if the value is shared.
|
||||
#[inline(always)]
|
||||
pub(crate) fn downcast_ref<T: Variant + Clone>(&self) -> Option<&T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
|
||||
if type_id == TypeId::of::<INT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
||||
return match &self.0 {
|
||||
Union::Int(value) => <dyn Any>::downcast_ref::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if type_id == TypeId::of::<FLOAT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
||||
return match &self.0 {
|
||||
Union::Float(value) => <dyn Any>::downcast_ref::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<bool>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
||||
return match &self.0 {
|
||||
Union::Bool(value) => <dyn Any>::downcast_ref::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<ImmutableString>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
||||
return match &self.0 {
|
||||
Union::Str(value) => <dyn Any>::downcast_ref::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<String>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<String>() {
|
||||
return match &self.0 {
|
||||
Union::Str(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<char>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<char>() {
|
||||
return match &self.0 {
|
||||
Union::Char(value) => <dyn Any>::downcast_ref::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if type_id == TypeId::of::<Array>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||
return match &self.0 {
|
||||
Union::Array(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
if type_id == TypeId::of::<Map>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Map>() {
|
||||
return match &self.0 {
|
||||
Union::Map(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<FnPtr>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
|
||||
return match &self.0 {
|
||||
Union::FnPtr(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<()>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||
return match &self.0 {
|
||||
Union::Unit(value) => <dyn Any>::downcast_ref::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<Dynamic>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
||||
return <dyn Any>::downcast_ref::<T>(self);
|
||||
}
|
||||
|
||||
@ -1011,66 +1004,64 @@ impl Dynamic {
|
||||
/// Returns `None` if the cast fails, or if the value is shared.
|
||||
#[inline(always)]
|
||||
pub(crate) fn downcast_mut<T: Variant + Clone>(&mut self) -> Option<&mut T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
|
||||
if type_id == TypeId::of::<INT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
||||
return match &mut self.0 {
|
||||
Union::Int(value) => <dyn Any>::downcast_mut::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
if type_id == TypeId::of::<FLOAT>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
||||
return match &mut self.0 {
|
||||
Union::Float(value) => <dyn Any>::downcast_mut::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<bool>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
||||
return match &mut self.0 {
|
||||
Union::Bool(value) => <dyn Any>::downcast_mut::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<ImmutableString>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
||||
return match &mut self.0 {
|
||||
Union::Str(value) => <dyn Any>::downcast_mut::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<char>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<char>() {
|
||||
return match &mut self.0 {
|
||||
Union::Char(value) => <dyn Any>::downcast_mut::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if type_id == TypeId::of::<Array>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||
return match &mut self.0 {
|
||||
Union::Array(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
if type_id == TypeId::of::<Map>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Map>() {
|
||||
return match &mut self.0 {
|
||||
Union::Map(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<FnPtr>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
|
||||
return match &mut self.0 {
|
||||
Union::FnPtr(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<()>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||
return match &mut self.0 {
|
||||
Union::Unit(value) => <dyn Any>::downcast_mut::<T>(value),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
if type_id == TypeId::of::<Dynamic>() {
|
||||
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
||||
return <dyn Any>::downcast_mut::<T>(self);
|
||||
}
|
||||
|
||||
|
@ -1,65 +1,126 @@
|
||||
use crate::def_package;
|
||||
use crate::module::FuncReturn;
|
||||
use crate::plugin::*;
|
||||
|
||||
// Comparison operators
|
||||
pub fn lt<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> {
|
||||
Ok(x < y)
|
||||
}
|
||||
pub fn lte<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> {
|
||||
Ok(x <= y)
|
||||
}
|
||||
pub fn gt<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> {
|
||||
Ok(x > y)
|
||||
}
|
||||
pub fn gte<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> {
|
||||
Ok(x >= y)
|
||||
}
|
||||
pub fn eq<T: PartialEq>(x: T, y: T) -> FuncReturn<bool> {
|
||||
Ok(x == y)
|
||||
}
|
||||
pub fn ne<T: PartialEq>(x: T, y: T) -> FuncReturn<bool> {
|
||||
Ok(x != y)
|
||||
macro_rules! gen_cmp_functions {
|
||||
($op_name:tt = $op_fn:ident ( $($arg_type:ident),+ ) -> $return_type:ident) => {
|
||||
pub mod $op_fn { $(
|
||||
pub mod $arg_type {
|
||||
use crate::plugin::*;
|
||||
|
||||
pub const OP_NAME: &'static str = $op_name;
|
||||
|
||||
#[export_fn]
|
||||
pub fn cmp_func(x: $arg_type, y: $arg_type) -> $return_type {
|
||||
super::super::super::$op_fn(x, y)
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
}
|
||||
|
||||
// Logic operators
|
||||
fn not(x: bool) -> FuncReturn<bool> {
|
||||
Ok(!x)
|
||||
}
|
||||
|
||||
macro_rules! reg_op {
|
||||
($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
|
||||
$( $lib.set_fn_2($op, $func::<$par>); )*
|
||||
};
|
||||
macro_rules! reg_functions {
|
||||
($mod_name:ident += $root:ident :: $op_name:ident ( $($arg_type:ident),+ )) => {
|
||||
$(set_exported_fn!($mod_name, $root::$op_name::$arg_type::OP_NAME, $root::$op_name::$arg_type::cmp_func);)*
|
||||
}
|
||||
}
|
||||
|
||||
def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
||||
if cfg!(not(feature = "only_i32")) && cfg!(not(feature = "only_i64")) {
|
||||
reg_op!(lib, "<", lt, i8, u8, i16, u16, i32, u32, u64);
|
||||
reg_op!(lib, "<=", lte, i8, u8, i16, u16, i32, u32, u64);
|
||||
reg_op!(lib, ">", gt, i8, u8, i16, u16, i32, u32, u64);
|
||||
reg_op!(lib, ">=", gte, i8, u8, i16, u16, i32, u32, u64);
|
||||
reg_op!(lib, "==", eq, i8, u8, i16, u16, i32, u32, u64);
|
||||
reg_op!(lib, "!=", ne, i8, u8, i16, u16, i32, u32, u64);
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
reg_functions!(lib += cmp::lt(i8, u8, i16, u16, i32, u32, u64));
|
||||
reg_functions!(lib += cmp::lte(i8, u8, i16, u16, i32, u32, u64));
|
||||
reg_functions!(lib += cmp::gt(i8, u8, i16, u16, i32, u32, u64));
|
||||
reg_functions!(lib += cmp::gte(i8, u8, i16, u16, i32, u32, u64));
|
||||
reg_functions!(lib += cmp::eq(i8, u8, i16, u16, i32, u32, u64));
|
||||
reg_functions!(lib += cmp::ne(i8, u8, i16, u16, i32, u32, u64));
|
||||
|
||||
if cfg!(not(target_arch = "wasm32")) {
|
||||
reg_op!(lib, "<", lt, i128, u128);
|
||||
reg_op!(lib, "<=", lte, i128, u128);
|
||||
reg_op!(lib, ">", gt, i128, u128);
|
||||
reg_op!(lib, ">=", gte, i128, u128);
|
||||
reg_op!(lib, "==", eq, i128, u128);
|
||||
reg_op!(lib, "!=", ne, i128, u128);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
reg_functions!(lib += cmp_128::lt(i128, u128));
|
||||
reg_functions!(lib += cmp_128::lte(i128, u128));
|
||||
reg_functions!(lib += cmp_128::gt(i128, u128));
|
||||
reg_functions!(lib += cmp_128::gte(i128, u128));
|
||||
reg_functions!(lib += cmp_128::eq(i128, u128));
|
||||
reg_functions!(lib += cmp_128::ne(i128, u128));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
reg_op!(lib, "<", lt, f32);
|
||||
reg_op!(lib, "<=", lte, f32);
|
||||
reg_op!(lib, ">", gt, f32);
|
||||
reg_op!(lib, ">=", gte, f32);
|
||||
reg_op!(lib, "==", eq, f32);
|
||||
reg_op!(lib, "!=", ne, f32);
|
||||
reg_functions!(lib += cmp_float::lt(f32));
|
||||
reg_functions!(lib += cmp_float::lte(f32));
|
||||
reg_functions!(lib += cmp_float::gt(f32));
|
||||
reg_functions!(lib += cmp_float::gte(f32));
|
||||
reg_functions!(lib += cmp_float::eq(f32));
|
||||
reg_functions!(lib += cmp_float::ne(f32));
|
||||
}
|
||||
|
||||
lib.set_fn_1("!", not);
|
||||
set_exported_fn!(lib, "!", not);
|
||||
});
|
||||
|
||||
// Comparison operators
|
||||
#[inline(always)]
|
||||
pub fn lt<T: PartialOrd>(x: T, y: T) -> bool {
|
||||
x < y
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn lte<T: PartialOrd>(x: T, y: T) -> bool {
|
||||
x <= y
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn gt<T: PartialOrd>(x: T, y: T) -> bool {
|
||||
x > y
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn gte<T: PartialOrd>(x: T, y: T) -> bool {
|
||||
x >= y
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn eq<T: PartialEq>(x: T, y: T) -> bool {
|
||||
x == y
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn ne<T: PartialEq>(x: T, y: T) -> bool {
|
||||
x != y
|
||||
}
|
||||
|
||||
// Logic operators
|
||||
#[export_fn]
|
||||
#[inline(always)]
|
||||
fn not(x: bool) -> bool {
|
||||
!x
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
mod cmp {
|
||||
gen_cmp_functions!("<" = lt(i8, u8, i16, u16, i32, u32, u64) -> bool);
|
||||
gen_cmp_functions!("<=" = lte(i8, u8, i16, u16, i32, u32, u64) -> bool);
|
||||
gen_cmp_functions!(">" = gt(i8, u8, i16, u16, i32, u32, u64) -> bool);
|
||||
gen_cmp_functions!(">=" = gte(i8, u8, i16, u16, i32, u32, u64) -> bool);
|
||||
gen_cmp_functions!("==" = eq(i8, u8, i16, u16, i32, u32, u64) -> bool);
|
||||
gen_cmp_functions!("!=" = ne(i8, u8, i16, u16, i32, u32, u64) -> bool);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod cmp_128 {
|
||||
gen_cmp_functions!("<" = lt(i128, u128) -> bool);
|
||||
gen_cmp_functions!("<=" = lte(i128, u128) -> bool);
|
||||
gen_cmp_functions!(">" = gt(i128, u128) -> bool);
|
||||
gen_cmp_functions!(">=" = gte(i128, u128) -> bool);
|
||||
gen_cmp_functions!("==" = eq(i128, u128) -> bool);
|
||||
gen_cmp_functions!("!=" = ne(i128, u128) -> bool);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
mod cmp_float {
|
||||
gen_cmp_functions!("<" = lt(f32) -> bool);
|
||||
gen_cmp_functions!("<=" = lte(f32) -> bool);
|
||||
gen_cmp_functions!(">" = gt(f32) -> bool);
|
||||
gen_cmp_functions!(">=" = gte(f32) -> bool);
|
||||
gen_cmp_functions!("==" = eq(f32) -> bool);
|
||||
gen_cmp_functions!("!=" = ne(f32) -> bool);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::def_package;
|
||||
use crate::module::Module;
|
||||
use crate::parser::INT;
|
||||
use crate::plugin::*;
|
||||
|
||||
@ -24,99 +23,6 @@ pub const MAX_INT: INT = i32::MAX;
|
||||
pub const MAX_INT: INT = i64::MAX;
|
||||
|
||||
def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
||||
init_module(lib);
|
||||
});
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_module]
|
||||
mod trig {
|
||||
use crate::parser::FLOAT;
|
||||
|
||||
pub fn sin(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().sin()
|
||||
}
|
||||
pub fn cos(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().cos()
|
||||
}
|
||||
pub fn tan(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().tan()
|
||||
}
|
||||
pub fn sinh(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().sinh()
|
||||
}
|
||||
pub fn cosh(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().cosh()
|
||||
}
|
||||
pub fn tanh(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().tanh()
|
||||
}
|
||||
pub fn asin(x: FLOAT) -> FLOAT {
|
||||
x.asin().to_degrees()
|
||||
}
|
||||
pub fn acos(x: FLOAT) -> FLOAT {
|
||||
x.acos().to_degrees()
|
||||
}
|
||||
pub fn atan(x: FLOAT) -> FLOAT {
|
||||
x.atan().to_degrees()
|
||||
}
|
||||
pub fn asinh(x: FLOAT) -> FLOAT {
|
||||
x.asinh().to_degrees()
|
||||
}
|
||||
pub fn acosh(x: FLOAT) -> FLOAT {
|
||||
x.acosh().to_degrees()
|
||||
}
|
||||
pub fn atanh(x: FLOAT) -> FLOAT {
|
||||
x.atanh().to_degrees()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_module]
|
||||
mod float {
|
||||
use crate::parser::FLOAT;
|
||||
|
||||
pub fn sqrt(x: FLOAT) -> FLOAT {
|
||||
x.sqrt()
|
||||
}
|
||||
pub fn exp(x: FLOAT) -> FLOAT {
|
||||
x.exp()
|
||||
}
|
||||
pub fn ln(x: FLOAT) -> FLOAT {
|
||||
x.ln()
|
||||
}
|
||||
pub fn log(x: FLOAT, base: FLOAT) -> FLOAT {
|
||||
x.log(base)
|
||||
}
|
||||
pub fn log10(x: FLOAT) -> FLOAT {
|
||||
x.log10()
|
||||
}
|
||||
pub fn floor(x: FLOAT) -> FLOAT {
|
||||
x.floor()
|
||||
}
|
||||
pub fn ceiling(x: FLOAT) -> FLOAT {
|
||||
x.ceil()
|
||||
}
|
||||
pub fn round(x: FLOAT) -> FLOAT {
|
||||
x.ceil()
|
||||
}
|
||||
pub fn int(x: FLOAT) -> FLOAT {
|
||||
x.trunc()
|
||||
}
|
||||
pub fn fraction(x: FLOAT) -> FLOAT {
|
||||
x.fract()
|
||||
}
|
||||
pub fn is_nan(x: FLOAT) -> bool {
|
||||
x.is_nan()
|
||||
}
|
||||
pub fn is_finite(x: FLOAT) -> bool {
|
||||
x.is_finite()
|
||||
}
|
||||
pub fn is_infinite(x: FLOAT) -> bool {
|
||||
x.is_infinite()
|
||||
}
|
||||
}
|
||||
|
||||
fn init_module(lib: &mut Module) {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
// Floating point functions
|
||||
@ -209,4 +115,93 @@ fn init_module(lib: &mut Module) {
|
||||
lib.set_fn_1("to_int", |x: f64| Ok(x as INT));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_module]
|
||||
mod trig {
|
||||
use crate::parser::FLOAT;
|
||||
|
||||
pub fn sin(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().sin()
|
||||
}
|
||||
pub fn cos(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().cos()
|
||||
}
|
||||
pub fn tan(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().tan()
|
||||
}
|
||||
pub fn sinh(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().sinh()
|
||||
}
|
||||
pub fn cosh(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().cosh()
|
||||
}
|
||||
pub fn tanh(x: FLOAT) -> FLOAT {
|
||||
x.to_radians().tanh()
|
||||
}
|
||||
pub fn asin(x: FLOAT) -> FLOAT {
|
||||
x.asin().to_degrees()
|
||||
}
|
||||
pub fn acos(x: FLOAT) -> FLOAT {
|
||||
x.acos().to_degrees()
|
||||
}
|
||||
pub fn atan(x: FLOAT) -> FLOAT {
|
||||
x.atan().to_degrees()
|
||||
}
|
||||
pub fn asinh(x: FLOAT) -> FLOAT {
|
||||
x.asinh().to_degrees()
|
||||
}
|
||||
pub fn acosh(x: FLOAT) -> FLOAT {
|
||||
x.acosh().to_degrees()
|
||||
}
|
||||
pub fn atanh(x: FLOAT) -> FLOAT {
|
||||
x.atanh().to_degrees()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_module]
|
||||
mod float {
|
||||
use crate::parser::FLOAT;
|
||||
|
||||
pub fn sqrt(x: FLOAT) -> FLOAT {
|
||||
x.sqrt()
|
||||
}
|
||||
pub fn exp(x: FLOAT) -> FLOAT {
|
||||
x.exp()
|
||||
}
|
||||
pub fn ln(x: FLOAT) -> FLOAT {
|
||||
x.ln()
|
||||
}
|
||||
pub fn log(x: FLOAT, base: FLOAT) -> FLOAT {
|
||||
x.log(base)
|
||||
}
|
||||
pub fn log10(x: FLOAT) -> FLOAT {
|
||||
x.log10()
|
||||
}
|
||||
pub fn floor(x: FLOAT) -> FLOAT {
|
||||
x.floor()
|
||||
}
|
||||
pub fn ceiling(x: FLOAT) -> FLOAT {
|
||||
x.ceil()
|
||||
}
|
||||
pub fn round(x: FLOAT) -> FLOAT {
|
||||
x.ceil()
|
||||
}
|
||||
pub fn int(x: FLOAT) -> FLOAT {
|
||||
x.trunc()
|
||||
}
|
||||
pub fn fraction(x: FLOAT) -> FLOAT {
|
||||
x.fract()
|
||||
}
|
||||
pub fn is_nan(x: FLOAT) -> bool {
|
||||
x.is_nan()
|
||||
}
|
||||
pub fn is_finite(x: FLOAT) -> bool {
|
||||
x.is_finite()
|
||||
}
|
||||
pub fn is_infinite(x: FLOAT) -> bool {
|
||||
x.is_infinite()
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ use super::logic::{eq, gt, gte, lt, lte, ne};
|
||||
use super::math_basic::MAX_INT;
|
||||
|
||||
use crate::def_package;
|
||||
use crate::engine::make_getter;
|
||||
use crate::plugin::*;
|
||||
use crate::result::EvalAltResult;
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
@ -26,83 +28,112 @@ use instant::Instant;
|
||||
|
||||
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
|
||||
// Register date/time functions
|
||||
lib.set_fn_0("timestamp", || Ok(Instant::now()));
|
||||
set_exported_fn!(lib, "timestamp", create_timestamp);
|
||||
set_exported_fn!(lib, "elapsed", elapsed);
|
||||
|
||||
lib.set_fn_2(
|
||||
"-",
|
||||
|ts1: Instant, ts2: Instant| {
|
||||
if ts2 > ts1 {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
return Ok(-(ts2 - ts1).as_secs_f64());
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
set_exported_fn!(lib, make_getter("elapsed"), elapsed);
|
||||
|
||||
#[cfg(feature = "no_float")]
|
||||
{
|
||||
let seconds = (ts2 - ts1).as_secs();
|
||||
set_exported_fn!(lib, "-", time_diff);
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if seconds > (MAX_INT as u64) {
|
||||
return EvalAltResult::ErrorArithmetic(
|
||||
format!(
|
||||
"Integer overflow for timestamp duration: {}",
|
||||
-(seconds as i64)
|
||||
),
|
||||
Position::none(),
|
||||
).into();
|
||||
}
|
||||
//lib.merge(&exported_module!(time_compare));
|
||||
|
||||
return Ok(-(seconds as INT));
|
||||
}
|
||||
} else {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
return Ok((ts1 - ts2).as_secs_f64());
|
||||
lib.set_fn_2("<", |x:Instant, y:Instant| Ok(lt(x, y)));
|
||||
lib.set_fn_2("<=", |x:Instant, y:Instant| Ok(lte(x, y)));
|
||||
lib.set_fn_2(">", |x:Instant, y:Instant| Ok(gt(x, y)));
|
||||
lib.set_fn_2(">=", |x:Instant, y:Instant| Ok(gte(x, y)));
|
||||
lib.set_fn_2("==", |x:Instant, y:Instant| Ok(eq(x, y)));
|
||||
lib.set_fn_2("!=", |x:Instant, y:Instant| Ok(ne(x, y)));
|
||||
});
|
||||
|
||||
#[cfg(feature = "no_float")]
|
||||
{
|
||||
let seconds = (ts1 - ts2).as_secs();
|
||||
#[export_fn]
|
||||
fn create_timestamp() -> Instant {
|
||||
Instant::now()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if seconds > (MAX_INT as u64) {
|
||||
return EvalAltResult::ErrorArithmetic(
|
||||
format!("Integer overflow for timestamp duration: {}", seconds),
|
||||
Position::none(),
|
||||
).into();
|
||||
}
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_fn]
|
||||
fn elapsed(timestamp: &mut Instant) -> FLOAT {
|
||||
timestamp.elapsed().as_secs_f64() as FLOAT
|
||||
}
|
||||
|
||||
return Ok(seconds as INT);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
#[cfg(feature = "no_float")]
|
||||
#[export_fn(return_raw)]
|
||||
fn elapsed(timestamp: &mut Instant) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let seconds = timestamp.elapsed().as_secs();
|
||||
|
||||
lib.set_fn_2("<", lt::<Instant>);
|
||||
lib.set_fn_2("<=", lte::<Instant>);
|
||||
lib.set_fn_2(">", gt::<Instant>);
|
||||
lib.set_fn_2(">=", gte::<Instant>);
|
||||
lib.set_fn_2("==", eq::<Instant>);
|
||||
lib.set_fn_2("!=", ne::<Instant>);
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
fn elapsed (timestamp: &mut Instant) -> Result<FLOAT, Box<EvalAltResult>> {
|
||||
Ok(timestamp.elapsed().as_secs_f64())
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if seconds > (MAX_INT as u64) {
|
||||
return EvalAltResult::ErrorArithmetic(
|
||||
format!("Integer overflow for timestamp.elapsed: {}", seconds),
|
||||
Position::none(),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
|
||||
#[cfg(feature = "no_float")]
|
||||
fn elapsed (timestamp: &mut Instant) -> Result<INT, Box<EvalAltResult>> {
|
||||
let seconds = timestamp.elapsed().as_secs();
|
||||
Ok((seconds as INT).into())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[export_fn]
|
||||
fn time_diff(ts1: Instant, ts2: Instant) -> FLOAT {
|
||||
if ts2 > ts1 {
|
||||
-(ts2 - ts1).as_secs_f64() as FLOAT
|
||||
} else {
|
||||
(ts1 - ts2).as_secs_f64() as FLOAT
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "no_float")]
|
||||
#[export_fn(return_raw)]
|
||||
fn time_diff(ts1: Instant, ts2: Instant) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
if ts2 > ts1 {
|
||||
let seconds = (ts2 - ts1).as_secs();
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if seconds > (MAX_INT as u64) {
|
||||
return EvalAltResult::ErrorArithmetic(
|
||||
format!("Integer overflow for timestamp.elapsed: {}", seconds),
|
||||
format!("Integer overflow for timestamp duration: -{}", seconds),
|
||||
Position::none(),
|
||||
).into();
|
||||
)
|
||||
.into();
|
||||
}
|
||||
|
||||
Ok(seconds as INT)
|
||||
Ok(-(seconds as INT).into())
|
||||
} else {
|
||||
let seconds = (ts1 - ts2).as_secs();
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if seconds > (MAX_INT as u64) {
|
||||
return EvalAltResult::ErrorArithmetic(
|
||||
format!("Integer overflow for timestamp duration: {}", seconds),
|
||||
Position::none(),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
|
||||
Ok((seconds as INT).into())
|
||||
}
|
||||
}
|
||||
|
||||
lib.set_fn_1_mut("elapsed", elapsed);
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
lib.set_getter_fn("elapsed", elapsed);
|
||||
});
|
||||
#[export_module]
|
||||
mod time_compare {
|
||||
pub fn eq(x: Instant, y: Instant) -> bool {
|
||||
x == y
|
||||
}
|
||||
pub fn ne(x: Instant, y: Instant) -> bool {
|
||||
x != y
|
||||
}
|
||||
pub fn lt(x: Instant, y: Instant) -> bool {
|
||||
x < y
|
||||
}
|
||||
pub fn lte(x: Instant, y: Instant) -> bool {
|
||||
x <= y
|
||||
}
|
||||
pub fn gt(x: Instant, y: Instant) -> bool {
|
||||
x > y
|
||||
}
|
||||
pub fn gte(x: Instant, y: Instant) -> bool {
|
||||
x >= y
|
||||
}
|
||||
}
|
||||
|
@ -12,20 +12,42 @@ mod special_array_package {
|
||||
}
|
||||
}
|
||||
|
||||
#[export_fn]
|
||||
fn make_greeting(n: INT) -> String {
|
||||
format!("{} {}", n, if n > 1 { "kitties" } else { "kitty" }).into()
|
||||
macro_rules! gen_unary_functions {
|
||||
($op_name:ident = $op_fn:ident ( $($arg_type:ident),+ ) -> $return_type:ident) => {
|
||||
mod $op_name { $(
|
||||
pub mod $arg_type {
|
||||
use super::super::*;
|
||||
|
||||
#[export_fn]
|
||||
pub fn single(x: $arg_type) -> $return_type {
|
||||
super::super::$op_fn(x)
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! reg_functions {
|
||||
($mod_name:ident += $op_name:ident :: $func:ident ( $($arg_type:ident),+ )) => {
|
||||
$(register_exported_fn!($mod_name, stringify!($op_name), $op_name::$arg_type::$func);)*
|
||||
}
|
||||
}
|
||||
|
||||
fn make_greeting<T: std::fmt::Display>(n: T) -> String {
|
||||
format!("{} kitties", n)
|
||||
}
|
||||
|
||||
gen_unary_functions!(greet = make_greeting(INT, bool, char) -> String);
|
||||
|
||||
#[test]
|
||||
fn test_plugins_package() -> Result<(), Box<EvalAltResult>> {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
let mut m = exported_module!(special_array_package);
|
||||
set_exported_fn!(m, "greet", make_greeting);
|
||||
|
||||
let m = exported_module!(special_array_package);
|
||||
engine.load_package(m);
|
||||
|
||||
reg_functions!(engine += greet::single(INT, bool, char));
|
||||
|
||||
assert_eq!(engine.eval::<INT>("let a = [1, 2, 3]; len(a, 2)")?, 6);
|
||||
assert_eq!(
|
||||
engine.eval::<String>("let a = [1, 2, 3]; greet(len(a, 2))")?,
|
||||
|
Loading…
Reference in New Issue
Block a user