Set capacity of hash maps.
This commit is contained in:
parent
a63f14b59c
commit
bde8917ed4
28
src/ast.rs
28
src/ast.rs
@ -15,6 +15,12 @@ use crate::FLOAT;
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
use crate::engine::Imports;
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use crate::engine::TYPICAL_ARRAY_SIZE;
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
use crate::engine::TYPICAL_MAP_SIZE;
|
||||
|
||||
use crate::stdlib::{
|
||||
borrow::Cow,
|
||||
boxed::Box,
|
||||
@ -31,6 +37,9 @@ use crate::stdlib::{
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
use crate::stdlib::collections::HashSet;
|
||||
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
use crate::stdlib::cmp::max;
|
||||
|
||||
/// A type representing the access mode of a scripted function.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub enum FnAccess {
|
||||
@ -927,17 +936,20 @@ impl Expr {
|
||||
Self::Unit(_) => ().into(),
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Self::Array(x, _) if x.iter().all(Self::is_constant) => Dynamic(Union::Array(
|
||||
Box::new(x.iter().map(|v| v.get_constant_value().unwrap()).collect()),
|
||||
)),
|
||||
Self::Array(x, _) if self.is_constant() => {
|
||||
let mut arr = Vec::with_capacity(max(TYPICAL_ARRAY_SIZE, x.len()));
|
||||
arr.extend(x.iter().map(|v| v.get_constant_value().unwrap()));
|
||||
Dynamic(Union::Array(Box::new(arr)))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Self::Map(x, _) if x.iter().all(|(_, v)| v.is_constant()) => {
|
||||
Dynamic(Union::Map(Box::new(
|
||||
Self::Map(x, _) if self.is_constant() => {
|
||||
let mut map = HashMap::with_capacity(max(TYPICAL_MAP_SIZE, x.len()));
|
||||
map.extend(
|
||||
x.iter()
|
||||
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap()))
|
||||
.collect(),
|
||||
)))
|
||||
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
||||
);
|
||||
Dynamic(Union::Map(Box::new(map)))
|
||||
}
|
||||
|
||||
_ => return None,
|
||||
|
@ -58,12 +58,21 @@ use crate::stdlib::mem;
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
pub type Array = crate::stdlib::vec::Vec<Dynamic>;
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
pub const TYPICAL_ARRAY_SIZE: usize = 8; // Small arrays are typical
|
||||
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
use crate::stdlib::cmp::max;
|
||||
|
||||
/// Hash map of `Dynamic` values with `ImmutableString` keys.
|
||||
///
|
||||
/// Not available under the `no_object` feature.
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
pub type Map = HashMap<ImmutableString, Dynamic>;
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
||||
|
||||
/// _[INTERNALS]_ A stack of imported modules.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
@ -597,7 +606,7 @@ pub struct Engine {
|
||||
|
||||
/// A hashset containing symbols to disable.
|
||||
pub(crate) disabled_symbols: HashSet<String>,
|
||||
/// A hashset containing custom keywords and precedence to recognize.
|
||||
/// A hashmap containing custom keywords and precedence to recognize.
|
||||
pub(crate) custom_keywords: HashMap<String, Option<u8>>,
|
||||
/// Custom syntax.
|
||||
pub(crate) custom_syntax: HashMap<ImmutableString, CustomSyntax>,
|
||||
@ -711,10 +720,10 @@ impl Engine {
|
||||
#[cfg(any(feature = "no_std", target_arch = "wasm32",))]
|
||||
module_resolver: None,
|
||||
|
||||
type_names: Default::default(),
|
||||
disabled_symbols: Default::default(),
|
||||
custom_keywords: Default::default(),
|
||||
custom_syntax: Default::default(),
|
||||
type_names: HashMap::with_capacity(8),
|
||||
disabled_symbols: HashSet::with_capacity(4),
|
||||
custom_keywords: HashMap::with_capacity(4),
|
||||
custom_syntax: HashMap::with_capacity(4),
|
||||
|
||||
// variable resolver
|
||||
resolve_var: None,
|
||||
@ -768,10 +777,10 @@ impl Engine {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
module_resolver: None,
|
||||
|
||||
type_names: Default::default(),
|
||||
disabled_symbols: Default::default(),
|
||||
custom_keywords: Default::default(),
|
||||
custom_syntax: Default::default(),
|
||||
type_names: HashMap::with_capacity(8),
|
||||
disabled_symbols: HashSet::with_capacity(4),
|
||||
custom_keywords: HashMap::with_capacity(4),
|
||||
custom_syntax: HashMap::with_capacity(4),
|
||||
|
||||
resolve_var: None,
|
||||
|
||||
@ -1716,21 +1725,25 @@ impl Engine {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Expr::Array(x, _) => Ok(Dynamic(Union::Array(Box::new(
|
||||
x.iter()
|
||||
.map(|item| self.eval_expr(scope, mods, state, lib, this_ptr, item, level))
|
||||
.collect::<Result<_, _>>()?,
|
||||
)))),
|
||||
Expr::Array(x, _) => {
|
||||
let mut arr = Vec::with_capacity(max(TYPICAL_ARRAY_SIZE, x.len()));
|
||||
for item in x.as_ref() {
|
||||
arr.push(self.eval_expr(scope, mods, state, lib, this_ptr, item, level)?);
|
||||
}
|
||||
Ok(Dynamic(Union::Array(Box::new(arr))))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Expr::Map(x, _) => Ok(Dynamic(Union::Map(Box::new(
|
||||
x.iter()
|
||||
.map(|(key, expr)| {
|
||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)
|
||||
.map(|val| (key.name.clone(), val))
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>, _>>()?,
|
||||
)))),
|
||||
Expr::Map(x, _) => {
|
||||
let mut map = HashMap::with_capacity(max(TYPICAL_MAP_SIZE, x.len()));
|
||||
for (IdentX { name: key, .. }, expr) in x.as_ref() {
|
||||
map.insert(
|
||||
key.clone(),
|
||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?,
|
||||
);
|
||||
}
|
||||
Ok(Dynamic(Union::Map(Box::new(map))))
|
||||
}
|
||||
|
||||
// Normal function call
|
||||
Expr::FnCall(x, pos) if x.namespace.is_none() => {
|
||||
|
@ -23,8 +23,7 @@ impl Engine {
|
||||
/// In other words, loaded packages are searched in reverse order.
|
||||
#[inline(always)]
|
||||
pub fn load_package(&mut self, package: impl Into<PackageLibrary>) -> &mut Self {
|
||||
// Push the package to the top - packages are searched in reverse order
|
||||
self.packages.push(package.into());
|
||||
self.packages.add(package.into());
|
||||
self
|
||||
}
|
||||
/// Control whether and how the `Engine` will optimize an AST after compilation.
|
||||
|
@ -59,7 +59,7 @@ pub struct FuncInfo {
|
||||
/// and/or script-defined functions.
|
||||
///
|
||||
/// Not available under the `no_module` feature.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Module {
|
||||
/// Sub-modules.
|
||||
modules: HashMap<String, Shared<Module>>,
|
||||
@ -69,15 +69,29 @@ pub struct Module {
|
||||
all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>,
|
||||
/// External Rust functions.
|
||||
functions: HashMap<u64, FuncInfo, StraightHasherBuilder>,
|
||||
/// Iterator functions, keyed by the type producing the iterator.
|
||||
type_iterators: HashMap<TypeId, IteratorFn>,
|
||||
/// Flattened collection of all external Rust functions, native or scripted,
|
||||
/// including those in sub-modules.
|
||||
all_functions: HashMap<u64, CallableFunction, StraightHasherBuilder>,
|
||||
/// Iterator functions, keyed by the type producing the iterator.
|
||||
type_iterators: HashMap<TypeId, IteratorFn>,
|
||||
/// Is the module indexed?
|
||||
indexed: bool,
|
||||
}
|
||||
|
||||
impl Default for Module {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
modules: HashMap::with_capacity(4),
|
||||
variables: HashMap::with_capacity(4),
|
||||
all_variables: HashMap::with_capacity_and_hasher(32, StraightHasherBuilder),
|
||||
functions: HashMap::with_capacity_and_hasher(64, StraightHasherBuilder),
|
||||
all_functions: HashMap::with_capacity_and_hasher(256, StraightHasherBuilder),
|
||||
type_iterators: HashMap::with_capacity(4),
|
||||
indexed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Module {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
@ -1462,9 +1476,9 @@ impl Module {
|
||||
}
|
||||
|
||||
if !self.indexed {
|
||||
let mut qualifiers: Vec<_> = Default::default();
|
||||
let mut variables: Vec<_> = Default::default();
|
||||
let mut functions: Vec<_> = Default::default();
|
||||
let mut qualifiers = Vec::with_capacity(4);
|
||||
let mut variables = Vec::with_capacity(8);
|
||||
let mut functions = Vec::with_capacity(16);
|
||||
|
||||
qualifiers.push("root");
|
||||
|
||||
|
@ -17,12 +17,6 @@ use crate::{calc_native_fn_hash, StaticVec};
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
use crate::ast::ReturnType;
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use crate::Array;
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
use crate::Map;
|
||||
|
||||
use crate::stdlib::{
|
||||
boxed::Box,
|
||||
hash::{Hash, Hasher},
|
||||
@ -566,26 +560,22 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
||||
},
|
||||
// [ constant .. ]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Expr::Array(a, pos) if a.iter().all(Expr::is_constant) => {
|
||||
Expr::Array(_, _) if expr.is_constant() => {
|
||||
state.set_dirty();
|
||||
let mut arr: Array = Default::default();
|
||||
arr.extend(mem::take(a).into_iter().map(|expr| expr.get_constant_value().unwrap()));
|
||||
*expr = Expr::DynamicConstant(Box::new(arr.into()), *pos);
|
||||
*expr = Expr::DynamicConstant(Box::new(expr.get_constant_value().unwrap()), expr.position());
|
||||
}
|
||||
// [ items .. ]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Expr::Array(a, _) => a.iter_mut().for_each(|expr| optimize_expr(expr, state)),
|
||||
Expr::Array(x, _) => x.iter_mut().for_each(|expr| optimize_expr(expr, state)),
|
||||
// #{ key:constant, .. }
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Expr::Map(m, pos) if m.iter().all(|(_, expr)| expr.is_constant()) => {
|
||||
Expr::Map(_, _) if expr.is_constant()=> {
|
||||
state.set_dirty();
|
||||
let mut map: Map = Default::default();
|
||||
map.extend(mem::take(m).into_iter().map(|(key, expr)| (key.name, expr.get_constant_value().unwrap())));
|
||||
*expr = Expr::DynamicConstant(Box::new(map.into()), *pos);
|
||||
*expr = Expr::DynamicConstant(Box::new(expr.get_constant_value().unwrap()), expr.position());
|
||||
}
|
||||
// #{ key:value, .. }
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Expr::Map(m, _) => m.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),
|
||||
Expr::Map(x, _) => x.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),
|
||||
// lhs in rhs
|
||||
Expr::In(x, _) => match (&mut x.lhs, &mut x.rhs) {
|
||||
// "xxx" in "xxxxx"
|
||||
|
@ -56,7 +56,9 @@ pub(crate) struct PackagesCollection(StaticVec<PackageLibrary>);
|
||||
|
||||
impl PackagesCollection {
|
||||
/// Add a `PackageLibrary` into the `PackagesCollection`.
|
||||
pub fn push(&mut self, package: PackageLibrary) {
|
||||
///
|
||||
/// Packages are searched in reverse order.
|
||||
pub fn add(&mut self, package: PackageLibrary) {
|
||||
// Later packages override previous ones.
|
||||
self.0.insert(0, package);
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ struct ParseState<'e> {
|
||||
allow_capture: bool,
|
||||
/// Encapsulates a local stack with imported module names.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
modules: Vec<ImmutableString>,
|
||||
modules: StaticVec<ImmutableString>,
|
||||
/// Maximum levels of expression nesting.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
max_expr_depth: usize,
|
||||
@ -99,11 +99,11 @@ impl<'e> ParseState<'e> {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
max_function_expr_depth,
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
externals: Default::default(),
|
||||
externals: HashMap::with_capacity(8),
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
allow_capture: true,
|
||||
strings: Default::default(),
|
||||
stack: Default::default(),
|
||||
strings: HashMap::with_capacity(64),
|
||||
stack: Vec::with_capacity(16),
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
modules: Default::default(),
|
||||
}
|
||||
@ -818,7 +818,7 @@ fn parse_switch(
|
||||
}
|
||||
}
|
||||
|
||||
let mut table: HashMap<u64, Stmt, StraightHasherBuilder> = Default::default();
|
||||
let mut table = HashMap::with_capacity_and_hasher(16, StraightHasherBuilder);
|
||||
let mut def_stmt = None;
|
||||
|
||||
loop {
|
||||
@ -1137,17 +1137,15 @@ fn parse_unary(
|
||||
|
||||
match token {
|
||||
// If statement is allowed to act as expressions
|
||||
Token::If if settings.allow_if_expr => {
|
||||
let mut block: StaticVec<_> = Default::default();
|
||||
block.push(parse_if(input, state, lib, settings.level_up())?);
|
||||
Ok(Expr::Stmt(Box::new(block), settings.pos))
|
||||
}
|
||||
Token::If if settings.allow_if_expr => Ok(Expr::Stmt(
|
||||
Box::new(vec![parse_if(input, state, lib, settings.level_up())?].into()),
|
||||
settings.pos,
|
||||
)),
|
||||
// Switch statement is allowed to act as expressions
|
||||
Token::Switch if settings.allow_switch_expr => {
|
||||
let mut block: StaticVec<_> = Default::default();
|
||||
block.push(parse_switch(input, state, lib, settings.level_up())?);
|
||||
Ok(Expr::Stmt(Box::new(block), settings.pos))
|
||||
}
|
||||
Token::Switch if settings.allow_switch_expr => Ok(Expr::Stmt(
|
||||
Box::new(vec![parse_switch(input, state, lib, settings.level_up())?].into()),
|
||||
settings.pos,
|
||||
)),
|
||||
// -expr
|
||||
Token::UnaryMinus => {
|
||||
let pos = eat_token(input, Token::UnaryMinus);
|
||||
@ -2635,7 +2633,7 @@ fn parse_fn(
|
||||
let params: StaticVec<_> = params.into_iter().map(|(p, _)| p).collect();
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let externals: HashSet<_> = state
|
||||
let externals = state
|
||||
.externals
|
||||
.iter()
|
||||
.map(|(name, _)| name)
|
||||
@ -2802,7 +2800,7 @@ fn parse_anon_fn(
|
||||
access: FnAccess::Public,
|
||||
params,
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
externals: Default::default(),
|
||||
externals: HashSet::with_capacity(4),
|
||||
body,
|
||||
lib: None,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
|
Loading…
Reference in New Issue
Block a user