Reduce Rc/Arc wrapping for functions.
This commit is contained in:
parent
ab76a69b12
commit
4a1fd66b9f
@ -3,11 +3,11 @@
|
|||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
use crate::fn_native::{FnCallArgs, PrintCallback, ProgressCallback};
|
use crate::fn_native::{FnCallArgs, PrintCallback, ProgressCallback, SharedFnDef};
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage};
|
use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage};
|
||||||
use crate::parser::{Expr, FnAccess, FnDef, ReturnType, SharedFnDef, Stmt, AST};
|
use crate::parser::{Expr, FnAccess, FnDef, ReturnType, Stmt, AST};
|
||||||
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
@ -1741,7 +1741,7 @@ impl Engine {
|
|||||||
let index = scope.len() - 1;
|
let index = scope.len() - 1;
|
||||||
state.scope_level += 1;
|
state.scope_level += 1;
|
||||||
|
|
||||||
for loop_var in func.get_iter_fn()(iter_type) {
|
for loop_var in func(iter_type) {
|
||||||
*scope.get_mut(index).0 = loop_var;
|
*scope.get_mut(index).0 = loop_var;
|
||||||
self.inc_operations(state, stmt.position())?;
|
self.inc_operations(state, stmt.position())?;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::parser::{FnDef, SharedFnDef};
|
use crate::parser::FnDef;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
||||||
@ -73,15 +73,31 @@ pub trait IteratorCallback: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + '
|
|||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
impl<F: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static> IteratorCallback for F {}
|
impl<F: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static> IteratorCallback for F {}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type SharedNativeFunction = Rc<FnAny>;
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type SharedNativeFunction = Arc<FnAny>;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type SharedIteratorFn = Rc<IteratorFn>;
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type SharedIteratorFn = Arc<IteratorFn>;
|
||||||
|
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type SharedFnDef = Arc<FnDef>;
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type SharedFnDef = Rc<FnDef>;
|
||||||
|
|
||||||
/// A type encapsulating a function callable by Rhai.
|
/// A type encapsulating a function callable by Rhai.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum CallableFunction {
|
pub enum CallableFunction {
|
||||||
/// A pure native Rust function with all arguments passed by value.
|
/// A pure native Rust function with all arguments passed by value.
|
||||||
Pure(Box<FnAny>),
|
Pure(SharedNativeFunction),
|
||||||
/// A native Rust object method with the first argument passed by reference,
|
/// A native Rust object method with the first argument passed by reference,
|
||||||
/// and the rest passed by value.
|
/// and the rest passed by value.
|
||||||
Method(Box<FnAny>),
|
Method(SharedNativeFunction),
|
||||||
/// An iterator function.
|
/// An iterator function.
|
||||||
Iterator(Box<IteratorFn>),
|
Iterator(SharedIteratorFn),
|
||||||
/// A script-defined function.
|
/// A script-defined function.
|
||||||
Script(SharedFnDef),
|
Script(SharedFnDef),
|
||||||
}
|
}
|
||||||
@ -90,37 +106,29 @@ impl CallableFunction {
|
|||||||
/// Is this a pure native Rust function?
|
/// Is this a pure native Rust function?
|
||||||
pub fn is_pure(&self) -> bool {
|
pub fn is_pure(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Pure(_) => true,
|
Self::Pure(_) => true,
|
||||||
CallableFunction::Method(_)
|
Self::Method(_) | Self::Iterator(_) | Self::Script(_) => false,
|
||||||
| CallableFunction::Iterator(_)
|
|
||||||
| CallableFunction::Script(_) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is this a pure native Rust method-call?
|
/// Is this a pure native Rust method-call?
|
||||||
pub fn is_method(&self) -> bool {
|
pub fn is_method(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Method(_) => true,
|
Self::Method(_) => true,
|
||||||
CallableFunction::Pure(_)
|
Self::Pure(_) | Self::Iterator(_) | Self::Script(_) => false,
|
||||||
| CallableFunction::Iterator(_)
|
|
||||||
| CallableFunction::Script(_) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is this an iterator function?
|
/// Is this an iterator function?
|
||||||
pub fn is_iter(&self) -> bool {
|
pub fn is_iter(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Iterator(_) => true,
|
Self::Iterator(_) => true,
|
||||||
CallableFunction::Pure(_)
|
Self::Pure(_) | Self::Method(_) | Self::Script(_) => false,
|
||||||
| CallableFunction::Method(_)
|
|
||||||
| CallableFunction::Script(_) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is this a Rhai-scripted function?
|
/// Is this a Rhai-scripted function?
|
||||||
pub fn is_script(&self) -> bool {
|
pub fn is_script(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Script(_) => true,
|
Self::Script(_) => true,
|
||||||
CallableFunction::Pure(_)
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => false,
|
||||||
| CallableFunction::Method(_)
|
|
||||||
| CallableFunction::Iterator(_) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get a reference to a native Rust function.
|
/// Get a reference to a native Rust function.
|
||||||
@ -128,10 +136,10 @@ impl CallableFunction {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if the `CallableFunction` is not `Pure` or `Method`.
|
/// Panics if the `CallableFunction` is not `Pure` or `Method`.
|
||||||
pub fn get_native_fn(&self) -> &Box<FnAny> {
|
pub fn get_native_fn(&self) -> &FnAny {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Pure(f) | CallableFunction::Method(f) => f,
|
Self::Pure(f) | Self::Method(f) => f.as_ref(),
|
||||||
CallableFunction::Iterator(_) | CallableFunction::Script(_) => panic!(),
|
Self::Iterator(_) | Self::Script(_) => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get a reference to a script-defined function definition.
|
/// Get a reference to a script-defined function definition.
|
||||||
@ -141,10 +149,8 @@ impl CallableFunction {
|
|||||||
/// Panics if the `CallableFunction` is not `Script`.
|
/// Panics if the `CallableFunction` is not `Script`.
|
||||||
pub fn get_fn_def(&self) -> &FnDef {
|
pub fn get_fn_def(&self) -> &FnDef {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Pure(_)
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => panic!(),
|
||||||
| CallableFunction::Method(_)
|
Self::Script(f) => f,
|
||||||
| CallableFunction::Iterator(_) => panic!(),
|
|
||||||
CallableFunction::Script(f) => f,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get a reference to an iterator function.
|
/// Get a reference to an iterator function.
|
||||||
@ -152,19 +158,18 @@ impl CallableFunction {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if the `CallableFunction` is not `Iterator`.
|
/// Panics if the `CallableFunction` is not `Iterator`.
|
||||||
pub fn get_iter_fn(&self) -> &Box<IteratorFn> {
|
pub fn get_iter_fn(&self) -> &IteratorFn {
|
||||||
match self {
|
match self {
|
||||||
CallableFunction::Pure(_)
|
Self::Iterator(f) => f.as_ref(),
|
||||||
| CallableFunction::Method(_)
|
Self::Pure(_) | Self::Method(_) | Self::Script(_) => panic!(),
|
||||||
| CallableFunction::Script(_) => panic!(),
|
|
||||||
CallableFunction::Iterator(f) => f,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Create a new `CallableFunction::Pure`.
|
||||||
|
pub fn from_pure(func: Box<FnAny>) -> Self {
|
||||||
|
Self::Pure(func.into())
|
||||||
|
}
|
||||||
|
/// Create a new `CallableFunction::Method`.
|
||||||
|
pub fn from_method(func: Box<FnAny>) -> Self {
|
||||||
|
Self::Method(func.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A callable function.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type SharedFunction = Rc<CallableFunction>;
|
|
||||||
/// A callable function.
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type SharedFunction = Arc<CallableFunction>;
|
|
||||||
|
@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::fn_native::{
|
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs};
|
||||||
CallableFunction::{Method, Pure},
|
|
||||||
FnCallArgs,
|
|
||||||
};
|
|
||||||
use crate::parser::FnAccess;
|
use crate::parser::FnAccess;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
|
|
||||||
@ -158,7 +155,7 @@ macro_rules! make_func {
|
|||||||
|
|
||||||
// Map the result
|
// Map the result
|
||||||
$map(r)
|
$map(r)
|
||||||
})
|
}) as Box<FnAny>
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +181,7 @@ pub fn map_result<T: Variant + Clone>(
|
|||||||
|
|
||||||
macro_rules! def_register {
|
macro_rules! def_register {
|
||||||
() => {
|
() => {
|
||||||
def_register!(imp Pure :);
|
def_register!(imp from_pure :);
|
||||||
};
|
};
|
||||||
(imp $abi:ident : $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
|
(imp $abi:ident : $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
|
||||||
// ^ function ABI type
|
// ^ function ABI type
|
||||||
@ -207,7 +204,7 @@ macro_rules! def_register {
|
|||||||
fn register_fn(&mut self, name: &str, f: FN) {
|
fn register_fn(&mut self, name: &str, f: FN) {
|
||||||
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
||||||
&[$(TypeId::of::<$par>()),*],
|
&[$(TypeId::of::<$par>()),*],
|
||||||
$abi(make_func!(f : map_dynamic ; $($par => $clone),*))
|
CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $clone),*))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +222,7 @@ macro_rules! def_register {
|
|||||||
fn register_dynamic_fn(&mut self, name: &str, f: FN) {
|
fn register_dynamic_fn(&mut self, name: &str, f: FN) {
|
||||||
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
||||||
&[$(TypeId::of::<$par>()),*],
|
&[$(TypeId::of::<$par>()),*],
|
||||||
$abi(make_func!(f : map_identity ; $($par => $clone),*))
|
CallableFunction::$abi(make_func!(f : map_identity ; $($par => $clone),*))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,7 +241,7 @@ macro_rules! def_register {
|
|||||||
fn register_result_fn(&mut self, name: &str, f: FN) {
|
fn register_result_fn(&mut self, name: &str, f: FN) {
|
||||||
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
||||||
&[$(TypeId::of::<$par>()),*],
|
&[$(TypeId::of::<$par>()),*],
|
||||||
$abi(make_func!(f : map_result ; $($par => $clone),*))
|
CallableFunction::$abi(make_func!(f : map_result ; $($par => $clone),*))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,11 +249,11 @@ macro_rules! def_register {
|
|||||||
//def_register!(imp_pop $($par => $mark => $param),*);
|
//def_register!(imp_pop $($par => $mark => $param),*);
|
||||||
};
|
};
|
||||||
($p0:ident $(, $p:ident)*) => {
|
($p0:ident $(, $p:ident)*) => {
|
||||||
def_register!(imp Pure : $p0 => $p0 => $p0 => by_value $(, $p => $p => $p => by_value)*);
|
def_register!(imp from_pure : $p0 => $p0 => $p0 => by_value $(, $p => $p => $p => by_value)*);
|
||||||
def_register!(imp Method : $p0 => Mut<$p0> => &mut $p0 => by_ref $(, $p => $p => $p => by_value)*);
|
def_register!(imp from_method : $p0 => Mut<$p0> => &mut $p0 => by_ref $(, $p => $p => $p => by_value)*);
|
||||||
// ^ CallableFunction
|
// ^ CallableFunction
|
||||||
// handle the first parameter ^ first parameter passed through
|
// handle the first parameter ^ first parameter passed through
|
||||||
// ^ others passed by value (by_value)
|
// ^ others passed by value (by_value)
|
||||||
|
|
||||||
// Currently does not support first argument which is a reference, as there will be
|
// Currently does not support first argument which is a reference, as there will be
|
||||||
// conflicting implementations since &T: Any and T: Any cannot be distinguished
|
// conflicting implementations since &T: Any and T: Any cannot be distinguished
|
||||||
|
@ -3,11 +3,7 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{Engine, FunctionsLib};
|
use crate::engine::{Engine, FunctionsLib};
|
||||||
use crate::fn_native::{
|
use crate::fn_native::{CallableFunction as CF, FnCallArgs, IteratorFn, SharedIteratorFn};
|
||||||
CallableFunction,
|
|
||||||
CallableFunction::{Method, Pure},
|
|
||||||
FnCallArgs, IteratorFn, SharedFunction,
|
|
||||||
};
|
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
FnAccess,
|
FnAccess,
|
||||||
FnAccess::{Private, Public},
|
FnAccess::{Private, Public},
|
||||||
@ -27,9 +23,7 @@ use crate::stdlib::{
|
|||||||
mem,
|
mem,
|
||||||
num::NonZeroUsize,
|
num::NonZeroUsize,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
rc::Rc,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::Arc,
|
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
@ -53,17 +47,17 @@ pub struct Module {
|
|||||||
all_variables: HashMap<u64, Dynamic>,
|
all_variables: HashMap<u64, Dynamic>,
|
||||||
|
|
||||||
/// External Rust functions.
|
/// External Rust functions.
|
||||||
functions: HashMap<u64, (String, FnAccess, StaticVec<TypeId>, SharedFunction)>,
|
functions: HashMap<u64, (String, FnAccess, StaticVec<TypeId>, CF)>,
|
||||||
|
|
||||||
/// Script-defined functions.
|
/// Script-defined functions.
|
||||||
fn_lib: FunctionsLib,
|
fn_lib: FunctionsLib,
|
||||||
|
|
||||||
/// Iterator functions, keyed by the type producing the iterator.
|
/// Iterator functions, keyed by the type producing the iterator.
|
||||||
type_iterators: HashMap<TypeId, SharedFunction>,
|
type_iterators: HashMap<TypeId, SharedIteratorFn>,
|
||||||
|
|
||||||
/// Flattened collection of all external Rust functions, native or scripted,
|
/// Flattened collection of all external Rust functions, native or scripted,
|
||||||
/// including those in sub-modules.
|
/// including those in sub-modules.
|
||||||
all_functions: HashMap<u64, SharedFunction>,
|
all_functions: HashMap<u64, CF>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Module {
|
impl fmt::Debug for Module {
|
||||||
@ -275,13 +269,7 @@ impl Module {
|
|||||||
/// Set a Rust function into the module, returning a hash key.
|
/// Set a Rust function into the module, returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is an existing Rust function of the same hash, it is replaced.
|
/// If there is an existing Rust function of the same hash, it is replaced.
|
||||||
pub fn set_fn(
|
pub fn set_fn(&mut self, name: String, access: FnAccess, params: &[TypeId], func: CF) -> u64 {
|
||||||
&mut self,
|
|
||||||
name: String,
|
|
||||||
access: FnAccess,
|
|
||||||
params: &[TypeId],
|
|
||||||
func: CallableFunction,
|
|
||||||
) -> u64 {
|
|
||||||
let hash_fn = calc_fn_hash(empty(), &name, params.len(), params.iter().cloned());
|
let hash_fn = calc_fn_hash(empty(), &name, params.len(), params.iter().cloned());
|
||||||
|
|
||||||
let params = params.into_iter().cloned().collect();
|
let params = params.into_iter().cloned().collect();
|
||||||
@ -312,8 +300,8 @@ impl Module {
|
|||||||
#[cfg(feature = "sync")] func: impl Fn() -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn() -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
|
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
|
||||||
let arg_types = [];
|
let args = [];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking one parameter into the module, returning a hash key.
|
/// Set a Rust function taking one parameter into the module, returning a hash key.
|
||||||
@ -337,8 +325,8 @@ impl Module {
|
|||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f =
|
let f =
|
||||||
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
|
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
|
||||||
let arg_types = [TypeId::of::<A>()];
|
let args = [TypeId::of::<A>()];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking one mutable parameter into the module, returning a hash key.
|
/// Set a Rust function taking one mutable parameter into the module, returning a hash key.
|
||||||
@ -363,8 +351,8 @@ impl Module {
|
|||||||
let f = move |args: &mut FnCallArgs| {
|
let f = move |args: &mut FnCallArgs| {
|
||||||
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>()];
|
let args = [TypeId::of::<A>()];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Method(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_method(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking two parameters into the module, returning a hash key.
|
/// Set a Rust function taking two parameters into the module, returning a hash key.
|
||||||
@ -394,8 +382,8 @@ impl Module {
|
|||||||
|
|
||||||
func(a, b).map(Dynamic::from)
|
func(a, b).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let args = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking two parameters (the first one mutable) into the module,
|
/// Set a Rust function taking two parameters (the first one mutable) into the module,
|
||||||
@ -429,8 +417,8 @@ impl Module {
|
|||||||
|
|
||||||
func(a, b).map(Dynamic::from)
|
func(a, b).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let args = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Method(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_method(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking three parameters into the module, returning a hash key.
|
/// Set a Rust function taking three parameters into the module, returning a hash key.
|
||||||
@ -467,8 +455,8 @@ impl Module {
|
|||||||
|
|
||||||
func(a, b, c).map(Dynamic::from)
|
func(a, b, c).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let args = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking three parameters (the first one mutable) into the module,
|
/// Set a Rust function taking three parameters (the first one mutable) into the module,
|
||||||
@ -506,8 +494,8 @@ impl Module {
|
|||||||
|
|
||||||
func(a, b, c).map(Dynamic::from)
|
func(a, b, c).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let args = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(name.into(), Public, &arg_types, Method(Box::new(f)))
|
self.set_fn(name.into(), Public, &args, CF::from_method(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a Rust function.
|
/// Get a Rust function.
|
||||||
@ -524,8 +512,8 @@ impl Module {
|
|||||||
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
||||||
/// assert!(module.get_fn(hash).is_some());
|
/// assert!(module.get_fn(hash).is_some());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
|
pub fn get_fn(&self, hash_fn: u64) -> Option<&CF> {
|
||||||
self.functions.get(&hash_fn).map(|(_, _, _, v)| v.as_ref())
|
self.functions.get(&hash_fn).map(|(_, _, _, v)| v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a modules-qualified function.
|
/// Get a modules-qualified function.
|
||||||
@ -536,16 +524,13 @@ impl Module {
|
|||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
hash_fn_native: u64,
|
hash_fn_native: u64,
|
||||||
) -> Result<&CallableFunction, Box<EvalAltResult>> {
|
) -> Result<&CF, Box<EvalAltResult>> {
|
||||||
self.all_functions
|
self.all_functions.get(&hash_fn_native).ok_or_else(|| {
|
||||||
.get(&hash_fn_native)
|
Box::new(EvalAltResult::ErrorFunctionNotFound(
|
||||||
.map(|f| f.as_ref())
|
name.to_string(),
|
||||||
.ok_or_else(|| {
|
Position::none(),
|
||||||
Box::new(EvalAltResult::ErrorFunctionNotFound(
|
))
|
||||||
name.to_string(),
|
})
|
||||||
Position::none(),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `Module` by evaluating an `AST`.
|
/// Create a new `Module` by evaluating an `AST`.
|
||||||
@ -606,7 +591,7 @@ impl Module {
|
|||||||
module: &'a Module,
|
module: &'a Module,
|
||||||
qualifiers: &mut Vec<&'a str>,
|
qualifiers: &mut Vec<&'a str>,
|
||||||
variables: &mut Vec<(u64, Dynamic)>,
|
variables: &mut Vec<(u64, Dynamic)>,
|
||||||
functions: &mut Vec<(u64, SharedFunction)>,
|
functions: &mut Vec<(u64, CF)>,
|
||||||
) {
|
) {
|
||||||
for (name, m) in &module.modules {
|
for (name, m) in &module.modules {
|
||||||
// Index all the sub-modules first.
|
// Index all the sub-modules first.
|
||||||
@ -655,7 +640,7 @@ impl Module {
|
|||||||
fn_def.params.len(),
|
fn_def.params.len(),
|
||||||
empty(),
|
empty(),
|
||||||
);
|
);
|
||||||
functions.push((hash_fn_def, CallableFunction::Script(fn_def.clone()).into()));
|
functions.push((hash_fn_def, CF::Script(fn_def.clone()).into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,16 +660,11 @@ impl Module {
|
|||||||
|
|
||||||
/// Set a type iterator into the module.
|
/// Set a type iterator into the module.
|
||||||
pub fn set_iter(&mut self, typ: TypeId, func: Box<IteratorFn>) {
|
pub fn set_iter(&mut self, typ: TypeId, func: Box<IteratorFn>) {
|
||||||
#[cfg(not(feature = "sync"))]
|
self.type_iterators.insert(typ, func.into());
|
||||||
self.type_iterators
|
|
||||||
.insert(typ, Rc::new(CallableFunction::Iterator(func)));
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
self.type_iterators
|
|
||||||
.insert(typ, Arc::new(CallableFunction::Iterator(func)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the specified type iterator.
|
/// Get the specified type iterator.
|
||||||
pub fn get_iter(&self, id: TypeId) -> Option<&CallableFunction> {
|
pub fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
|
||||||
self.type_iterators.get(&id).map(|v| v.as_ref())
|
self.type_iterators.get(&id).map(|v| v.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
||||||
|
|
||||||
use crate::fn_native::CallableFunction;
|
use crate::fn_native::{CallableFunction, IteratorFn};
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::utils::StaticVec;
|
use crate::utils::StaticVec;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ impl PackagesCollection {
|
|||||||
self.packages.iter().any(|p| p.contains_iter(id))
|
self.packages.iter().any(|p| p.contains_iter(id))
|
||||||
}
|
}
|
||||||
/// Get the specified TypeId iterator.
|
/// Get the specified TypeId iterator.
|
||||||
pub fn get_iter(&self, id: TypeId) -> Option<&CallableFunction> {
|
pub fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
|
||||||
self.packages
|
self.packages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.get_iter(id))
|
.map(|p| p.get_iter(id))
|
||||||
|
@ -25,9 +25,7 @@ use crate::stdlib::{
|
|||||||
iter::{empty, Peekable},
|
iter::{empty, Peekable},
|
||||||
num::NonZeroUsize,
|
num::NonZeroUsize,
|
||||||
ops::{Add, Deref, DerefMut},
|
ops::{Add, Deref, DerefMut},
|
||||||
rc::Rc,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::Arc,
|
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
@ -59,21 +57,14 @@ type PERR = ParseErrorType;
|
|||||||
pub struct AST(
|
pub struct AST(
|
||||||
/// Global statements.
|
/// Global statements.
|
||||||
Vec<Stmt>,
|
Vec<Stmt>,
|
||||||
/// Script-defined functions, wrapped in an `Arc` for shared access.
|
/// Script-defined functions.
|
||||||
#[cfg(feature = "sync")]
|
FunctionsLib,
|
||||||
Arc<FunctionsLib>,
|
|
||||||
/// Script-defined functions, wrapped in an `Rc` for shared access.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
Rc<FunctionsLib>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
impl AST {
|
impl AST {
|
||||||
/// Create a new `AST`.
|
/// Create a new `AST`.
|
||||||
pub fn new(statements: Vec<Stmt>, fn_lib: FunctionsLib) -> Self {
|
pub fn new(statements: Vec<Stmt>, fn_lib: FunctionsLib) -> Self {
|
||||||
#[cfg(feature = "sync")]
|
Self(statements, fn_lib)
|
||||||
return Self(statements, Arc::new(fn_lib));
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
return Self(statements, Rc::new(fn_lib));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the statements.
|
/// Get the statements.
|
||||||
@ -88,7 +79,7 @@ impl AST {
|
|||||||
|
|
||||||
/// Get the script-defined functions.
|
/// Get the script-defined functions.
|
||||||
pub(crate) fn fn_lib(&self) -> &FunctionsLib {
|
pub(crate) fn fn_lib(&self) -> &FunctionsLib {
|
||||||
self.1.as_ref()
|
&self.1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge two `AST` into one. Both `AST`'s are untouched and a new, merged, version
|
/// Merge two `AST` into one. Both `AST`'s are untouched and a new, merged, version
|
||||||
@ -147,20 +138,13 @@ impl AST {
|
|||||||
(true, true) => vec![],
|
(true, true) => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::new(ast, functions.merge(other.1.as_ref()))
|
Self::new(ast, functions.merge(&other.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all function definitions in the `AST`.
|
/// Clear all function definitions in the `AST`.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub fn clear_functions(&mut self) {
|
pub fn clear_functions(&mut self) {
|
||||||
#[cfg(feature = "sync")]
|
self.1 = Default::default();
|
||||||
{
|
|
||||||
self.1 = Arc::new(Default::default());
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
{
|
|
||||||
self.1 = Rc::new(Default::default());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all statements in the `AST`, leaving only function definitions.
|
/// Clear all statements in the `AST`, leaving only function definitions.
|
||||||
@ -202,13 +186,6 @@ pub struct FnDef {
|
|||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sharable script-defined function.
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type SharedFnDef = Arc<FnDef>;
|
|
||||||
/// A sharable script-defined function.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type SharedFnDef = Rc<FnDef>;
|
|
||||||
|
|
||||||
/// `return`/`throw` statement.
|
/// `return`/`throw` statement.
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
pub enum ReturnType {
|
pub enum ReturnType {
|
||||||
|
Loading…
Reference in New Issue
Block a user