Use fold.

This commit is contained in:
Stephen Chung 2021-11-16 13:15:43 +08:00
parent 2fffe31b59
commit c2c30f7711
7 changed files with 110 additions and 90 deletions

View File

@ -2200,12 +2200,11 @@ impl Expr {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Self::Map(x, _) if self.is_constant() => { Self::Map(x, _) if self.is_constant() => {
let mut map = x.1.clone(); Dynamic::from_map(x.0.iter().fold(x.1.clone(), |mut map, (k, v)| {
x.0.iter().for_each(|(k, v)| { let value_ref = map.get_mut(k.name.as_str()).expect("contains all keys");
*map.get_mut(k.name.as_str()).expect("contains all keys") = *value_ref = v.get_literal_value().expect("constant value");
v.get_literal_value().expect("constant value") map
}); }))
Dynamic::from_map(map)
} }
_ => return None, _ => return None,

View File

@ -1893,20 +1893,22 @@ impl Engine {
let crate::ast::FnCallExpr { let crate::ast::FnCallExpr {
args, constants, .. args, constants, ..
} = x.as_ref(); } = x.as_ref();
let mut arg_values = StaticVec::with_capacity(args.len());
let mut first_arg_pos = Position::NONE;
args.iter().try_for_each(|expr| { let (values, pos) = args.iter().try_fold(
self.get_arg_value(scope, mods, state, lib, this_ptr, level, expr, constants) (StaticVec::with_capacity(args.len()), Position::NONE),
.map(|(value, pos)| { |(mut values, mut pos), expr| -> Result<_, Box<EvalAltResult>> {
if arg_values.is_empty() { let (value, arg_pos) = self.get_arg_value(
first_arg_pos = pos scope, mods, state, lib, this_ptr, level, expr, constants,
} )?;
arg_values.push(value.flatten()); if values.is_empty() {
}) pos = arg_pos;
})?; }
values.push(value.flatten());
Ok((values, pos))
},
)?;
idx_values.push((arg_values, first_arg_pos).into()); idx_values.push((values, pos).into());
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => { Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
@ -1937,22 +1939,22 @@ impl Engine {
let crate::ast::FnCallExpr { let crate::ast::FnCallExpr {
args, constants, .. args, constants, ..
} = x.as_ref(); } = x.as_ref();
let mut arg_values = StaticVec::with_capacity(args.len());
let mut first_arg_pos = Position::NONE;
args.iter().try_for_each(|expr| { args.iter()
self.get_arg_value( .try_fold(
scope, mods, state, lib, this_ptr, level, expr, constants, (StaticVec::with_capacity(args.len()), Position::NONE),
) |(mut values, mut pos), expr| -> Result<_, Box<EvalAltResult>> {
.map(|(value, pos)| { let (value, arg_pos) = self.get_arg_value(
if arg_values.is_empty() { scope, mods, state, lib, this_ptr, level, expr, constants,
first_arg_pos = pos )?;
} if values.is_empty() {
arg_values.push(value.flatten()); pos = arg_pos
}) }
})?; values.push(value.flatten());
Ok((values, pos))
(arg_values, first_arg_pos).into() },
)?
.into()
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => { Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
@ -2255,25 +2257,35 @@ impl Engine {
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Array(x, _) => { Expr::Array(x, _) => Ok(x
let mut arr = Array::with_capacity(x.len()); .iter()
x.iter().try_for_each(|item| { .try_fold(
self.eval_expr(scope, mods, state, lib, this_ptr, item, level) Array::with_capacity(x.len()),
.map(|value| arr.push(value.flatten())) |mut arr, item| -> Result<_, Box<EvalAltResult>> {
})?; arr.push(
Ok(arr.into()) self.eval_expr(scope, mods, state, lib, this_ptr, item, level)?
} .flatten(),
);
Ok(arr)
},
)?
.into()),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::Map(x, _) => { Expr::Map(x, _) => Ok(x
let mut map = x.1.clone(); .0
x.0.iter().try_for_each(|(Ident { name: key, .. }, expr)| { .iter()
let value_ref = map.get_mut(key.as_str()).expect("contains all keys"); .try_fold(
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level) x.1.clone(),
.map(|value| *value_ref = value.flatten()) |mut map, (Ident { name: key, .. }, expr)| -> Result<_, Box<EvalAltResult>> {
})?; let value_ref = map.get_mut(key.as_str()).expect("contains all keys");
Ok(map.into()) *value_ref = self
} .eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.flatten();
Ok(map)
},
)?
.into()),
// Namespace-qualified function call // Namespace-qualified function call
Expr::FnCall(x, pos) if x.is_qualified() => { Expr::FnCall(x, pos) if x.is_qualified() => {

View File

@ -1153,13 +1153,19 @@ impl Engine {
)); ));
} }
let (name, mut fn_curry) = arg.cast::<FnPtr>().take_data(); let (name, fn_curry) = arg.cast::<FnPtr>().take_data();
// Append the new curried arguments to the existing list. // Append the new curried arguments to the existing list.
a_expr.iter().skip(1).try_for_each(|expr| { let fn_curry = a_expr.iter().skip(1).try_fold(
self.get_arg_value(scope, mods, state, lib, this_ptr, level, expr, constants) fn_curry,
.map(|(value, _)| fn_curry.push(value)) |mut curried, expr| -> Result<_, Box<EvalAltResult>> {
})?; let (value, _) = self.get_arg_value(
scope, mods, state, lib, this_ptr, level, expr, constants,
)?;
curried.push(value);
Ok(curried)
},
)?;
return Ok(FnPtr::new_unchecked(name, fn_curry).into()); return Ok(FnPtr::new_unchecked(name, fn_curry).into());
} }

View File

@ -124,10 +124,7 @@ pub fn calc_fn_hash(fn_name: &str, num: usize) -> u64 {
pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 { pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
let s = &mut get_hasher(); let s = &mut get_hasher();
let mut len = 0; let mut len = 0;
params.for_each(|t| { params.inspect(|_| len += 1).for_each(|t| t.hash(s));
len += 1;
t.hash(s);
});
len.hash(s); len.hash(s);
s.finish() s.finish()
} }

View File

@ -1409,10 +1409,11 @@ impl Module {
/// ``` /// ```
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
pub fn eval_ast_as_new( pub fn eval_ast_as_new(
mut scope: crate::Scope, scope: crate::Scope,
ast: &crate::AST, ast: &crate::AST,
engine: &crate::Engine, engine: &crate::Engine,
) -> Result<Self, Box<EvalAltResult>> { ) -> Result<Self, Box<EvalAltResult>> {
let mut scope = scope;
let mut mods = crate::engine::Imports::new(); let mut mods = crate::engine::Imports::new();
let orig_mods_len = mods.len(); let orig_mods_len = mods.len();
@ -1420,21 +1421,28 @@ impl Module {
engine.eval_ast_with_scope_raw(&mut scope, &mut mods, &ast, 0)?; engine.eval_ast_with_scope_raw(&mut scope, &mut mods, &ast, 0)?;
// Create new module // Create new module
let mut module = Module::new(); let mut module =
scope
scope.into_iter().for_each(|(_, value, mut aliases)| { .into_iter()
// Variables with an alias left in the scope become module variables .fold(Module::new(), |mut module, (_, value, mut aliases)| {
match aliases.len() { // Variables with an alias left in the scope become module variables
0 => (), match aliases.len() {
1 => { 0 => (),
let alias = aliases.pop().expect("not empty"); 1 => {
module.set_var(alias, value); let alias = aliases.pop().expect("not empty");
} module.set_var(alias, value);
_ => aliases.into_iter().for_each(|alias| { }
module.set_var(alias, value.clone()); _ => {
}), let last_alias = aliases.pop().expect("not empty");
} aliases.into_iter().for_each(|alias| {
}); module.set_var(alias, value.clone());
});
// Avoid cloning the last value
module.set_var(last_alias, value);
}
}
module
});
// Extra modules left in the scope become sub-modules // Extra modules left in the scope become sub-modules
let mut func_mods = crate::engine::Imports::new(); let mut func_mods = crate::engine::Imports::new();

View File

@ -90,11 +90,13 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> crate::Array {
.map(|&s| s.into()) .map(|&s| s.into())
.collect(); .collect();
let mut list = Array::new(); let mut list = ctx.iter_namespaces().flat_map(Module::iter_script_fn).fold(
Array::new(),
ctx.iter_namespaces() |mut list, (_, _, _, _, f)| {
.flat_map(|m| m.iter_script_fn()) list.push(make_metadata(&dict, None, f).into());
.for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into())); list
},
);
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
{ {

View File

@ -518,22 +518,18 @@ impl<'a> Scope<'a> {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn clone_visible(&self) -> Self { pub fn clone_visible(&self) -> Self {
let mut entries = Self::new(); self.names.iter().rev().enumerate().fold(
Self::new(),
self.names |mut entries, (index, (name, alias))| {
.iter()
.rev()
.enumerate()
.for_each(|(index, (name, alias))| {
if !entries.names.iter().any(|(key, _)| key == name) { if !entries.names.iter().any(|(key, _)| key == name) {
entries.names.push((name.clone(), alias.clone())); entries.names.push((name.clone(), alias.clone()));
entries entries
.values .values
.push(self.values[self.len() - 1 - index].clone()); .push(self.values[self.len() - 1 - index].clone());
} }
}); entries
},
entries )
} }
/// Get an iterator to entries in the [`Scope`]. /// Get an iterator to entries in the [`Scope`].
#[inline] #[inline]