Use ImmutableString.

This commit is contained in:
Stephen Chung 2020-12-11 12:57:07 +08:00
parent 839da9c7f0
commit bed29da71a
6 changed files with 36 additions and 23 deletions

View File

@ -618,9 +618,9 @@ pub enum Stmt {
/// `for` id `in` expr `{` stmt `}` /// `for` id `in` expr `{` stmt `}`
For(Expr, Box<(String, Stmt)>, Position), For(Expr, Box<(String, Stmt)>, Position),
/// \[`export`\] `let` id `=` expr /// \[`export`\] `let` id `=` expr
Let(Box<Ident>, Option<Expr>, bool, Position), Let(Box<IdentX>, Option<Expr>, bool, Position),
/// \[`export`\] `const` id `=` expr /// \[`export`\] `const` id `=` expr
Const(Box<Ident>, Option<Expr>, bool, Position), Const(Box<IdentX>, Option<Expr>, bool, Position),
/// expr op`=` expr /// expr op`=` expr
Assignment(Box<(Expr, Cow<'static, str>, Expr)>, Position), Assignment(Box<(Expr, Cow<'static, str>, Expr)>, Position),
/// `{` stmt`;` ... `}` /// `{` stmt`;` ... `}`

View File

@ -2302,9 +2302,9 @@ impl Engine {
}; };
let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() { let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() {
( (
var_def.name.clone().into(), var_def.name.to_string().into(),
if *export { if *export {
Some(var_def.name.to_string()) Some(var_def.name.clone())
} else { } else {
None None
}, },
@ -2371,7 +2371,7 @@ impl Engine {
// Mark scope variables as public // Mark scope variables as public
if let Some(index) = scope.get_index(name).map(|(i, _)| i) { if let Some(index) = scope.get_index(name).map(|(i, _)| i) {
let alias = rename.as_ref().map(|x| &x.name).unwrap_or_else(|| name); 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 { } else {
return EvalAltResult::ErrorVariableNotFound(name.to_string(), *id_pos) return EvalAltResult::ErrorVariableNotFound(name.to_string(), *id_pos)
.into(); .into();

View File

@ -120,9 +120,9 @@ impl FuncInfo {
#[derive(Clone)] #[derive(Clone)]
pub struct Module { pub struct Module {
/// Sub-modules. /// Sub-modules.
modules: HashMap<String, Shared<Module>>, modules: HashMap<ImmutableString, Shared<Module>>,
/// Module variables. /// Module variables.
variables: HashMap<String, Dynamic>, variables: HashMap<ImmutableString, Dynamic>,
/// Flattened collection of all module variables, including those in sub-modules. /// Flattened collection of all module variables, including those in sub-modules.
all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>, all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>,
/// External Rust functions. /// External Rust functions.
@ -160,7 +160,7 @@ impl fmt::Debug for Module {
"Module(\n modules: {}\n vars: {}\n functions: {}\n)", "Module(\n modules: {}\n vars: {}\n functions: {}\n)",
self.modules self.modules
.keys() .keys()
.map(String::as_str) .map(|m| m.as_str())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "), .join(", "),
self.variables self.variables
@ -331,7 +331,11 @@ impl Module {
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42); /// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn set_var(&mut self, name: impl Into<String>, value: impl Variant + Clone) -> &mut Self { pub fn set_var(
&mut self,
name: impl Into<ImmutableString>,
value: impl Variant + Clone,
) -> &mut Self {
self.variables.insert(name.into(), Dynamic::from(value)); self.variables.insert(name.into(), Dynamic::from(value));
self.indexed = false; self.indexed = false;
self self
@ -458,7 +462,7 @@ impl Module {
#[inline(always)] #[inline(always)]
pub fn set_sub_module( pub fn set_sub_module(
&mut self, &mut self,
name: impl Into<String>, name: impl Into<ImmutableString>,
sub_module: impl Into<Shared<Module>>, sub_module: impl Into<Shared<Module>>,
) -> &mut Self { ) -> &mut Self {
self.modules.insert(name.into(), sub_module.into()); self.modules.insert(name.into(), sub_module.into());
@ -1423,7 +1427,7 @@ impl Module {
other.modules.iter().for_each(|(k, v)| { other.modules.iter().for_each(|(k, v)| {
let mut m = Self::new(); let mut m = Self::new();
m.merge_filtered(v, _filter); m.merge_filtered(v, _filter);
self.set_sub_module(k, m); self.set_sub_module(k.clone(), m);
}); });
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]
self.modules self.modules

View File

@ -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; let mut def_stmt = None;
loop { 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( Ok(Stmt::Switch(
item, item,
Box::new((table, def_stmt)), Box::new((final_table, def_stmt)),
settings.pos, settings.pos,
)) ))
} }
@ -2158,14 +2161,14 @@ fn parse_let(
AccessMode::ReadWrite => { AccessMode::ReadWrite => {
let var_name = state.get_interned_string(name.clone()); let var_name = state.get_interned_string(name.clone());
state.stack.push((var_name, AccessMode::ReadWrite)); 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)) Ok(Stmt::Let(Box::new(var_def), init_expr, export, token_pos))
} }
// const name = { expr:constant } // const name = { expr:constant }
AccessMode::ReadOnly => { AccessMode::ReadOnly => {
let var_name = state.get_interned_string(name.clone()); let var_name = state.get_interned_string(name.clone());
state.stack.push((var_name, AccessMode::ReadOnly)); 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)) Ok(Stmt::Const(Box::new(var_def), init_expr, export, token_pos))
} }
} }

View File

@ -1,8 +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::dynamic::{AccessMode, Variant}; use crate::dynamic::{AccessMode, Variant};
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec}; use crate::stdlib::{borrow::Cow, boxed::Box, iter, vec::Vec};
use crate::{Dynamic, StaticVec}; use crate::{Dynamic, ImmutableString, StaticVec};
/// Type containing information about the current scope. /// Type containing information about the current scope.
/// Useful for keeping state between [`Engine`][crate::Engine] evaluation runs. /// Useful for keeping state between [`Engine`][crate::Engine] evaluation runs.
@ -50,7 +50,7 @@ pub struct Scope<'a> {
/// Current value of the entry. /// Current value of the entry.
values: Vec<Dynamic>, values: Vec<Dynamic>,
/// (Name, aliases) of the entry. The list of aliases is Boxed because it occurs rarely. /// (Name, aliases) of the entry. The list of aliases is Boxed because it occurs rarely.
names: Vec<(Cow<'a, str>, Box<StaticVec<String>>)>, names: Vec<(Cow<'a, str>, Box<StaticVec<ImmutableString>>)>,
} }
impl Default for Scope<'_> { impl Default for Scope<'_> {
@ -364,10 +364,14 @@ impl<'a> Scope<'a> {
/// 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 add_entry_alias(&mut self, index: usize, alias: String) -> &mut Self { pub(crate) fn add_entry_alias(
&mut self,
index: usize,
alias: impl Into<ImmutableString> + PartialEq<ImmutableString>,
) -> &mut Self {
let entry = self.names.get_mut(index).expect("invalid index in Scope"); let entry = self.names.get_mut(index).expect("invalid index in Scope");
if !entry.1.contains(&alias) { if !entry.1.iter().any(|a| &alias == a) {
entry.1.push(alias); entry.1.push(alias.into());
} }
self self
} }
@ -393,7 +397,9 @@ impl<'a> Scope<'a> {
/// Get an iterator to entries in the [`Scope`]. /// Get an iterator to entries in the [`Scope`].
#[inline(always)] #[inline(always)]
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn into_iter(self) -> impl Iterator<Item = (Cow<'a, str>, Dynamic, Vec<String>)> { pub(crate) fn into_iter(
self,
) -> impl Iterator<Item = (Cow<'a, str>, Dynamic, Vec<ImmutableString>)> {
self.names self.names
.into_iter() .into_iter()
.zip(self.values.into_iter()) .zip(self.values.into_iter())

View File

@ -55,7 +55,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?; 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 }")?; let ast = engine.compile("if 1 == 2 { 42 }")?;