Use function pointers for iterators.

This commit is contained in:
Stephen Chung 2020-05-20 19:27:23 +08:00
parent 55ee4d6a19
commit 80fcc40710
6 changed files with 23 additions and 57 deletions

View File

@ -4,9 +4,7 @@ use crate::any::{Dynamic, Variant};
use crate::engine::{make_getter, make_setter, Engine, State, FUNC_INDEXER};
use crate::error::ParseError;
use crate::fn_call::FuncArgs;
use crate::fn_native::{
IteratorCallback, ObjectGetCallback, ObjectIndexerCallback, ObjectSetCallback,
};
use crate::fn_native::{IteratorFn, ObjectGetCallback, ObjectIndexerCallback, ObjectSetCallback};
use crate::fn_register::RegisterFn;
use crate::optimize::{optimize_into_ast, OptimizationLevel};
use crate::parser::{parse, parse_global_expr, AST};
@ -123,8 +121,8 @@ impl Engine {
/// Register an iterator adapter for a type with the `Engine`.
/// This is an advanced feature.
pub fn register_iterator<T: Variant + Clone, F: IteratorCallback>(&mut self, f: F) {
self.global_module.set_iter(TypeId::of::<T>(), Box::new(f));
pub fn register_iterator<T: Variant + Clone>(&mut self, f: IteratorFn) {
self.global_module.set_iter(TypeId::of::<T>(), f);
}
/// Register a getter function for a member of a registered type with the `Engine`.

View File

@ -11,10 +11,7 @@ pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>
#[cfg(not(feature = "sync"))]
pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
#[cfg(feature = "sync")]
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
#[cfg(not(feature = "sync"))]
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
pub type IteratorFn = fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
#[cfg(feature = "sync")]
pub type PrintCallback = dyn Fn(&str) + Send + Sync + 'static;
@ -57,32 +54,11 @@ pub trait ObjectIndexerCallback<T, X, U>: Fn(&mut T, X) -> U + 'static {}
#[cfg(not(feature = "sync"))]
impl<F: Fn(&mut T, X) -> U + 'static, T, X, U> ObjectIndexerCallback<T, X, U> for F {}
#[cfg(feature = "sync")]
pub trait IteratorCallback:
Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync + 'static
{
}
#[cfg(feature = "sync")]
impl<F: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync + 'static> IteratorCallback
for F
{
}
#[cfg(not(feature = "sync"))]
pub trait IteratorCallback: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static {}
#[cfg(not(feature = "sync"))]
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"))]
@ -97,7 +73,7 @@ pub enum CallableFunction {
/// and the rest passed by value.
Method(SharedNativeFunction),
/// An iterator function.
Iterator(SharedIteratorFn),
Iterator(IteratorFn),
/// A script-defined function.
Script(SharedFnDef),
}
@ -158,9 +134,9 @@ impl CallableFunction {
/// # Panics
///
/// Panics if the `CallableFunction` is not `Iterator`.
pub fn get_iter_fn(&self) -> &IteratorFn {
pub fn get_iter_fn(&self) -> IteratorFn {
match self {
Self::Iterator(f) => f.as_ref(),
Self::Iterator(f) => *f,
Self::Pure(_) | Self::Method(_) | Self::Script(_) => panic!(),
}
}

View File

@ -3,7 +3,7 @@
use crate::any::{Dynamic, Variant};
use crate::calc_fn_hash;
use crate::engine::{Engine, FunctionsLib};
use crate::fn_native::{CallableFunction as CF, FnCallArgs, IteratorFn, SharedIteratorFn};
use crate::fn_native::{CallableFunction as CF, FnCallArgs, IteratorFn};
use crate::parser::{
FnAccess,
FnAccess::{Private, Public},
@ -53,7 +53,7 @@ pub struct Module {
fn_lib: FunctionsLib,
/// Iterator functions, keyed by the type producing the iterator.
type_iterators: HashMap<TypeId, SharedIteratorFn>,
type_iterators: HashMap<TypeId, IteratorFn>,
/// Flattened collection of all external Rust functions, native or scripted,
/// including those in sub-modules.
@ -659,13 +659,13 @@ impl Module {
}
/// Set a type iterator into the module.
pub fn set_iter(&mut self, typ: TypeId, func: Box<IteratorFn>) {
self.type_iterators.insert(typ, func.into());
pub fn set_iter(&mut self, typ: TypeId, func: IteratorFn) {
self.type_iterators.insert(typ, func);
}
/// Get the specified type iterator.
pub fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
self.type_iterators.get(&id).map(|v| v.as_ref())
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.type_iterators.get(&id).cloned()
}
}

View File

@ -120,8 +120,6 @@ def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
// Register array iterator
lib.set_iter(
TypeId::of::<Array>(),
Box::new(|arr| Box::new(
arr.cast::<Array>().into_iter()) as Box<dyn Iterator<Item = Dynamic>>
),
|arr| Box::new(arr.cast::<Array>().into_iter()) as Box<dyn Iterator<Item = Dynamic>>,
);
});

View File

@ -14,13 +14,10 @@ fn reg_range<T: Variant + Clone>(lib: &mut Module)
where
Range<T>: Iterator<Item = T>,
{
lib.set_iter(
TypeId::of::<Range<T>>(),
Box::new(|source| {
Box::new(source.cast::<Range<T>>().map(|x| x.into_dynamic()))
as Box<dyn Iterator<Item = Dynamic>>
}),
);
lib.set_iter(TypeId::of::<Range<T>>(), |source| {
Box::new(source.cast::<Range<T>>().map(|x| x.into_dynamic()))
as Box<dyn Iterator<Item = Dynamic>>
});
}
fn get_range<T: Variant + Clone>(from: T, to: T) -> FuncReturn<Range<T>> {
@ -58,13 +55,10 @@ where
T: Variant + Clone + PartialOrd,
StepRange<T>: Iterator<Item = T>,
{
lib.set_iter(
TypeId::of::<StepRange<T>>(),
Box::new(|source| {
Box::new(source.cast::<StepRange<T>>().map(|x| x.into_dynamic()))
as Box<dyn Iterator<Item = Dynamic>>
}),
);
lib.set_iter(TypeId::of::<StepRange<T>>(), |source| {
Box::new(source.cast::<StepRange<T>>().map(|x| x.into_dynamic()))
as Box<dyn Iterator<Item = Dynamic>>
});
}
fn get_step_range<T>(from: T, to: T, step: T) -> FuncReturn<StepRange<T>>

View File

@ -83,7 +83,7 @@ impl PackagesCollection {
self.packages.iter().any(|p| p.contains_iter(id))
}
/// Get the specified TypeId iterator.
pub fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.packages
.iter()
.map(|p| p.get_iter(id))