Optimize imports layout.
This commit is contained in:
parent
81ca86a8d2
commit
61b0c7b2b3
@ -53,7 +53,7 @@ pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
||||
// the module name will live beyond the AST of the eval script text.
|
||||
// The best we can do is a shared reference.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Imports(StaticVec<(ImmutableString, Shared<Module>)>);
|
||||
pub struct Imports(StaticVec<ImmutableString>, StaticVec<Shared<Module>>);
|
||||
|
||||
impl Imports {
|
||||
/// Get the length of this stack of imported [modules][Module].
|
||||
@ -69,7 +69,7 @@ impl Imports {
|
||||
/// Get the imported [modules][Module] at a particular index.
|
||||
#[inline(always)]
|
||||
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
||||
self.0.get(index).map(|(_, m)| m).cloned()
|
||||
self.1.get(index).cloned()
|
||||
}
|
||||
/// Get the index of an imported [modules][Module] by name.
|
||||
#[inline(always)]
|
||||
@ -78,18 +78,19 @@ impl Imports {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.rev()
|
||||
.find(|(_, (key, _))| key.as_str() == name)
|
||||
.map(|(index, _)| index)
|
||||
.find_map(|(i, key)| if key.as_str() == name { Some(i) } else { None })
|
||||
}
|
||||
/// Push an imported [modules][Module] onto the stack.
|
||||
#[inline(always)]
|
||||
pub fn push(&mut self, name: impl Into<ImmutableString>, module: impl Into<Shared<Module>>) {
|
||||
self.0.push((name.into(), module.into()));
|
||||
self.0.push(name.into());
|
||||
self.1.push(module.into());
|
||||
}
|
||||
/// Truncate the stack of imported [modules][Module] to a particular length.
|
||||
#[inline(always)]
|
||||
pub fn truncate(&mut self, size: usize) {
|
||||
self.0.truncate(size);
|
||||
self.1.truncate(size);
|
||||
}
|
||||
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
||||
#[allow(dead_code)]
|
||||
@ -97,6 +98,7 @@ impl Imports {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||
self.0
|
||||
.iter()
|
||||
.zip(self.1.iter())
|
||||
.rev()
|
||||
.map(|(name, module)| (name.as_str(), module.as_ref()))
|
||||
}
|
||||
@ -104,52 +106,44 @@ impl Imports {
|
||||
#[allow(dead_code)]
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_raw(&self) -> impl Iterator<Item = (&ImmutableString, &Shared<Module>)> {
|
||||
self.0.iter().rev().map(|(n, m)| (n, m))
|
||||
self.0.iter().rev().zip(self.1.iter().rev())
|
||||
}
|
||||
/// Get an iterator to this stack of imported [modules][Module] in forward order.
|
||||
#[allow(dead_code)]
|
||||
#[inline(always)]
|
||||
pub(crate) fn scan_raw(&self) -> impl Iterator<Item = (&ImmutableString, &Shared<Module>)> {
|
||||
self.0.iter().map(|(n, m)| (n, m))
|
||||
self.0.iter().zip(self.1.iter())
|
||||
}
|
||||
/// Get a consuming iterator to this stack of imported [modules][Module] in reverse order.
|
||||
#[inline(always)]
|
||||
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> {
|
||||
self.0.into_iter().rev()
|
||||
}
|
||||
/// Add a stream of imported [modules][Module].
|
||||
#[inline(always)]
|
||||
pub fn extend(&mut self, stream: impl Iterator<Item = (ImmutableString, Shared<Module>)>) {
|
||||
self.0.extend(stream)
|
||||
self.0.into_iter().rev().zip(self.1.into_iter().rev())
|
||||
}
|
||||
/// Does the specified function hash key exist in this stack of imported [modules][Module]?
|
||||
#[allow(dead_code)]
|
||||
#[inline(always)]
|
||||
pub fn contains_fn(&self, hash: u64) -> bool {
|
||||
self.0.iter().any(|(_, m)| m.contains_qualified_fn(hash))
|
||||
self.1.iter().any(|m| m.contains_qualified_fn(hash))
|
||||
}
|
||||
/// Get specified function via its hash key.
|
||||
#[inline(always)]
|
||||
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&ImmutableString>)> {
|
||||
self.0
|
||||
self.1
|
||||
.iter()
|
||||
.rev()
|
||||
.find_map(|(_, m)| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
||||
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
||||
}
|
||||
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of
|
||||
/// imported [modules][Module]?
|
||||
#[allow(dead_code)]
|
||||
#[inline(always)]
|
||||
pub fn contains_iter(&self, id: TypeId) -> bool {
|
||||
self.0.iter().any(|(_, m)| m.contains_qualified_iter(id))
|
||||
self.1.iter().any(|m| m.contains_qualified_iter(id))
|
||||
}
|
||||
/// Get the specified [`TypeId`][std::any::TypeId] iterator.
|
||||
#[inline(always)]
|
||||
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
||||
self.0
|
||||
.iter()
|
||||
.rev()
|
||||
.find_map(|(_, m)| m.get_qualified_iter(id))
|
||||
self.1.iter().rev().find_map(|m| m.get_qualified_iter(id))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,7 +539,10 @@ impl Engine {
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
if !fn_def.mods.is_empty() {
|
||||
mods.extend(fn_def.mods.iter_raw().map(|(n, m)| (n.clone(), m.clone())));
|
||||
fn_def
|
||||
.mods
|
||||
.iter_raw()
|
||||
.for_each(|(n, m)| mods.push(n.clone(), m.clone()));
|
||||
}
|
||||
|
||||
// Evaluate the function
|
||||
|
@ -1836,7 +1836,7 @@ impl Module {
|
||||
// Collect a particular module.
|
||||
fn index_module<'a>(
|
||||
module: &'a Module,
|
||||
qualifiers: &mut Vec<&'a str>,
|
||||
path: &mut Vec<&'a str>,
|
||||
variables: &mut HashMap<u64, Dynamic, StraightHasherBuilder>,
|
||||
functions: &mut HashMap<u64, CallableFunction, StraightHasherBuilder>,
|
||||
type_iterators: &mut HashMap<TypeId, IteratorFn>,
|
||||
@ -1845,16 +1845,16 @@ impl Module {
|
||||
|
||||
module.modules.iter().for_each(|(name, m)| {
|
||||
// Index all the sub-modules first.
|
||||
qualifiers.push(name);
|
||||
if index_module(m, qualifiers, variables, functions, type_iterators) {
|
||||
path.push(name);
|
||||
if index_module(m, path, variables, functions, type_iterators) {
|
||||
contains_indexed_global_functions = true;
|
||||
}
|
||||
qualifiers.pop();
|
||||
path.pop();
|
||||
});
|
||||
|
||||
// Index all variables
|
||||
module.variables.iter().for_each(|(var_name, value)| {
|
||||
let hash_var = crate::calc_fn_hash(qualifiers.iter().map(|&v| v), var_name, 0);
|
||||
let hash_var = crate::calc_fn_hash(path.iter().map(|&v| v), var_name, 0);
|
||||
variables.insert(hash_var, value.clone());
|
||||
});
|
||||
|
||||
@ -1880,15 +1880,12 @@ impl Module {
|
||||
}
|
||||
|
||||
if !f.func.is_script() {
|
||||
let hash_qualified_fn = calc_native_fn_hash(
|
||||
qualifiers.iter().cloned(),
|
||||
f.name.as_str(),
|
||||
&f.param_types,
|
||||
);
|
||||
let hash_qualified_fn =
|
||||
calc_native_fn_hash(path.iter().cloned(), f.name.as_str(), &f.param_types);
|
||||
functions.insert(hash_qualified_fn, f.func.clone());
|
||||
} else if cfg!(not(feature = "no_function")) {
|
||||
let hash_qualified_script =
|
||||
crate::calc_fn_hash(qualifiers.iter().cloned(), f.name.as_str(), f.params);
|
||||
crate::calc_fn_hash(path.iter().cloned(), f.name.as_str(), f.params);
|
||||
functions.insert(hash_qualified_script, f.func.clone());
|
||||
}
|
||||
});
|
||||
@ -1897,16 +1894,16 @@ impl Module {
|
||||
}
|
||||
|
||||
if !self.indexed {
|
||||
let mut qualifiers = Vec::with_capacity(4);
|
||||
let mut path = Vec::with_capacity(4);
|
||||
let mut variables = HashMap::with_capacity_and_hasher(16, StraightHasherBuilder);
|
||||
let mut functions = HashMap::with_capacity_and_hasher(256, StraightHasherBuilder);
|
||||
let mut type_iterators = HashMap::with_capacity(16);
|
||||
|
||||
qualifiers.push("root");
|
||||
path.push("root");
|
||||
|
||||
self.contains_indexed_global_functions = index_module(
|
||||
self,
|
||||
&mut qualifiers,
|
||||
&mut path,
|
||||
&mut variables,
|
||||
&mut functions,
|
||||
&mut type_iterators,
|
||||
|
12
src/token.rs
12
src/token.rs
@ -840,8 +840,8 @@ pub fn parse_string_literal(
|
||||
pos: &mut Position,
|
||||
enclosing_char: char,
|
||||
) -> Result<String, (LexError, Position)> {
|
||||
let mut result: StaticVec<char> = Default::default();
|
||||
let mut escape: StaticVec<char> = Default::default();
|
||||
let mut result: smallvec::SmallVec<[char; 16]> = Default::default();
|
||||
let mut escape: smallvec::SmallVec<[char; 12]> = Default::default();
|
||||
|
||||
let start = *pos;
|
||||
|
||||
@ -1109,7 +1109,7 @@ fn get_next_token_inner(
|
||||
|
||||
// digit ...
|
||||
('0'..='9', _) => {
|
||||
let mut result: StaticVec<char> = Default::default();
|
||||
let mut result: smallvec::SmallVec<[char; 16]> = Default::default();
|
||||
let mut radix_base: Option<u32> = None;
|
||||
let mut valid: fn(char) -> bool = is_numeric_digit;
|
||||
result.push(c);
|
||||
@ -1596,7 +1596,7 @@ fn get_identifier(
|
||||
start_pos: Position,
|
||||
first_char: char,
|
||||
) -> Option<(Token, Position)> {
|
||||
let mut result: StaticVec<_> = Default::default();
|
||||
let mut result: smallvec::SmallVec<[char; 8]> = Default::default();
|
||||
result.push(first_char);
|
||||
|
||||
while let Some(next_char) = stream.peek_next() {
|
||||
@ -1691,10 +1691,10 @@ pub fn is_id_continue(x: char) -> bool {
|
||||
pub struct MultiInputsStream<'a> {
|
||||
/// Buffered character, if any.
|
||||
buf: Option<char>,
|
||||
/// The input character streams.
|
||||
streams: StaticVec<Peekable<Chars<'a>>>,
|
||||
/// The current stream index.
|
||||
index: usize,
|
||||
/// The input character streams.
|
||||
streams: StaticVec<Peekable<Chars<'a>>>,
|
||||
}
|
||||
|
||||
impl InputStream for MultiInputsStream<'_> {
|
||||
|
Loading…
Reference in New Issue
Block a user