use std::{collections::HashMap, rc::Rc}; use crate::ast::{Name, Program, Term, Unique}; pub struct Interner { identifiers: HashMap, current: Unique, } impl Default for Interner { fn default() -> Self { Self::new() } } impl Interner { pub fn new() -> Self { Interner { identifiers: HashMap::new(), current: Unique::new(0), } } pub fn program(&mut self, program: &mut Program) { self.term(&mut program.term); } pub fn term(&mut self, term: &mut Term) { match term { Term::Var(name) => name.unique = self.intern(&name.text), Term::Delay(term) => self.term(Rc::make_mut(term)), Term::Lambda { parameter_name, body, } => { parameter_name.unique = self.intern(¶meter_name.text); self.term(Rc::make_mut(body)); } Term::Apply { function, argument } => { self.term(Rc::make_mut(function)); self.term(Rc::make_mut(argument)); } Term::Constant(_) => (), Term::Force(term) => self.term(Rc::make_mut(term)), Term::Error => (), Term::Builtin(_) => (), } } fn intern(&mut self, text: &str) -> Unique { if let Some(u) = self.identifiers.get(text) { *u } else { let unique = self.current; self.identifiers.insert(text.to_string(), unique); self.current.increment(); unique } } }