Refactor iterators API.
This commit is contained in:
parent
e0c39edff4
commit
707ece7e80
@ -12,6 +12,7 @@ Breaking changes
|
|||||||
* `AST::iter_functions` now returns an iterator instead of taking a closure.
|
* `AST::iter_functions` now returns an iterator instead of taking a closure.
|
||||||
* `Module::get_script_function_by_signature` renamed to `Module::get_script_fn` and returns `&<Shared<ScriptFnDef>>`.
|
* `Module::get_script_function_by_signature` renamed to `Module::get_script_fn` and returns `&<Shared<ScriptFnDef>>`.
|
||||||
* `Module::num_fn`, `Module::num_var` and `Module::num_iter` are removed and merged into `Module::count`.
|
* `Module::num_fn`, `Module::num_var` and `Module::num_iter` are removed and merged into `Module::count`.
|
||||||
|
* `Module::set_iter` is renamed to `Module::set_iter_raw`.
|
||||||
* The `merge_namespaces` parameter to `Module::eval_ast_as_new` is removed and now defaults to `true`.
|
* The `merge_namespaces` parameter to `Module::eval_ast_as_new` is removed and now defaults to `true`.
|
||||||
* `GlobalFileModuleResolver` is removed because its performance gain over the `FileModuleResolver` is no longer very significant.
|
* `GlobalFileModuleResolver` is removed because its performance gain over the `FileModuleResolver` is no longer very significant.
|
||||||
* The following `EvalAltResult` variants are removed and merged into `EvalAltResult::ErrorMismatchDataType`: `ErrorCharMismatch`, `ErrorNumericIndexExpr`, `ErrorStringIndexExpr`, `ErrorImportExpr`, `ErrorLogicGuard`, `ErrorBooleanArgMismatch`
|
* The following `EvalAltResult` variants are removed and merged into `EvalAltResult::ErrorMismatchDataType`: `ErrorCharMismatch`, `ErrorNumericIndexExpr`, `ErrorStringIndexExpr`, `ErrorImportExpr`, `ErrorLogicGuard`, `ErrorBooleanArgMismatch`
|
||||||
@ -32,6 +33,7 @@ New features
|
|||||||
* `Dynamic::from(&str)` now constructs a `Dynamic` with a copy of the string as value.
|
* `Dynamic::from(&str)` now constructs a `Dynamic` with a copy of the string as value.
|
||||||
* `AST::combine` and `AST::combine_filtered` allows combining two `AST`'s without creating a new one.
|
* `AST::combine` and `AST::combine_filtered` allows combining two `AST`'s without creating a new one.
|
||||||
* `map`, `filter`, `reduce`, `reduce_rev`, `some`, `all`, `extract`, `splice`, `chop` and `sort` functions for arrays.
|
* `map`, `filter`, `reduce`, `reduce_rev`, `some`, `all`, `extract`, `splice`, `chop` and `sort` functions for arrays.
|
||||||
|
* New `Module::set_iter`, `Module::set_iterable` and `Module::set_iterator` to define type iterators more easily. `Engine::register_iterator` is changed to use the simpler version.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
10
src/api.rs
10
src/api.rs
@ -3,7 +3,7 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::{Engine, EvalContext, Imports, State};
|
use crate::engine::{Engine, EvalContext, Imports, State};
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::fn_native::{IteratorFn, SendSync};
|
use crate::fn_native::SendSync;
|
||||||
use crate::module::{FuncReturn, Module};
|
use crate::module::{FuncReturn, Module};
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::parser::AST;
|
use crate::parser::AST;
|
||||||
@ -174,11 +174,13 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register an iterator adapter for a type with the `Engine`.
|
/// Register an iterator adapter for an iterable type with the `Engine`.
|
||||||
/// This is an advanced feature.
|
/// This is an advanced feature.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_iterator<T: Variant + Clone>(&mut self, f: IteratorFn) -> &mut Self {
|
pub fn register_iterator<T: Variant + Clone + IntoIterator<Item = U>, U: Variant + Clone>(
|
||||||
self.global_module.set_iter(TypeId::of::<T>(), f);
|
&mut self,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.global_module.set_iterable::<T, U>();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1782,21 +1782,22 @@ impl Engine {
|
|||||||
// For loop
|
// For loop
|
||||||
Stmt::For(x) => {
|
Stmt::For(x) => {
|
||||||
let (name, expr, stmt, _) = x.as_ref();
|
let (name, expr, stmt, _) = x.as_ref();
|
||||||
let iter_type = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
|
let iter_obj = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
|
||||||
let tid = iter_type.type_id();
|
let iter_type = iter_obj.type_id();
|
||||||
|
|
||||||
if let Some(func) = self
|
let func = self
|
||||||
.global_module
|
.global_module
|
||||||
.get_iter(tid)
|
.get_iter(iter_type)
|
||||||
.or_else(|| self.packages.get_iter(tid))
|
.or_else(|| self.packages.get_iter(iter_type));
|
||||||
{
|
|
||||||
|
if let Some(func) = func {
|
||||||
// Add the loop variable
|
// Add the loop variable
|
||||||
let var_name = unsafe_cast_var_name_to_lifetime(name, &state);
|
let var_name = unsafe_cast_var_name_to_lifetime(name, &state);
|
||||||
scope.push(var_name, ());
|
scope.push(var_name, ());
|
||||||
let index = scope.len() - 1;
|
let index = scope.len() - 1;
|
||||||
state.scope_level += 1;
|
state.scope_level += 1;
|
||||||
|
|
||||||
for iter_value in func(iter_type) {
|
for iter_value in func(iter_obj) {
|
||||||
let (loop_var, _) = scope.get_mut(index);
|
let (loop_var, _) = scope.get_mut(index);
|
||||||
|
|
||||||
let value = iter_value.flatten();
|
let value = iter_value.flatten();
|
||||||
|
@ -85,7 +85,7 @@ mod utils;
|
|||||||
pub use any::Dynamic;
|
pub use any::Dynamic;
|
||||||
pub use engine::{Engine, EvalContext};
|
pub use engine::{Engine, EvalContext};
|
||||||
pub use error::{ParseError, ParseErrorType};
|
pub use error::{ParseError, ParseErrorType};
|
||||||
pub use fn_native::{FnPtr, IteratorFn};
|
pub use fn_native::FnPtr;
|
||||||
pub use fn_register::{RegisterFn, RegisterResultFn};
|
pub use fn_register::{RegisterFn, RegisterResultFn};
|
||||||
pub use module::Module;
|
pub use module::Module;
|
||||||
pub use parser::{ImmutableString, AST, INT};
|
pub use parser::{ImmutableString, AST, INT};
|
||||||
|
@ -1468,6 +1468,24 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a type iterator into the module.
|
||||||
|
pub fn set_iterable<T: Variant + Clone + IntoIterator<Item = U>, U: Variant + Clone>(
|
||||||
|
&mut self,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.set_iter(TypeId::of::<T>(), |obj: Dynamic| {
|
||||||
|
Box::new(obj.cast::<T>().into_iter().map(Dynamic::from))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set an iterator type into the module as a type iterator.
|
||||||
|
pub fn set_iterator<T: Variant + Clone + Iterator<Item = U>, U: Variant + Clone>(
|
||||||
|
&mut self,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.set_iter(TypeId::of::<T>(), |obj: Dynamic| {
|
||||||
|
Box::new(obj.cast::<T>().map(Dynamic::from))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the specified type iterator.
|
/// Get the specified type iterator.
|
||||||
pub(crate) fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
pub(crate) fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
||||||
self.type_iterators.get(&id).cloned()
|
self.type_iterators.get(&id).cloned()
|
||||||
|
@ -86,10 +86,7 @@ def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
|||||||
combine_with_exported_module!(lib, "array", array_functions);
|
combine_with_exported_module!(lib, "array", array_functions);
|
||||||
|
|
||||||
// Register array iterator
|
// Register array iterator
|
||||||
lib.set_iter(
|
lib.set_iterable::<Array, Dynamic>();
|
||||||
TypeId::of::<Array>(),
|
|
||||||
|arr| Box::new(arr.cast::<Array>().into_iter()) as Box<dyn Iterator<Item = Dynamic>>,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
|
@ -1,23 +1,16 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::Variant;
|
||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
use crate::module::{FuncReturn, Module};
|
use crate::module::{FuncReturn, Module};
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::ops::{Add, Range};
|
||||||
any::TypeId,
|
|
||||||
boxed::Box,
|
|
||||||
ops::{Add, Range},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Register range function
|
// Register range function
|
||||||
fn reg_range<T: Variant + Clone>(lib: &mut Module)
|
fn reg_range<T: Variant + Clone>(lib: &mut Module)
|
||||||
where
|
where
|
||||||
Range<T>: Iterator<Item = T>,
|
Range<T>: Iterator<Item = T>,
|
||||||
{
|
{
|
||||||
lib.set_iter(TypeId::of::<Range<T>>(), |source| {
|
lib.set_iterator::<Range<T>, T>();
|
||||||
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>> {
|
fn get_range<T: Variant + Clone>(from: T, to: T) -> FuncReturn<Range<T>> {
|
||||||
@ -55,10 +48,7 @@ where
|
|||||||
T: Variant + Clone + PartialOrd,
|
T: Variant + Clone + PartialOrd,
|
||||||
StepRange<T>: Iterator<Item = T>,
|
StepRange<T>: Iterator<Item = T>,
|
||||||
{
|
{
|
||||||
lib.set_iter(TypeId::of::<StepRange<T>>(), |source| {
|
lib.set_iterator::<StepRange<T>, T>();
|
||||||
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>>
|
fn get_step_range<T>(from: T, to: T, step: T) -> FuncReturn<StepRange<T>>
|
||||||
|
@ -108,9 +108,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
|||||||
// Register string iterator
|
// Register string iterator
|
||||||
lib.set_iter(
|
lib.set_iter(
|
||||||
TypeId::of::<ImmutableString>(),
|
TypeId::of::<ImmutableString>(),
|
||||||
|arr| Box::new(
|
|s: Dynamic| Box::new(s.cast::<ImmutableString>().chars().collect::<Vec<_>>().into_iter().map(Into::into))
|
||||||
arr.cast::<ImmutableString>().chars().collect::<Vec<_>>().into_iter().map(Into::into)
|
|
||||||
) as Box<dyn Iterator<Item = Dynamic>>,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user