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(Expr, Box<(String, Stmt)>, Position),
/// \[`export`\] `let` id `=` expr
Let(Box<Ident>, Option<Expr>, bool, Position),
Let(Box<IdentX>, Option<Expr>, bool, Position),
/// \[`export`\] `const` id `=` expr
Const(Box<Ident>, Option<Expr>, bool, Position),
Const(Box<IdentX>, Option<Expr>, bool, Position),
/// expr op`=` expr
Assignment(Box<(Expr, Cow<'static, str>, Expr)>, Position),
/// `{` stmt`;` ... `}`

View File

@ -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();

View File

@ -120,9 +120,9 @@ impl FuncInfo {
#[derive(Clone)]
pub struct Module {
/// Sub-modules.
modules: HashMap<String, Shared<Module>>,
modules: HashMap<ImmutableString, Shared<Module>>,
/// Module variables.
variables: HashMap<String, Dynamic>,
variables: HashMap<ImmutableString, Dynamic>,
/// Flattened collection of all module variables, including those in sub-modules.
all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>,
/// 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::<Vec<_>>()
.join(", "),
self.variables
@ -331,7 +331,11 @@ impl Module {
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
#[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.indexed = false;
self
@ -458,7 +462,7 @@ impl Module {
#[inline(always)]
pub fn set_sub_module(
&mut self,
name: impl Into<String>,
name: impl Into<ImmutableString>,
sub_module: impl Into<Shared<Module>>,
) -> &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

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;
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))
}
}

View File

@ -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<Dynamic>,
/// (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<'_> {
@ -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<ImmutableString> + PartialEq<ImmutableString>,
) -> &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<Item = (Cow<'a, str>, Dynamic, Vec<String>)> {
pub(crate) fn into_iter(
self,
) -> impl Iterator<Item = (Cow<'a, str>, Dynamic, Vec<ImmutableString>)> {
self.names
.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 } }")?;
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 }")?;