Skip to content

Instantly share code, notes, and snippets.

@Chriscbr
Created September 25, 2024 01:14
Show Gist options
  • Save Chriscbr/4552a1da8aec506c876538b4d719322c to your computer and use it in GitHub Desktop.
Save Chriscbr/4552a1da8aec506c876538b4d719322c to your computer and use it in GitHub Desktop.
use std::{collections::HashSet, rc::Rc};
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum Type {
Int,
String,
Boolean,
Array(Box<Type>),
Function(Vec<Type>, Box<Type>), // parameter types, return type
}
#[derive(Default)]
pub struct TypeInterner {
types: HashSet<Rc<Type>>,
}
impl TypeInterner {
pub fn new() -> Self {
Self {
types: HashSet::new(),
}
}
pub fn intern(&mut self, t: Type) -> Rc<Type> {
if let Some(existing) = self.types.get(&t) {
existing.clone()
} else {
let rc_type = Rc::new(t);
self.types.insert(rc_type.clone());
rc_type
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_intern() {
let mut interner = TypeInterner::new();
let t1 = interner.intern(Type::Int);
let t2 = interner.intern(Type::Int);
assert_eq!(t1, t2);
let t3 = interner.intern(Type::String);
assert_ne!(t1, t3);
let t4 = interner.intern(Type::Array(Box::new(Type::Int)));
assert_ne!(t1, t4);
let t5 = interner.intern(Type::Array(Box::new(Type::Int)));
assert_eq!(t4, t5);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment