Use fold.
This commit is contained in:
parent
2fffe31b59
commit
c2c30f7711
11
src/ast.rs
11
src/ast.rs
@ -2200,12 +2200,11 @@ impl Expr {
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Self::Map(x, _) if self.is_constant() => {
|
||||
let mut map = x.1.clone();
|
||||
x.0.iter().for_each(|(k, v)| {
|
||||
*map.get_mut(k.name.as_str()).expect("contains all keys") =
|
||||
v.get_literal_value().expect("constant value")
|
||||
});
|
||||
Dynamic::from_map(map)
|
||||
Dynamic::from_map(x.0.iter().fold(x.1.clone(), |mut map, (k, v)| {
|
||||
let value_ref = map.get_mut(k.name.as_str()).expect("contains all keys");
|
||||
*value_ref = v.get_literal_value().expect("constant value");
|
||||
map
|
||||
}))
|
||||
}
|
||||
|
||||
_ => return None,
|
||||
|
100
src/engine.rs
100
src/engine.rs
@ -1893,20 +1893,22 @@ impl Engine {
|
||||
let crate::ast::FnCallExpr {
|
||||
args, constants, ..
|
||||
} = 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| {
|
||||
self.get_arg_value(scope, mods, state, lib, this_ptr, level, expr, constants)
|
||||
.map(|(value, pos)| {
|
||||
if arg_values.is_empty() {
|
||||
first_arg_pos = pos
|
||||
}
|
||||
arg_values.push(value.flatten());
|
||||
})
|
||||
})?;
|
||||
let (values, pos) = args.iter().try_fold(
|
||||
(StaticVec::with_capacity(args.len()), Position::NONE),
|
||||
|(mut values, mut pos), expr| -> Result<_, Box<EvalAltResult>> {
|
||||
let (value, arg_pos) = self.get_arg_value(
|
||||
scope, mods, state, lib, this_ptr, level, expr, constants,
|
||||
)?;
|
||||
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"))]
|
||||
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
|
||||
@ -1937,22 +1939,22 @@ impl Engine {
|
||||
let crate::ast::FnCallExpr {
|
||||
args, constants, ..
|
||||
} = 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| {
|
||||
self.get_arg_value(
|
||||
scope, mods, state, lib, this_ptr, level, expr, constants,
|
||||
)
|
||||
.map(|(value, pos)| {
|
||||
if arg_values.is_empty() {
|
||||
first_arg_pos = pos
|
||||
}
|
||||
arg_values.push(value.flatten());
|
||||
})
|
||||
})?;
|
||||
|
||||
(arg_values, first_arg_pos).into()
|
||||
args.iter()
|
||||
.try_fold(
|
||||
(StaticVec::with_capacity(args.len()), Position::NONE),
|
||||
|(mut values, mut pos), expr| -> Result<_, Box<EvalAltResult>> {
|
||||
let (value, arg_pos) = self.get_arg_value(
|
||||
scope, mods, state, lib, this_ptr, level, expr, constants,
|
||||
)?;
|
||||
if values.is_empty() {
|
||||
pos = arg_pos
|
||||
}
|
||||
values.push(value.flatten());
|
||||
Ok((values, pos))
|
||||
},
|
||||
)?
|
||||
.into()
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
|
||||
@ -2255,25 +2257,35 @@ impl Engine {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Expr::Array(x, _) => {
|
||||
let mut arr = Array::with_capacity(x.len());
|
||||
x.iter().try_for_each(|item| {
|
||||
self.eval_expr(scope, mods, state, lib, this_ptr, item, level)
|
||||
.map(|value| arr.push(value.flatten()))
|
||||
})?;
|
||||
Ok(arr.into())
|
||||
}
|
||||
Expr::Array(x, _) => Ok(x
|
||||
.iter()
|
||||
.try_fold(
|
||||
Array::with_capacity(x.len()),
|
||||
|mut arr, item| -> Result<_, Box<EvalAltResult>> {
|
||||
arr.push(
|
||||
self.eval_expr(scope, mods, state, lib, this_ptr, item, level)?
|
||||
.flatten(),
|
||||
);
|
||||
Ok(arr)
|
||||
},
|
||||
)?
|
||||
.into()),
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Expr::Map(x, _) => {
|
||||
let mut map = x.1.clone();
|
||||
x.0.iter().try_for_each(|(Ident { name: key, .. }, expr)| {
|
||||
let value_ref = map.get_mut(key.as_str()).expect("contains all keys");
|
||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)
|
||||
.map(|value| *value_ref = value.flatten())
|
||||
})?;
|
||||
Ok(map.into())
|
||||
}
|
||||
Expr::Map(x, _) => Ok(x
|
||||
.0
|
||||
.iter()
|
||||
.try_fold(
|
||||
x.1.clone(),
|
||||
|mut map, (Ident { name: key, .. }, expr)| -> Result<_, Box<EvalAltResult>> {
|
||||
let value_ref = map.get_mut(key.as_str()).expect("contains all keys");
|
||||
*value_ref = self
|
||||
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||
.flatten();
|
||||
Ok(map)
|
||||
},
|
||||
)?
|
||||
.into()),
|
||||
|
||||
// Namespace-qualified function call
|
||||
Expr::FnCall(x, pos) if x.is_qualified() => {
|
||||
|
@ -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.
|
||||
a_expr.iter().skip(1).try_for_each(|expr| {
|
||||
self.get_arg_value(scope, mods, state, lib, this_ptr, level, expr, constants)
|
||||
.map(|(value, _)| fn_curry.push(value))
|
||||
})?;
|
||||
let fn_curry = a_expr.iter().skip(1).try_fold(
|
||||
fn_curry,
|
||||
|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());
|
||||
}
|
||||
|
@ -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 {
|
||||
let s = &mut get_hasher();
|
||||
let mut len = 0;
|
||||
params.for_each(|t| {
|
||||
len += 1;
|
||||
t.hash(s);
|
||||
});
|
||||
params.inspect(|_| len += 1).for_each(|t| t.hash(s));
|
||||
len.hash(s);
|
||||
s.finish()
|
||||
}
|
||||
|
@ -1409,10 +1409,11 @@ impl Module {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
pub fn eval_ast_as_new(
|
||||
mut scope: crate::Scope,
|
||||
scope: crate::Scope,
|
||||
ast: &crate::AST,
|
||||
engine: &crate::Engine,
|
||||
) -> Result<Self, Box<EvalAltResult>> {
|
||||
let mut scope = scope;
|
||||
let mut mods = crate::engine::Imports::new();
|
||||
let orig_mods_len = mods.len();
|
||||
|
||||
@ -1420,21 +1421,28 @@ impl Module {
|
||||
engine.eval_ast_with_scope_raw(&mut scope, &mut mods, &ast, 0)?;
|
||||
|
||||
// Create new module
|
||||
let mut module = Module::new();
|
||||
|
||||
scope.into_iter().for_each(|(_, value, mut aliases)| {
|
||||
// Variables with an alias left in the scope become module variables
|
||||
match aliases.len() {
|
||||
0 => (),
|
||||
1 => {
|
||||
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 mut module =
|
||||
scope
|
||||
.into_iter()
|
||||
.fold(Module::new(), |mut module, (_, value, mut aliases)| {
|
||||
// Variables with an alias left in the scope become module variables
|
||||
match aliases.len() {
|
||||
0 => (),
|
||||
1 => {
|
||||
let alias = aliases.pop().expect("not empty");
|
||||
module.set_var(alias, value);
|
||||
}
|
||||
_ => {
|
||||
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
|
||||
let mut func_mods = crate::engine::Imports::new();
|
||||
|
@ -90,11 +90,13 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> crate::Array {
|
||||
.map(|&s| s.into())
|
||||
.collect();
|
||||
|
||||
let mut list = Array::new();
|
||||
|
||||
ctx.iter_namespaces()
|
||||
.flat_map(|m| m.iter_script_fn())
|
||||
.for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into()));
|
||||
let mut list = ctx.iter_namespaces().flat_map(Module::iter_script_fn).fold(
|
||||
Array::new(),
|
||||
|mut list, (_, _, _, _, f)| {
|
||||
list.push(make_metadata(&dict, None, f).into());
|
||||
list
|
||||
},
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
{
|
||||
|
@ -518,22 +518,18 @@ impl<'a> Scope<'a> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn clone_visible(&self) -> Self {
|
||||
let mut entries = Self::new();
|
||||
|
||||
self.names
|
||||
.iter()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.for_each(|(index, (name, alias))| {
|
||||
self.names.iter().rev().enumerate().fold(
|
||||
Self::new(),
|
||||
|mut entries, (index, (name, alias))| {
|
||||
if !entries.names.iter().any(|(key, _)| key == name) {
|
||||
entries.names.push((name.clone(), alias.clone()));
|
||||
entries
|
||||
.values
|
||||
.push(self.values[self.len() - 1 - index].clone());
|
||||
}
|
||||
});
|
||||
|
||||
entries
|
||||
entries
|
||||
},
|
||||
)
|
||||
}
|
||||
/// Get an iterator to entries in the [`Scope`].
|
||||
#[inline]
|
||||
|
Loading…
Reference in New Issue
Block a user