Optimize Scope.
This commit is contained in:
parent
3485f9b00b
commit
c55fc5a9a5
@ -2070,7 +2070,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
unsafe_cast_var_name_to_lifetime(&var_def.name).into()
|
unsafe_cast_var_name_to_lifetime(&var_def.name).into()
|
||||||
};
|
};
|
||||||
scope.push_dynamic_value(var_name, entry_type, val, false);
|
scope.push_dynamic_value(var_name, entry_type, val);
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +36,6 @@ use crate::engine::{Map, Target, FN_GET, FN_SET};
|
|||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
use crate::engine::KEYWORD_IS_SHARED;
|
use crate::engine::KEYWORD_IS_SHARED;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
use crate::scope::Entry as ScopeEntry;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, TypeId},
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -553,22 +549,14 @@ impl Engine {
|
|||||||
if let Some(captured) = _capture_scope {
|
if let Some(captured) = _capture_scope {
|
||||||
captured
|
captured
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|ScopeEntry { name, .. }| {
|
.filter(|(name, _, _, _)| func.externals.contains(name.as_ref()))
|
||||||
func.externals.contains(name.as_ref())
|
.for_each(|(name, typ, value, _)| {
|
||||||
})
|
|
||||||
.for_each(
|
|
||||||
|ScopeEntry {
|
|
||||||
name, typ, value, ..
|
|
||||||
}| {
|
|
||||||
// Consume the scope values.
|
// Consume the scope values.
|
||||||
match typ {
|
match typ {
|
||||||
ScopeEntryType::Normal => scope.push(name, value),
|
ScopeEntryType::Normal => scope.push(name, value),
|
||||||
ScopeEntryType::Constant => {
|
ScopeEntryType::Constant => scope.push_constant(name, value),
|
||||||
scope.push_constant(name, value)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = if _is_method {
|
let result = if _is_method {
|
||||||
|
@ -16,7 +16,7 @@ use crate::{ast::ScriptFnDef, fn_native::Shared};
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::AST,
|
ast::AST,
|
||||||
engine::{Engine, Imports},
|
engine::{Engine, Imports},
|
||||||
scope::{Entry as ScopeEntry, Scope},
|
scope::Scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
@ -1348,12 +1348,10 @@ impl Module {
|
|||||||
// Create new module
|
// Create new module
|
||||||
let mut module = Module::new();
|
let mut module = Module::new();
|
||||||
|
|
||||||
scope
|
scope.into_iter().for_each(|(_, _, value, alias)| {
|
||||||
.into_iter()
|
|
||||||
.for_each(|ScopeEntry { value, alias, .. }| {
|
|
||||||
// Variables with an alias left in the scope become module variables
|
// Variables with an alias left in the scope become module variables
|
||||||
if let Some(alias) = alias {
|
if let Some(alias) = alias {
|
||||||
module.variables.insert(*alias, value);
|
module.variables.insert(alias, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use crate::engine::{
|
|||||||
use crate::fn_call::run_builtin_binary_op;
|
use crate::fn_call::run_builtin_binary_op;
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::parser::map_dynamic_to_expr;
|
use crate::parser::map_dynamic_to_expr;
|
||||||
use crate::scope::{Entry as ScopeEntry, Scope};
|
use crate::scope::Scope;
|
||||||
use crate::token::{is_valid_identifier, Position};
|
use crate::token::{is_valid_identifier, Position};
|
||||||
use crate::{calc_native_fn_hash, StaticVec};
|
use crate::{calc_native_fn_hash, StaticVec};
|
||||||
|
|
||||||
@ -721,24 +721,15 @@ fn optimize(
|
|||||||
// Set up the state
|
// Set up the state
|
||||||
let mut state = State::new(engine, lib, level);
|
let mut state = State::new(engine, lib, level);
|
||||||
|
|
||||||
// Add constants from the scope into the state
|
// Add constants from the scope that can be made into a literal into the state
|
||||||
scope
|
scope
|
||||||
.to_iter()
|
.iter()
|
||||||
// Get all the constants that can be made into a constant literal.
|
.filter(|(_, typ, _)| *typ)
|
||||||
.filter(|ScopeEntry { typ, .. }| typ.is_constant())
|
.for_each(|(name, _, value)| {
|
||||||
.for_each(
|
if let Some(val) = map_dynamic_to_expr(value.clone(), Position::none()) {
|
||||||
|ScopeEntry {
|
state.push_constant(name, val);
|
||||||
name, expr, value, ..
|
|
||||||
}| {
|
|
||||||
if let Some(val) = expr
|
|
||||||
.as_ref()
|
|
||||||
.map(|expr| expr.as_ref().clone())
|
|
||||||
.or_else(|| map_dynamic_to_expr(value.clone(), Position::none()))
|
|
||||||
{
|
|
||||||
state.push_constant(name.as_ref(), val);
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
let orig_constants_len = state.constants.len();
|
let orig_constants_len = state.constants.len();
|
||||||
|
|
||||||
|
176
src/scope.rs
176
src/scope.rs
@ -1,11 +1,8 @@
|
|||||||
//! Module that defines the `Scope` type representing a function call-stack scope.
|
//! Module that defines the `Scope` type representing a function call-stack scope.
|
||||||
|
|
||||||
use crate::ast::Expr;
|
|
||||||
use crate::dynamic::{Dynamic, Variant};
|
use crate::dynamic::{Dynamic, Variant};
|
||||||
use crate::parser::map_dynamic_to_expr;
|
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
use crate::stdlib::{borrow::Cow, iter, string::String, vec::Vec};
|
||||||
|
|
||||||
/// Type of an entry in the Scope.
|
/// Type of an entry in the Scope.
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
||||||
@ -27,21 +24,6 @@ impl EntryType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An entry in the Scope.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Entry<'a> {
|
|
||||||
/// Name of the entry.
|
|
||||||
pub name: Cow<'a, str>,
|
|
||||||
/// Type of the entry.
|
|
||||||
pub typ: EntryType,
|
|
||||||
/// Current value of the entry.
|
|
||||||
pub value: Dynamic,
|
|
||||||
/// Alias of the entry.
|
|
||||||
pub alias: Option<Box<String>>,
|
|
||||||
/// A constant expression if the initial value matches one of the recognized types.
|
|
||||||
pub expr: Option<Box<Expr>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type containing information about the current scope.
|
/// Type containing information about the current scope.
|
||||||
/// Useful for keeping state between `Engine` evaluation runs.
|
/// Useful for keeping state between `Engine` evaluation runs.
|
||||||
///
|
///
|
||||||
@ -72,8 +54,25 @@ pub struct Entry<'a> {
|
|||||||
///
|
///
|
||||||
/// When searching for entries, newly-added entries are found before similarly-named but older entries,
|
/// When searching for entries, newly-added entries are found before similarly-named but older entries,
|
||||||
/// allowing for automatic _shadowing_.
|
/// allowing for automatic _shadowing_.
|
||||||
|
//
|
||||||
|
// # Implementation Notes
|
||||||
|
//
|
||||||
|
// `Scope` is implemented as three `Vec`'s of exactly the same length. Variables data (name, type, etc.)
|
||||||
|
// is manually split into three equal-length arrays. That's because variable names take up the most space,
|
||||||
|
// with `Cow<str>` being four words long, but in the vast majority of cases the name is NOT used to look up
|
||||||
|
// a variable's value. Variable lookup is usually via direct index, by-passing the name altogether.
|
||||||
|
//
|
||||||
|
// Since `Dynamic` is reasonably small, packing it tightly improves cache locality when variables are accessed.
|
||||||
|
// The variable type is packed separately into another array because it is even smaller.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Scope<'a>(Vec<Entry<'a>>);
|
pub struct Scope<'a> {
|
||||||
|
/// (Name, alias) of the entry.
|
||||||
|
names: Vec<(Cow<'a, str>, Option<String>)>,
|
||||||
|
/// Type of the entry.
|
||||||
|
types: Vec<EntryType>,
|
||||||
|
/// Current value of the entry.
|
||||||
|
values: Vec<Dynamic>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Scope<'a> {
|
impl<'a> Scope<'a> {
|
||||||
/// Create a new Scope.
|
/// Create a new Scope.
|
||||||
@ -114,7 +113,9 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) -> &mut Self {
|
pub fn clear(&mut self) -> &mut Self {
|
||||||
self.0.clear();
|
self.names.clear();
|
||||||
|
self.types.clear();
|
||||||
|
self.values.clear();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +134,7 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.values.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the Scope empty?
|
/// Is the Scope empty?
|
||||||
@ -151,7 +152,7 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.len() == 0
|
self.values.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add (push) a new entry to the Scope.
|
/// Add (push) a new entry to the Scope.
|
||||||
@ -172,7 +173,7 @@ impl<'a> Scope<'a> {
|
|||||||
name: K,
|
name: K,
|
||||||
value: T,
|
value: T,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.push_dynamic_value(name, EntryType::Normal, Dynamic::from(value), false)
|
self.push_dynamic_value(name, EntryType::Normal, Dynamic::from(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add (push) a new `Dynamic` entry to the Scope.
|
/// Add (push) a new `Dynamic` entry to the Scope.
|
||||||
@ -189,7 +190,7 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_dynamic<K: Into<Cow<'a, str>>>(&mut self, name: K, value: Dynamic) -> &mut Self {
|
pub fn push_dynamic<K: Into<Cow<'a, str>>>(&mut self, name: K, value: Dynamic) -> &mut Self {
|
||||||
self.push_dynamic_value(name, EntryType::Normal, value, false)
|
self.push_dynamic_value(name, EntryType::Normal, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add (push) a new constant to the Scope.
|
/// Add (push) a new constant to the Scope.
|
||||||
@ -216,7 +217,7 @@ impl<'a> Scope<'a> {
|
|||||||
name: K,
|
name: K,
|
||||||
value: T,
|
value: T,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.push_dynamic_value(name, EntryType::Constant, Dynamic::from(value), true)
|
self.push_dynamic_value(name, EntryType::Constant, Dynamic::from(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add (push) a new constant with a `Dynamic` value to the Scope.
|
/// Add (push) a new constant with a `Dynamic` value to the Scope.
|
||||||
@ -244,7 +245,7 @@ impl<'a> Scope<'a> {
|
|||||||
name: K,
|
name: K,
|
||||||
value: Dynamic,
|
value: Dynamic,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.push_dynamic_value(name, EntryType::Constant, value, true)
|
self.push_dynamic_value(name, EntryType::Constant, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add (push) a new entry with a `Dynamic` value to the Scope.
|
/// Add (push) a new entry with a `Dynamic` value to the Scope.
|
||||||
@ -254,22 +255,10 @@ impl<'a> Scope<'a> {
|
|||||||
name: K,
|
name: K,
|
||||||
entry_type: EntryType,
|
entry_type: EntryType,
|
||||||
value: Dynamic,
|
value: Dynamic,
|
||||||
map_expr: bool,
|
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let expr = if map_expr {
|
self.names.push((name.into(), None));
|
||||||
map_dynamic_to_expr(value.clone(), Position::none()).map(Box::new)
|
self.types.push(entry_type);
|
||||||
} else {
|
self.values.push(value.into());
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
self.0.push(Entry {
|
|
||||||
name: name.into(),
|
|
||||||
typ: entry_type,
|
|
||||||
alias: None,
|
|
||||||
value: value.into(),
|
|
||||||
expr,
|
|
||||||
});
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +290,9 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn rewind(&mut self, size: usize) -> &mut Self {
|
pub fn rewind(&mut self, size: usize) -> &mut Self {
|
||||||
self.0.truncate(size);
|
self.names.truncate(size);
|
||||||
|
self.types.truncate(size);
|
||||||
|
self.values.truncate(size);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,37 +311,28 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn contains(&self, name: &str) -> bool {
|
pub fn contains(&self, name: &str) -> bool {
|
||||||
self.0
|
self.names
|
||||||
.iter()
|
.iter()
|
||||||
.rev() // Always search a Scope in reverse order
|
.rev() // Always search a Scope in reverse order
|
||||||
.any(|Entry { name: key, .. }| name == key)
|
.any(|(key, _)| name == key.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find an entry in the Scope, starting from the last.
|
/// Find an entry in the Scope, starting from the last.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_index(&self, name: &str) -> Option<(usize, EntryType)> {
|
pub(crate) fn get_index(&self, name: &str) -> Option<(usize, EntryType)> {
|
||||||
self.0
|
self.names
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev() // Always search a Scope in reverse order
|
.rev() // Always search a Scope in reverse order
|
||||||
.find_map(|(index, Entry { name: key, typ, .. })| {
|
.find_map(|(index, (key, _))| {
|
||||||
if name == key {
|
if name == key.as_ref() {
|
||||||
Some((index, *typ))
|
Some((index, self.types[index]))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an entry in the Scope, starting from the last.
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn get_entry(&self, name: &str) -> Option<&Entry> {
|
|
||||||
self.0
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.find(|Entry { name: key, .. }| name == key)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the value of an entry in the Scope, starting from the last.
|
/// Get the value of an entry in the Scope, starting from the last.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -365,8 +347,12 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_value<T: Variant + Clone>(&self, name: &str) -> Option<T> {
|
pub fn get_value<T: Variant + Clone>(&self, name: &str) -> Option<T> {
|
||||||
self.get_entry(name)
|
self.names
|
||||||
.and_then(|Entry { value, .. }| value.flatten_clone().try_cast())
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.rev()
|
||||||
|
.find(|(_, (key, _))| name == key.as_ref())
|
||||||
|
.and_then(|(index, _)| self.values[index].flatten_clone().try_cast())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the value of the named entry.
|
/// Update the value of the named entry.
|
||||||
@ -398,7 +384,7 @@ impl<'a> Scope<'a> {
|
|||||||
}
|
}
|
||||||
Some((_, EntryType::Constant)) => panic!("variable {} is constant", name),
|
Some((_, EntryType::Constant)) => panic!("variable {} is constant", name),
|
||||||
Some((index, EntryType::Normal)) => {
|
Some((index, EntryType::Normal)) => {
|
||||||
self.0.get_mut(index).unwrap().value = Dynamic::from(value);
|
*self.values.get_mut(index).unwrap() = Dynamic::from(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
@ -407,16 +393,18 @@ impl<'a> Scope<'a> {
|
|||||||
/// Get a mutable reference to an entry in the Scope.
|
/// Get a mutable reference to an entry in the Scope.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_mut(&mut self, index: usize) -> (&mut Dynamic, EntryType) {
|
pub(crate) fn get_mut(&mut self, index: usize) -> (&mut Dynamic, EntryType) {
|
||||||
let entry = self.0.get_mut(index).expect("invalid index in Scope");
|
(
|
||||||
(&mut entry.value, entry.typ)
|
self.values.get_mut(index).expect("invalid index in Scope"),
|
||||||
|
self.types[index],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the access type of an entry in the Scope.
|
/// Update the access type of an entry in the Scope.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn set_entry_alias(&mut self, index: usize, alias: String) -> &mut Self {
|
pub(crate) fn set_entry_alias(&mut self, index: usize, alias: String) -> &mut Self {
|
||||||
let entry = self.0.get_mut(index).expect("invalid index in Scope");
|
let entry = self.names.get_mut(index).expect("invalid index in Scope");
|
||||||
entry.alias = Some(Box::new(alias));
|
entry.1 = Some(alias);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,34 +412,36 @@ impl<'a> Scope<'a> {
|
|||||||
/// Shadowed variables are omitted in the copy.
|
/// Shadowed variables are omitted in the copy.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn clone_visible(&self) -> Self {
|
pub(crate) fn clone_visible(&self) -> Self {
|
||||||
let mut entries: Vec<Entry> = Default::default();
|
let mut entries: Self = Default::default();
|
||||||
|
|
||||||
self.0.iter().rev().for_each(|entry| {
|
self.names
|
||||||
if entries
|
|
||||||
.iter()
|
.iter()
|
||||||
.find(|Entry { name, .. }| &entry.name == name)
|
.enumerate()
|
||||||
.is_none()
|
.rev()
|
||||||
{
|
.for_each(|(index, (name, alias))| {
|
||||||
entries.push(entry.clone());
|
if !entries.names.iter().any(|(key, _)| key == name) {
|
||||||
|
entries.names.push((name.clone(), alias.clone()));
|
||||||
|
entries.types.push(self.types[index]);
|
||||||
|
entries.values.push(self.values[index].clone());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self(entries)
|
entries
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator to entries in the Scope.
|
/// Get an iterator to entries in the Scope.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn into_iter(self) -> impl Iterator<Item = Entry<'a>> {
|
pub(crate) fn into_iter(
|
||||||
self.0.into_iter()
|
self,
|
||||||
}
|
) -> impl Iterator<Item = (Cow<'a, str>, EntryType, Dynamic, Option<String>)> {
|
||||||
|
self.names
|
||||||
/// Get an iterator to entries in the Scope in reverse order.
|
.into_iter()
|
||||||
#[inline(always)]
|
.zip(self.types.into_iter().zip(self.values.into_iter()))
|
||||||
pub(crate) fn to_iter(&self) -> impl Iterator<Item = &Entry> {
|
.map(|((name, alias), (typ, value))| (name, typ, value, alias))
|
||||||
self.0.iter().rev() // Always search a Scope in reverse order
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator to entries in the Scope.
|
/// Get an iterator to entries in the Scope.
|
||||||
|
/// Shared values are flatten-cloned.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -484,25 +474,21 @@ impl<'a> Scope<'a> {
|
|||||||
/// Get an iterator to entries in the Scope.
|
/// Get an iterator to entries in the Scope.
|
||||||
/// Shared values are not expanded.
|
/// Shared values are not expanded.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_raw(&self) -> impl Iterator<Item = (&str, bool, &Dynamic)> {
|
pub fn iter_raw<'x: 'a>(&'x self) -> impl Iterator<Item = (&'a str, bool, &'x Dynamic)> + 'x {
|
||||||
self.0.iter().map(
|
self.names
|
||||||
|Entry {
|
.iter()
|
||||||
name, typ, value, ..
|
.zip(self.types.iter().zip(self.values.iter()))
|
||||||
}| { (name.as_ref(), typ.is_constant(), value) },
|
.map(|((name, _), (typ, value))| (name.as_ref(), typ.is_constant(), value))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: Into<Cow<'a, str>>> iter::Extend<(K, EntryType, Dynamic)> for Scope<'a> {
|
impl<'a, K: Into<Cow<'a, str>>> iter::Extend<(K, EntryType, Dynamic)> for Scope<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn extend<T: IntoIterator<Item = (K, EntryType, Dynamic)>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = (K, EntryType, Dynamic)>>(&mut self, iter: T) {
|
||||||
self.0
|
iter.into_iter().for_each(|(name, typ, value)| {
|
||||||
.extend(iter.into_iter().map(|(name, typ, value)| Entry {
|
self.names.push((name.into(), None));
|
||||||
name: name.into(),
|
self.types.push(typ);
|
||||||
typ,
|
self.values.push(value);
|
||||||
alias: None,
|
});
|
||||||
value: value.into(),
|
|
||||||
expr: None,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user