diff --git a/src/ast.rs b/src/ast.rs index 06196a67..4891878b 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -6,7 +6,6 @@ use crate::module::NamespaceRef; use crate::stdlib::{ borrow::Cow, boxed::Box, - collections::HashMap, fmt, hash::{Hash, Hasher}, num::{NonZeroU64, NonZeroUsize}, @@ -16,7 +15,7 @@ use crate::stdlib::{ vec::Vec, }; use crate::token::Token; -use crate::utils::StraightHasherBuilder; +use crate::utils::{HashableHashMap, StraightHasherBuilder}; use crate::{ Dynamic, FnNamespace, FnPtr, ImmutableString, Module, Position, Shared, StaticVec, INT, }; @@ -691,54 +690,6 @@ pub enum ReturnType { Exception, } -/// A type that wraps a [`HashMap`]`` for the `switch` statement and implements [`Hash`]. -#[derive(Clone)] -pub struct SwitchHashWrapper(HashMap); - -impl From> for SwitchHashWrapper { - fn from(value: HashMap) -> Self { - Self(value) - } -} -impl AsRef> for SwitchHashWrapper { - fn as_ref(&self) -> &HashMap { - &self.0 - } -} -impl AsMut> for SwitchHashWrapper { - fn as_mut(&mut self) -> &mut HashMap { - &mut self.0 - } -} -impl Deref for SwitchHashWrapper { - type Target = HashMap; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl DerefMut for SwitchHashWrapper { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl fmt::Debug for SwitchHashWrapper { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} -impl Hash for SwitchHashWrapper { - fn hash(&self, state: &mut H) { - let mut keys: Vec<_> = self.0.keys().collect(); - keys.sort(); - - keys.into_iter().for_each(|key| { - key.hash(state); - self.0.get(&key).unwrap().hash(state); - }); - } -} - /// _(INTERNALS)_ A statement. /// Exported under the `internals` feature only. /// @@ -752,7 +703,14 @@ pub enum Stmt { /// `if` expr `{` stmt `}` `else` `{` stmt `}` If(Expr, Box<(Stmt, Option)>, Position), /// `switch` expr `{` literal or _ `=>` stmt `,` ... `}` - Switch(Expr, Box<(SwitchHashWrapper, Option)>, Position), + Switch( + Expr, + Box<( + HashableHashMap, + Option, + )>, + Position, + ), /// `while` expr `{` stmt `}` While(Expr, Box, Position), /// `do` `{` stmt `}` `while`|`until` expr diff --git a/src/lib.rs b/src/lib.rs index 642f6139..21a57ab1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,8 +184,8 @@ pub use token::{get_next_token, parse_string_literal, InputStream, Token, Tokeni #[cfg(feature = "internals")] #[deprecated = "this type is volatile and may change"] pub use ast::{ - BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallExpr, Ident, ReturnType, ScriptFnDef, Stmt, - SwitchHashWrapper, + BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallExpr, HashableHashMap, Ident, ReturnType, + ScriptFnDef, Stmt, }; #[cfg(feature = "internals")] diff --git a/src/utils.rs b/src/utils.rs index c43a5aaf..9d2a2417 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,11 +6,13 @@ use crate::stdlib::{ borrow::Borrow, boxed::Box, cmp::Ordering, + collections::HashMap, fmt, + fmt::{Debug, Display}, hash::{BuildHasher, Hash, Hasher}, iter::{empty, FromIterator}, num::NonZeroU64, - ops::{Add, AddAssign, Deref}, + ops::{Add, AddAssign, Deref, DerefMut}, str::FromStr, string::{String, ToString}, }; @@ -140,6 +142,55 @@ pub(crate) fn combine_hashes(a: NonZeroU64, b: NonZeroU64) -> NonZeroU64 { NonZeroU64::new(a.get() ^ b.get()).unwrap_or_else(|| NonZeroU64::new(42).unwrap()) } +/// _(INTERNALS)_ A type that wraps a [`HashMap`] and implements [`Hash`]. +/// Exported under the `internals` feature only. +#[derive(Clone, Default)] +pub struct HashableHashMap(HashMap); + +impl From> for HashableHashMap { + fn from(value: HashMap) -> Self { + Self(value) + } +} +impl AsRef> for HashableHashMap { + fn as_ref(&self) -> &HashMap { + &self.0 + } +} +impl AsMut> for HashableHashMap { + fn as_mut(&mut self) -> &mut HashMap { + &mut self.0 + } +} +impl Deref for HashableHashMap { + type Target = HashMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for HashableHashMap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl Debug for HashableHashMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} +impl Hash for HashableHashMap { + fn hash(&self, state: &mut B) { + let mut keys: Vec<_> = self.0.keys().collect(); + keys.sort(); + + keys.into_iter().for_each(|key| { + key.hash(state); + self.0.get(&key).unwrap().hash(state); + }); + } +} + /// The system immutable string type. /// /// An [`ImmutableString`] wraps an [`Rc`][std::rc::Rc]`<`[`String`]`>` @@ -276,17 +327,17 @@ impl<'a> FromIterator for ImmutableString { } } -impl fmt::Display for ImmutableString { +impl Display for ImmutableString { #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.0.as_str(), f) + Display::fmt(self.0.as_str(), f) } } -impl fmt::Debug for ImmutableString { +impl Debug for ImmutableString { #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.0.as_str(), f) + Debug::fmt(self.0.as_str(), f) } }