From 9ed79984016a1e1423311670a2f913d21e6eaded Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 31 Dec 2021 17:00:51 +0100 Subject: [PATCH] fix string interning --- src/gc.rs | 29 +++++++++++++++++++++++++---- test.dil | 10 +++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/gc.rs b/src/gc.rs index 5e1efbd..e5019f9 100644 --- a/src/gc.rs +++ b/src/gc.rs @@ -74,10 +74,29 @@ enum HeapObjectKind { #[derive(Debug)] pub struct RtAlloc { - symbols: HashSet>, + symbols: HashSet, objects: LinkedList, } +#[derive(Debug)] +struct NonNullStrWrapper(NonNull); + +impl Hash for NonNullStrWrapper { + fn hash(&self, state: &mut H) { + // SAFETY: Assume the ptr is valid, same rules as `Gc` + unsafe { self.0.as_ref().hash(state) } + } +} + +impl PartialEq for NonNullStrWrapper { + fn eq(&self, other: &Self) -> bool { + // SAFETY: Assume the ptr is valid, same rules as `Gc` + unsafe { self.0.as_ref().eq(other.0.as_ref()) } + } +} + +impl Eq for NonNullStrWrapper {} + impl RtAlloc { /// # Safety /// Promise to not forget to mark any roots and to not deref `Gc` after you've dropped me 🥺 @@ -119,10 +138,12 @@ impl RtAlloc { pub fn intern_string(&mut self, str: &str) -> Symbol { let original_nonnull = NonNull::from(str); - if let Some(interned) = self.symbols.get(&original_nonnull) { - Symbol::new(Gc { ptr: *interned }) + if let Some(interned) = self.symbols.get(&NonNullStrWrapper(original_nonnull)) { + Symbol::new(Gc { ptr: interned.0 }) } else { - Symbol::new(self.alloc_str(str)) + let allocated = self.alloc_str(str); + self.symbols.insert(NonNullStrWrapper(allocated.ptr)); + Symbol::new(allocated) } } } diff --git a/test.dil b/test.dil index 818947d..400067c 100644 --- a/test.dil +++ b/test.dil @@ -1 +1,9 @@ -print "Hello World!"; \ No newline at end of file +let x = 5; +print x + 4; + +let test = x + 6 * 159353.004; +print test; + +if x > test { + print "lmao"; +} \ No newline at end of file