use thiserror::Error; use crate::ast::{DeBruijn, FakeNamedDeBruijn, Name, NamedDeBruijn, Term, Unique}; mod bimap; #[derive(Debug, Clone, PartialEq, Copy, Eq, Hash)] struct Level(usize); #[derive(Error, Debug)] pub enum Error { #[error("Free Unique `{0}`")] FreeUnique(Unique), #[error("Free Index `{0}`")] FreeIndex(DeBruijn), } pub struct Converter { current_level: Level, levels: Vec, current_unique: Unique, } impl Converter { pub fn new() -> Self { Converter { current_level: Level(0), levels: vec![bimap::BiMap::new()], current_unique: Unique::new(0), } } pub fn name_to_named_debruijn( &mut self, term: Term, ) -> Result, Error> { let converted_term = match term { Term::Var(Name { text, unique }) => Term::Var(NamedDeBruijn { text, index: self.get_index(unique)?, }), Term::Delay(term) => Term::Delay(Box::new(self.name_to_named_debruijn(*term)?)), Term::Lambda { parameter_name, body, } => { self.declare_unique(parameter_name.unique); let index = self.get_index(parameter_name.unique)?; let name = NamedDeBruijn { text: parameter_name.text, index, }; self.start_scope(); let body = self.name_to_named_debruijn(*body)?; self.end_scope(); self.remove_unique(parameter_name.unique); Term::Lambda { parameter_name: name, body: Box::new(body), } } Term::Apply { function, argument } => Term::Apply { function: Box::new(self.name_to_named_debruijn(*function)?), argument: Box::new(self.name_to_named_debruijn(*argument)?), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => Term::Force(Box::new(self.name_to_named_debruijn(*term)?)), Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), }; Ok(converted_term) } pub fn name_to_debruijn(&mut self, term: Term) -> Result, Error> { let converted_term = match term { Term::Var(Name { unique, .. }) => Term::Var(self.get_index(unique)?), Term::Delay(term) => Term::Delay(Box::new(self.name_to_debruijn(*term)?)), Term::Lambda { parameter_name, body, } => { self.declare_unique(parameter_name.unique); let name = self.get_index(parameter_name.unique)?; self.start_scope(); let body = self.name_to_debruijn(*body)?; self.end_scope(); self.remove_unique(parameter_name.unique); Term::Lambda { parameter_name: name, body: Box::new(body), } } Term::Apply { function, argument } => Term::Apply { function: Box::new(self.name_to_debruijn(*function)?), argument: Box::new(self.name_to_debruijn(*argument)?), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => Term::Force(Box::new(self.name_to_debruijn(*term)?)), Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), }; Ok(converted_term) } pub fn named_debruijn_to_name( &mut self, term: Term, ) -> Result, Error> { let converted_term = match term { Term::Var(NamedDeBruijn { text, index }) => Term::Var(Name { text, unique: self.get_unique(index)?, }), Term::Delay(term) => Term::Delay(Box::new(self.named_debruijn_to_name(*term)?)), Term::Lambda { parameter_name, body, } => { self.declare_binder(); let unique = self.get_unique(parameter_name.index)?; let name = Name { text: parameter_name.text, unique, }; self.start_scope(); let body = self.named_debruijn_to_name(*body)?; self.end_scope(); Term::Lambda { parameter_name: name, body: Box::new(body), } } Term::Apply { function, argument } => Term::Apply { function: Box::new(self.named_debruijn_to_name(*function)?), argument: Box::new(self.named_debruijn_to_name(*argument)?), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => Term::Force(Box::new(self.named_debruijn_to_name(*term)?)), Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), }; Ok(converted_term) } pub fn debruijn_to_name(&mut self, term: Term) -> Result, Error> { let converted_term = match term { Term::Var(index) => { let unique = self.get_unique(index)?; Term::Var(Name { text: format!("i_{}", unique), unique, }) } Term::Delay(term) => Term::Delay(Box::new(self.debruijn_to_name(*term)?)), Term::Lambda { parameter_name, body, } => { self.declare_binder(); let unique = self.get_unique(parameter_name)?; let name = Name { text: format!("i_{}", unique), unique, }; self.start_scope(); let body = self.debruijn_to_name(*body)?; self.end_scope(); Term::Lambda { parameter_name: name, body: Box::new(body), } } Term::Apply { function, argument } => Term::Apply { function: Box::new(self.debruijn_to_name(*function)?), argument: Box::new(self.debruijn_to_name(*argument)?), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => Term::Force(Box::new(self.debruijn_to_name(*term)?)), Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), }; Ok(converted_term) } pub fn named_debruijn_to_debruijn(&mut self, term: Term) -> Term { match term { Term::Var(name) => Term::Var(name.into()), Term::Delay(term) => Term::Delay(Box::new(self.named_debruijn_to_debruijn(*term))), Term::Lambda { parameter_name, body, } => Term::Lambda { parameter_name: parameter_name.into(), body: Box::new(self.named_debruijn_to_debruijn(*body)), }, Term::Apply { function, argument } => Term::Apply { function: Box::new(self.named_debruijn_to_debruijn(*function)), argument: Box::new(self.named_debruijn_to_debruijn(*argument)), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => Term::Force(Box::new(self.named_debruijn_to_debruijn(*term))), Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), } } pub fn debruijn_to_named_debruijn(&mut self, term: Term) -> Term { match term { Term::Var(name) => Term::Var(name.into()), Term::Delay(term) => Term::Delay(Box::new(self.debruijn_to_named_debruijn(*term))), Term::Lambda { parameter_name, body, } => Term::Lambda { parameter_name: parameter_name.into(), body: Box::new(self.debruijn_to_named_debruijn(*body)), }, Term::Apply { function, argument } => Term::Apply { function: Box::new(self.debruijn_to_named_debruijn(*function)), argument: Box::new(self.debruijn_to_named_debruijn(*argument)), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => Term::Force(Box::new(self.debruijn_to_named_debruijn(*term))), Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), } } pub fn fake_named_debruijn_to_named_debruijn( &mut self, term: Term, ) -> Term { match term { Term::Var(name) => Term::Var(name.into()), Term::Delay(term) => { Term::Delay(Box::new(self.fake_named_debruijn_to_named_debruijn(*term))) } Term::Lambda { parameter_name, body, } => Term::Lambda { parameter_name: parameter_name.into(), body: Box::new(self.fake_named_debruijn_to_named_debruijn(*body)), }, Term::Apply { function, argument } => Term::Apply { function: Box::new(self.fake_named_debruijn_to_named_debruijn(*function)), argument: Box::new(self.fake_named_debruijn_to_named_debruijn(*argument)), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => { Term::Force(Box::new(self.fake_named_debruijn_to_named_debruijn(*term))) } Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), } } pub fn named_debruijn_to_fake_named_debruijn( &mut self, term: Term, ) -> Term { match term { Term::Var(name) => Term::Var(name.into()), Term::Delay(term) => { Term::Delay(Box::new(self.named_debruijn_to_fake_named_debruijn(*term))) } Term::Lambda { parameter_name, body, } => Term::Lambda { parameter_name: parameter_name.into(), body: Box::new(self.named_debruijn_to_fake_named_debruijn(*body)), }, Term::Apply { function, argument } => Term::Apply { function: Box::new(self.named_debruijn_to_fake_named_debruijn(*function)), argument: Box::new(self.named_debruijn_to_fake_named_debruijn(*argument)), }, Term::Constant(constant) => Term::Constant(constant), Term::Force(term) => { Term::Force(Box::new(self.named_debruijn_to_fake_named_debruijn(*term))) } Term::Error => Term::Error, Term::Builtin(builtin) => Term::Builtin(builtin), } } fn get_index(&mut self, unique: Unique) -> Result { for scope in self.levels.iter().rev() { if let Some(found_level) = scope.get(&unique) { let index = self.current_level.0 - found_level.0; return Ok(index.into()); } } Err(Error::FreeUnique(unique)) } fn get_unique(&mut self, index: DeBruijn) -> Result { for scope in self.levels.iter().rev() { let index = Level(self.current_level.0 - index.inner()); if let Some(unique) = scope.get_right(&index) { return Ok(*unique); } } Err(Error::FreeIndex(index)) } fn declare_unique(&mut self, unique: Unique) { let scope = &mut self.levels[self.current_level.0]; scope.insert(unique, self.current_level); } fn remove_unique(&mut self, unique: Unique) { let scope = &mut self.levels[self.current_level.0]; scope.remove(unique, self.current_level); } fn declare_binder(&mut self) { let scope = &mut self.levels[self.current_level.0]; scope.insert(self.current_unique, self.current_level); self.current_unique.increment(); } fn start_scope(&mut self) { self.current_level = Level(self.current_level.0 + 1); self.levels.push(bimap::BiMap::new()); } fn end_scope(&mut self) { self.current_level = Level(self.current_level.0 - 1); self.levels.pop(); } }