Reduce Rc/Arc wrapping for functions.

This commit is contained in:
Stephen Chung 2020-05-19 22:25:57 +08:00
parent ab76a69b12
commit 4a1fd66b9f
6 changed files with 97 additions and 138 deletions

View File

@ -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())?;

View File

@ -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>;

View File

@ -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,8 +249,8 @@ 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)

View File

@ -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,11 +524,8 @@ 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)
.map(|f| f.as_ref())
.ok_or_else(|| {
Box::new(EvalAltResult::ErrorFunctionNotFound( Box::new(EvalAltResult::ErrorFunctionNotFound(
name.to_string(), name.to_string(),
Position::none(), Position::none(),
@ -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())
} }
} }

View File

@ -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))

View File

@ -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 {