diff --git a/dust-lang/src/identifier.rs b/dust-lang/src/identifier.rs index 4caf0e5..ac8999f 100644 --- a/dust-lang/src/identifier.rs +++ b/dust-lang/src/identifier.rs @@ -1,16 +1,36 @@ use std::{ + collections::HashMap, fmt::{self, Display, Formatter}, - sync::Arc, + sync::{Arc, OnceLock, RwLock}, }; use serde::{de::Visitor, Deserialize, Serialize}; +static IDENTIFIER_CACHE: OnceLock>> = OnceLock::new(); + +fn identifier_cache<'a>() -> &'a RwLock> { + IDENTIFIER_CACHE.get_or_init(|| RwLock::new(HashMap::new())) +} + #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pub struct Identifier(Arc); impl Identifier { - pub fn new(string: T) -> Self { - Identifier(Arc::new(string.to_string())) + pub fn new(string: &str) -> Self { + let cache = identifier_cache(); + + if let Some(identifier) = cache.read().unwrap().get(string) { + return identifier.clone(); + } + + let identifier = Identifier(Arc::new(string.to_string())); + + cache + .write() + .unwrap() + .insert(string.to_string(), identifier.clone()); + + identifier } pub fn as_str(&self) -> &str { diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index ae3eee1..df783b7 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -1,8 +1,6 @@ #[cfg(test)] mod tests; -use std::{cell::RefCell, collections::HashMap}; - use chumsky::{input::SpannedInput, pratt::*, prelude::*}; use crate::{ @@ -43,21 +41,8 @@ pub fn parser<'src>( let comment = select_ref! { Token::Comment(_) => {} }; - let identifiers: RefCell> = RefCell::new(HashMap::new()); let identifier = select! { - Token::Identifier(text) => { - let mut identifiers = identifiers.borrow_mut(); - - if let Some(identifier) = identifiers.get(&text) { - identifier.clone() - } else { - let new = Identifier::new(text); - - identifiers.insert(text, new.clone()); - - new - } - } + Token::Identifier(text) => Identifier::new(text), }; let positioned_identifier = identifier