Convert some packages into plugins.

This commit is contained in:
Stephen Chung 2020-08-14 13:43:26 +08:00
parent 2495b367e5
commit c0dc47c9db
5 changed files with 361 additions and 261 deletions

View File

@ -535,45 +535,47 @@ impl Dynamic {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn from<T: Variant + Clone>(value: T) -> Self { pub fn from<T: Variant + Clone>(value: T) -> Self {
let type_id = TypeId::of::<T>(); if TypeId::of::<T>() == TypeId::of::<INT>() {
if type_id == TypeId::of::<INT>() {
return <dyn Any>::downcast_ref::<INT>(&value) return <dyn Any>::downcast_ref::<INT>(&value)
.unwrap() .unwrap()
.clone() .clone()
.into(); .into();
} }
#[cfg(not(feature = "no_float"))] #[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) return <dyn Any>::downcast_ref::<FLOAT>(&value)
.unwrap() .unwrap()
.clone() .clone()
.into(); .into();
} }
if type_id == TypeId::of::<bool>() { if TypeId::of::<T>() == TypeId::of::<bool>() {
return <dyn Any>::downcast_ref::<bool>(&value) return <dyn Any>::downcast_ref::<bool>(&value)
.unwrap() .unwrap()
.clone() .clone()
.into(); .into();
} }
if type_id == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return <dyn Any>::downcast_ref::<char>(&value) return <dyn Any>::downcast_ref::<char>(&value)
.unwrap() .unwrap()
.clone() .clone()
.into(); .into();
} }
if type_id == TypeId::of::<ImmutableString>() { if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
return <dyn Any>::downcast_ref::<ImmutableString>(&value) return <dyn Any>::downcast_ref::<ImmutableString>(&value)
.unwrap() .unwrap()
.clone() .clone()
.into(); .into();
} }
if type_id == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return ().into(); return ().into();
} }
let mut boxed = Box::new(value); 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) { boxed = match unsafe_cast_box::<_, String>(boxed) {
Ok(s) => return (*s).into(), Ok(s) => return (*s).into(),
Err(val) => val, Err(val) => val,
@ -599,11 +601,6 @@ impl Dynamic {
Err(val) => val, Err(val) => val,
}; };
boxed = match unsafe_cast_box::<_, Dynamic>(boxed) {
Ok(d) => return *d,
Err(val) => val,
};
Self(Union::Variant(Box::new(boxed))) Self(Union::Variant(Box::new(boxed)))
} }
@ -660,8 +657,6 @@ impl Dynamic {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn try_cast<T: Variant>(self) -> Option<T> { pub fn try_cast<T: Variant>(self) -> Option<T> {
let type_id = TypeId::of::<T>();
match self.0 { match self.0 {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))] #[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); 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 { return match self.0 {
Union::Int(value) => unsafe_try_cast(value), Union::Int(value) => unsafe_try_cast(value),
_ => None, _ => None,
@ -685,35 +680,35 @@ impl Dynamic {
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if type_id == TypeId::of::<FLOAT>() { if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
return match self.0 { return match self.0 {
Union::Float(value) => unsafe_try_cast(value), Union::Float(value) => unsafe_try_cast(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<bool>() { if TypeId::of::<T>() == TypeId::of::<bool>() {
return match self.0 { return match self.0 {
Union::Bool(value) => unsafe_try_cast(value), Union::Bool(value) => unsafe_try_cast(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<ImmutableString>() { if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
return match self.0 { return match self.0 {
Union::Str(value) => unsafe_try_cast(value), Union::Str(value) => unsafe_try_cast(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<String>() { if TypeId::of::<T>() == TypeId::of::<String>() {
return match self.0 { return match self.0 {
Union::Str(value) => unsafe_try_cast(value.into_owned()), Union::Str(value) => unsafe_try_cast(value.into_owned()),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return match self.0 { return match self.0 {
Union::Char(value) => unsafe_try_cast(value), Union::Char(value) => unsafe_try_cast(value),
_ => None, _ => None,
@ -721,7 +716,7 @@ impl Dynamic {
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if type_id == TypeId::of::<Array>() { if TypeId::of::<T>() == TypeId::of::<Array>() {
return match self.0 { return match self.0 {
Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
_ => None, _ => None,
@ -729,21 +724,21 @@ impl Dynamic {
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if type_id == TypeId::of::<Map>() { if TypeId::of::<T>() == TypeId::of::<Map>() {
return match self.0 { return match self.0 {
Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<FnPtr>() { if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
return match self.0 { return match self.0 {
Union::FnPtr(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), Union::FnPtr(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return match self.0 { return match self.0 {
Union::Unit(value) => unsafe_try_cast(value), Union::Unit(value) => unsafe_try_cast(value),
_ => None, _ => None,
@ -928,72 +923,70 @@ impl Dynamic {
/// Returns `None` if the cast fails, or if the value is shared. /// Returns `None` if the cast fails, or if the value is shared.
#[inline(always)] #[inline(always)]
pub(crate) fn downcast_ref<T: Variant + Clone>(&self) -> Option<&T> { pub(crate) fn downcast_ref<T: Variant + Clone>(&self) -> Option<&T> {
let type_id = TypeId::of::<T>(); if TypeId::of::<T>() == TypeId::of::<INT>() {
if type_id == TypeId::of::<INT>() {
return match &self.0 { return match &self.0 {
Union::Int(value) => <dyn Any>::downcast_ref::<T>(value), Union::Int(value) => <dyn Any>::downcast_ref::<T>(value),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if type_id == TypeId::of::<FLOAT>() { if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
return match &self.0 { return match &self.0 {
Union::Float(value) => <dyn Any>::downcast_ref::<T>(value), Union::Float(value) => <dyn Any>::downcast_ref::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<bool>() { if TypeId::of::<T>() == TypeId::of::<bool>() {
return match &self.0 { return match &self.0 {
Union::Bool(value) => <dyn Any>::downcast_ref::<T>(value), Union::Bool(value) => <dyn Any>::downcast_ref::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<ImmutableString>() { if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
return match &self.0 { return match &self.0 {
Union::Str(value) => <dyn Any>::downcast_ref::<T>(value), Union::Str(value) => <dyn Any>::downcast_ref::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<String>() { if TypeId::of::<T>() == TypeId::of::<String>() {
return match &self.0 { return match &self.0 {
Union::Str(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()), Union::Str(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return match &self.0 { return match &self.0 {
Union::Char(value) => <dyn Any>::downcast_ref::<T>(value), Union::Char(value) => <dyn Any>::downcast_ref::<T>(value),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if type_id == TypeId::of::<Array>() { if TypeId::of::<T>() == TypeId::of::<Array>() {
return match &self.0 { return match &self.0 {
Union::Array(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()), Union::Array(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if type_id == TypeId::of::<Map>() { if TypeId::of::<T>() == TypeId::of::<Map>() {
return match &self.0 { return match &self.0 {
Union::Map(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()), Union::Map(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<FnPtr>() { if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
return match &self.0 { return match &self.0 {
Union::FnPtr(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()), Union::FnPtr(value) => <dyn Any>::downcast_ref::<T>(value.as_ref()),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return match &self.0 { return match &self.0 {
Union::Unit(value) => <dyn Any>::downcast_ref::<T>(value), Union::Unit(value) => <dyn Any>::downcast_ref::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<Dynamic>() { if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
return <dyn Any>::downcast_ref::<T>(self); 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. /// Returns `None` if the cast fails, or if the value is shared.
#[inline(always)] #[inline(always)]
pub(crate) fn downcast_mut<T: Variant + Clone>(&mut self) -> Option<&mut T> { pub(crate) fn downcast_mut<T: Variant + Clone>(&mut self) -> Option<&mut T> {
let type_id = TypeId::of::<T>(); if TypeId::of::<T>() == TypeId::of::<INT>() {
if type_id == TypeId::of::<INT>() {
return match &mut self.0 { return match &mut self.0 {
Union::Int(value) => <dyn Any>::downcast_mut::<T>(value), Union::Int(value) => <dyn Any>::downcast_mut::<T>(value),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if type_id == TypeId::of::<FLOAT>() { if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
return match &mut self.0 { return match &mut self.0 {
Union::Float(value) => <dyn Any>::downcast_mut::<T>(value), Union::Float(value) => <dyn Any>::downcast_mut::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<bool>() { if TypeId::of::<T>() == TypeId::of::<bool>() {
return match &mut self.0 { return match &mut self.0 {
Union::Bool(value) => <dyn Any>::downcast_mut::<T>(value), Union::Bool(value) => <dyn Any>::downcast_mut::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<ImmutableString>() { if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
return match &mut self.0 { return match &mut self.0 {
Union::Str(value) => <dyn Any>::downcast_mut::<T>(value), Union::Str(value) => <dyn Any>::downcast_mut::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return match &mut self.0 { return match &mut self.0 {
Union::Char(value) => <dyn Any>::downcast_mut::<T>(value), Union::Char(value) => <dyn Any>::downcast_mut::<T>(value),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if type_id == TypeId::of::<Array>() { if TypeId::of::<T>() == TypeId::of::<Array>() {
return match &mut self.0 { return match &mut self.0 {
Union::Array(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()), Union::Array(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if type_id == TypeId::of::<Map>() { if TypeId::of::<T>() == TypeId::of::<Map>() {
return match &mut self.0 { return match &mut self.0 {
Union::Map(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()), Union::Map(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<FnPtr>() { if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
return match &mut self.0 { return match &mut self.0 {
Union::FnPtr(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()), Union::FnPtr(value) => <dyn Any>::downcast_mut::<T>(value.as_mut()),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return match &mut self.0 { return match &mut self.0 {
Union::Unit(value) => <dyn Any>::downcast_mut::<T>(value), Union::Unit(value) => <dyn Any>::downcast_mut::<T>(value),
_ => None, _ => None,
}; };
} }
if type_id == TypeId::of::<Dynamic>() { if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
return <dyn Any>::downcast_mut::<T>(self); return <dyn Any>::downcast_mut::<T>(self);
} }

View File

@ -1,65 +1,126 @@
use crate::def_package; use crate::def_package;
use crate::module::FuncReturn; use crate::plugin::*;
// Comparison operators macro_rules! gen_cmp_functions {
pub fn lt<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> { ($op_name:tt = $op_fn:ident ( $($arg_type:ident),+ ) -> $return_type:ident) => {
Ok(x < y) pub mod $op_fn { $(
} pub mod $arg_type {
pub fn lte<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> { use crate::plugin::*;
Ok(x <= y)
} pub const OP_NAME: &'static str = $op_name;
pub fn gt<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> {
Ok(x > y) #[export_fn]
} pub fn cmp_func(x: $arg_type, y: $arg_type) -> $return_type {
pub fn gte<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> { super::super::super::$op_fn(x, y)
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)
} }
// Logic operators macro_rules! reg_functions {
fn not(x: bool) -> FuncReturn<bool> { ($mod_name:ident += $root:ident :: $op_name:ident ( $($arg_type:ident),+ )) => {
Ok(!x) $(set_exported_fn!($mod_name, $root::$op_name::$arg_type::OP_NAME, $root::$op_name::$arg_type::cmp_func);)*
} }
macro_rules! reg_op {
($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
$( $lib.set_fn_2($op, $func::<$par>); )*
};
} }
def_package!(crate:LogicPackage:"Logical operators.", lib, { def_package!(crate:LogicPackage:"Logical operators.", lib, {
if cfg!(not(feature = "only_i32")) && cfg!(not(feature = "only_i64")) { #[cfg(not(feature = "only_i32"))]
reg_op!(lib, "<", lt, i8, u8, i16, u16, i32, u32, u64); #[cfg(not(feature = "only_i64"))]
reg_op!(lib, "<=", lte, i8, u8, i16, u16, i32, u32, u64); {
reg_op!(lib, ">", gt, i8, u8, i16, u16, i32, u32, u64); reg_functions!(lib += cmp::lt(i8, u8, i16, u16, i32, u32, u64));
reg_op!(lib, ">=", gte, i8, u8, i16, u16, i32, u32, u64); reg_functions!(lib += cmp::lte(i8, u8, i16, u16, i32, u32, u64));
reg_op!(lib, "==", eq, i8, u8, i16, u16, i32, u32, u64); reg_functions!(lib += cmp::gt(i8, u8, i16, u16, i32, u32, u64));
reg_op!(lib, "!=", ne, 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")) { #[cfg(not(target_arch = "wasm32"))]
reg_op!(lib, "<", lt, i128, u128); {
reg_op!(lib, "<=", lte, i128, u128); reg_functions!(lib += cmp_128::lt(i128, u128));
reg_op!(lib, ">", gt, i128, u128); reg_functions!(lib += cmp_128::lte(i128, u128));
reg_op!(lib, ">=", gte, i128, u128); reg_functions!(lib += cmp_128::gt(i128, u128));
reg_op!(lib, "==", eq, i128, u128); reg_functions!(lib += cmp_128::gte(i128, u128));
reg_op!(lib, "!=", ne, i128, u128); reg_functions!(lib += cmp_128::eq(i128, u128));
reg_functions!(lib += cmp_128::ne(i128, u128));
} }
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
{ {
reg_op!(lib, "<", lt, f32); reg_functions!(lib += cmp_float::lt(f32));
reg_op!(lib, "<=", lte, f32); reg_functions!(lib += cmp_float::lte(f32));
reg_op!(lib, ">", gt, f32); reg_functions!(lib += cmp_float::gt(f32));
reg_op!(lib, ">=", gte, f32); reg_functions!(lib += cmp_float::gte(f32));
reg_op!(lib, "==", eq, f32); reg_functions!(lib += cmp_float::eq(f32));
reg_op!(lib, "!=", ne, 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);
}

View File

@ -1,5 +1,4 @@
use crate::def_package; use crate::def_package;
use crate::module::Module;
use crate::parser::INT; use crate::parser::INT;
use crate::plugin::*; use crate::plugin::*;
@ -24,99 +23,6 @@ pub const MAX_INT: INT = i32::MAX;
pub const MAX_INT: INT = i64::MAX; pub const MAX_INT: INT = i64::MAX;
def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, { 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"))] #[cfg(not(feature = "no_float"))]
{ {
// Floating point functions // 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)); 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()
}
} }

View File

@ -6,6 +6,8 @@ use super::logic::{eq, gt, gte, lt, lte, ne};
use super::math_basic::MAX_INT; use super::math_basic::MAX_INT;
use crate::def_package; use crate::def_package;
use crate::engine::make_getter;
use crate::plugin::*;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
@ -26,83 +28,112 @@ use instant::Instant;
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, { def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
// Register date/time functions // 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( #[cfg(not(feature = "no_object"))]
"-", set_exported_fn!(lib, make_getter("elapsed"), elapsed);
|ts1: Instant, ts2: Instant| {
if ts2 > ts1 {
#[cfg(not(feature = "no_float"))]
return Ok(-(ts2 - ts1).as_secs_f64());
#[cfg(feature = "no_float")] set_exported_fn!(lib, "-", time_diff);
{
let seconds = (ts2 - ts1).as_secs();
#[cfg(not(feature = "unchecked"))] //lib.merge(&exported_module!(time_compare));
if seconds > (MAX_INT as u64) {
return EvalAltResult::ErrorArithmetic(
format!(
"Integer overflow for timestamp duration: {}",
-(seconds as i64)
),
Position::none(),
).into();
}
return Ok(-(seconds as INT)); lib.set_fn_2("<", |x:Instant, y:Instant| Ok(lt(x, y)));
} lib.set_fn_2("<=", |x:Instant, y:Instant| Ok(lte(x, y)));
} else { lib.set_fn_2(">", |x:Instant, y:Instant| Ok(gt(x, y)));
#[cfg(not(feature = "no_float"))] lib.set_fn_2(">=", |x:Instant, y:Instant| Ok(gte(x, y)));
return Ok((ts1 - ts2).as_secs_f64()); 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")] #[export_fn]
{ fn create_timestamp() -> Instant {
let seconds = (ts1 - ts2).as_secs(); Instant::now()
}
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_float"))]
if seconds > (MAX_INT as u64) { #[export_fn]
return EvalAltResult::ErrorArithmetic( fn elapsed(timestamp: &mut Instant) -> FLOAT {
format!("Integer overflow for timestamp duration: {}", seconds), timestamp.elapsed().as_secs_f64() as FLOAT
Position::none(), }
).into();
}
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>); #[cfg(not(feature = "unchecked"))]
lib.set_fn_2("<=", lte::<Instant>); if seconds > (MAX_INT as u64) {
lib.set_fn_2(">", gt::<Instant>); return EvalAltResult::ErrorArithmetic(
lib.set_fn_2(">=", gte::<Instant>); format!("Integer overflow for timestamp.elapsed: {}", seconds),
lib.set_fn_2("==", eq::<Instant>); Position::none(),
lib.set_fn_2("!=", ne::<Instant>); )
.into();
#[cfg(not(feature = "no_float"))]
fn elapsed (timestamp: &mut Instant) -> Result<FLOAT, Box<EvalAltResult>> {
Ok(timestamp.elapsed().as_secs_f64())
} }
#[cfg(feature = "no_float")] Ok((seconds as INT).into())
fn elapsed (timestamp: &mut Instant) -> Result<INT, Box<EvalAltResult>> { }
let seconds = timestamp.elapsed().as_secs();
#[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"))] #[cfg(not(feature = "unchecked"))]
if seconds > (MAX_INT as u64) { if seconds > (MAX_INT as u64) {
return EvalAltResult::ErrorArithmetic( return EvalAltResult::ErrorArithmetic(
format!("Integer overflow for timestamp.elapsed: {}", seconds), format!("Integer overflow for timestamp duration: -{}", seconds),
Position::none(), 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); #[export_module]
mod time_compare {
#[cfg(not(feature = "no_object"))] pub fn eq(x: Instant, y: Instant) -> bool {
lib.set_getter_fn("elapsed", elapsed); 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
}
}

View File

@ -12,20 +12,42 @@ mod special_array_package {
} }
} }
#[export_fn] macro_rules! gen_unary_functions {
fn make_greeting(n: INT) -> String { ($op_name:ident = $op_fn:ident ( $($arg_type:ident),+ ) -> $return_type:ident) => {
format!("{} {}", n, if n > 1 { "kitties" } else { "kitty" }).into() 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] #[test]
fn test_plugins_package() -> Result<(), Box<EvalAltResult>> { fn test_plugins_package() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new(); let mut engine = Engine::new();
let mut m = exported_module!(special_array_package); let m = exported_module!(special_array_package);
set_exported_fn!(m, "greet", make_greeting);
engine.load_package(m); 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::<INT>("let a = [1, 2, 3]; len(a, 2)")?, 6);
assert_eq!( assert_eq!(
engine.eval::<String>("let a = [1, 2, 3]; greet(len(a, 2))")?, engine.eval::<String>("let a = [1, 2, 3]; greet(len(a, 2))")?,