diff --git a/src/ast.rs b/src/ast.rs index 140a7cd8..ecac8042 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -618,9 +618,9 @@ pub enum Stmt { /// `for` id `in` expr `{` stmt `}` For(Expr, Box<(String, Stmt)>, Position), /// \[`export`\] `let` id `=` expr - Let(Box, Option, bool, Position), + Let(Box, Option, bool, Position), /// \[`export`\] `const` id `=` expr - Const(Box, Option, bool, Position), + Const(Box, Option, bool, Position), /// expr op`=` expr Assignment(Box<(Expr, Cow<'static, str>, Expr)>, Position), /// `{` stmt`;` ... `}` diff --git a/src/engine.rs b/src/engine.rs index 129ff1cf..b053af40 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -2302,9 +2302,9 @@ impl Engine { }; let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() { ( - var_def.name.clone().into(), + var_def.name.to_string().into(), if *export { - Some(var_def.name.to_string()) + Some(var_def.name.clone()) } else { None }, @@ -2371,7 +2371,7 @@ impl Engine { // Mark scope variables as public if let Some(index) = scope.get_index(name).map(|(i, _)| i) { let alias = rename.as_ref().map(|x| &x.name).unwrap_or_else(|| name); - scope.add_entry_alias(index, alias.to_string()); + scope.add_entry_alias(index, alias.clone()); } else { return EvalAltResult::ErrorVariableNotFound(name.to_string(), *id_pos) .into(); diff --git a/src/module/mod.rs b/src/module/mod.rs index 510c0884..6db9889d 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -120,9 +120,9 @@ impl FuncInfo { #[derive(Clone)] pub struct Module { /// Sub-modules. - modules: HashMap>, + modules: HashMap>, /// Module variables. - variables: HashMap, + variables: HashMap, /// Flattened collection of all module variables, including those in sub-modules. all_variables: HashMap, /// External Rust functions. @@ -160,7 +160,7 @@ impl fmt::Debug for Module { "Module(\n modules: {}\n vars: {}\n functions: {}\n)", self.modules .keys() - .map(String::as_str) + .map(|m| m.as_str()) .collect::>() .join(", "), self.variables @@ -331,7 +331,11 @@ impl Module { /// assert_eq!(module.get_var_value::("answer").unwrap(), 42); /// ``` #[inline(always)] - pub fn set_var(&mut self, name: impl Into, value: impl Variant + Clone) -> &mut Self { + pub fn set_var( + &mut self, + name: impl Into, + value: impl Variant + Clone, + ) -> &mut Self { self.variables.insert(name.into(), Dynamic::from(value)); self.indexed = false; self @@ -458,7 +462,7 @@ impl Module { #[inline(always)] pub fn set_sub_module( &mut self, - name: impl Into, + name: impl Into, sub_module: impl Into>, ) -> &mut Self { self.modules.insert(name.into(), sub_module.into()); @@ -1423,7 +1427,7 @@ impl Module { other.modules.iter().for_each(|(k, v)| { let mut m = Self::new(); m.merge_filtered(v, _filter); - self.set_sub_module(k, m); + self.set_sub_module(k.clone(), m); }); #[cfg(feature = "no_function")] self.modules diff --git a/src/parser.rs b/src/parser.rs index 34c4f848..479c2778 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -826,7 +826,7 @@ fn parse_switch( } } - let mut table = HashMap::with_capacity_and_hasher(16, StraightHasherBuilder); + let mut table = HashMap::new(); let mut def_stmt = None; loop { @@ -915,9 +915,12 @@ fn parse_switch( } } + let mut final_table = HashMap::with_capacity_and_hasher(table.len(), StraightHasherBuilder); + final_table.extend(table.into_iter()); + Ok(Stmt::Switch( item, - Box::new((table, def_stmt)), + Box::new((final_table, def_stmt)), settings.pos, )) } @@ -2158,14 +2161,14 @@ fn parse_let( AccessMode::ReadWrite => { let var_name = state.get_interned_string(name.clone()); state.stack.push((var_name, AccessMode::ReadWrite)); - let var_def = Ident::new(name, pos); + let var_def = IdentX::new(name, pos); Ok(Stmt::Let(Box::new(var_def), init_expr, export, token_pos)) } // const name = { expr:constant } AccessMode::ReadOnly => { let var_name = state.get_interned_string(name.clone()); state.stack.push((var_name, AccessMode::ReadOnly)); - let var_def = Ident::new(name, pos); + let var_def = IdentX::new(name, pos); Ok(Stmt::Const(Box::new(var_def), init_expr, export, token_pos)) } } diff --git a/src/scope.rs b/src/scope.rs index 93b4ba7d..4e5cc08a 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -1,8 +1,8 @@ //! Module that defines the [`Scope`] type representing a function call-stack scope. use crate::dynamic::{AccessMode, Variant}; -use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec}; -use crate::{Dynamic, StaticVec}; +use crate::stdlib::{borrow::Cow, boxed::Box, iter, vec::Vec}; +use crate::{Dynamic, ImmutableString, StaticVec}; /// Type containing information about the current scope. /// Useful for keeping state between [`Engine`][crate::Engine] evaluation runs. @@ -50,7 +50,7 @@ pub struct Scope<'a> { /// Current value of the entry. values: Vec, /// (Name, aliases) of the entry. The list of aliases is Boxed because it occurs rarely. - names: Vec<(Cow<'a, str>, Box>)>, + names: Vec<(Cow<'a, str>, Box>)>, } impl Default for Scope<'_> { @@ -364,10 +364,14 @@ impl<'a> Scope<'a> { /// Update the access type of an entry in the [`Scope`]. #[cfg(not(feature = "no_module"))] #[inline(always)] - pub(crate) fn add_entry_alias(&mut self, index: usize, alias: String) -> &mut Self { + pub(crate) fn add_entry_alias( + &mut self, + index: usize, + alias: impl Into + PartialEq, + ) -> &mut Self { let entry = self.names.get_mut(index).expect("invalid index in Scope"); - if !entry.1.contains(&alias) { - entry.1.push(alias); + if !entry.1.iter().any(|a| &alias == a) { + entry.1.push(alias.into()); } self } @@ -393,7 +397,9 @@ impl<'a> Scope<'a> { /// Get an iterator to entries in the [`Scope`]. #[inline(always)] #[allow(dead_code)] - pub(crate) fn into_iter(self) -> impl Iterator, Dynamic, Vec)> { + pub(crate) fn into_iter( + self, + ) -> impl Iterator, Dynamic, Vec)> { self.names .into_iter() .zip(self.values.into_iter()) diff --git a/tests/optimizer.rs b/tests/optimizer.rs index db8477a5..fa817bf1 100644 --- a/tests/optimizer.rs +++ b/tests/optimizer.rs @@ -55,7 +55,7 @@ fn test_optimizer_parse() -> Result<(), Box> { let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?; - assert!(format!("{:?}", ast).starts_with(r#"AST([Block([Const(Ident { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#)); + assert!(format!("{:?}", ast).starts_with(r#"AST([Block([Const(IdentX { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#)); let ast = engine.compile("if 1 == 2 { 42 }")?;