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"))]
|
#[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,
|
||||||
|
100
src/engine.rs
100
src/engine.rs
@ -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() => {
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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"))]
|
||||||
{
|
{
|
||||||
|
@ -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]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user