From 59a8f6477bdc3c8443cc9c1daf763528ef06d955 Mon Sep 17 00:00:00 2001 From: rvcas Date: Wed, 15 Jun 2022 20:12:12 -0400 Subject: [PATCH] feat: convet a named debruijn to a name --- crates/uplc/src/ast.rs | 10 ++++ crates/uplc/src/debruijn.rs | 80 +++++++++++++++++++++++++++---- crates/uplc/src/debruijn/bimap.rs | 32 +++++++++++++ 3 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 crates/uplc/src/debruijn/bimap.rs diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index 6344c6dc..4bbc3325 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -155,6 +155,10 @@ impl DeBruijn { pub fn new(index: usize) -> Self { DeBruijn(index) } + + pub fn inner(&self) -> usize { + self.0 + } } impl From for DeBruijn { @@ -169,6 +173,12 @@ impl From for usize { } } +impl Display for DeBruijn { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + impl From for DeBruijn { fn from(n: NamedDeBruijn) -> Self { n.index diff --git a/crates/uplc/src/debruijn.rs b/crates/uplc/src/debruijn.rs index 3216e9f4..dc968d0f 100644 --- a/crates/uplc/src/debruijn.rs +++ b/crates/uplc/src/debruijn.rs @@ -1,28 +1,32 @@ -use std::collections::HashMap; - use thiserror::Error; use crate::ast::{DeBruijn, FakeNamedDeBruijn, Name, NamedDeBruijn, Term, Unique}; -#[derive(Debug, Copy, Clone)] +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>, + levels: Vec, + current_unique: Unique, } impl Converter { pub fn new() -> Self { Converter { current_level: Level(0), - levels: vec![HashMap::new()], + levels: vec![bimap::BiMap::new()], + current_unique: Unique::new(0), } } @@ -111,9 +115,49 @@ impl Converter { pub fn named_debruijn_to_name( &mut self, - _term: Term, + term: Term, ) -> Result, Error> { - todo!() + 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 named_debruijn_to_debruijn(&mut self, term: Term) -> Term { @@ -234,16 +278,36 @@ impl Converter { 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 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(HashMap::new()); + self.levels.push(bimap::BiMap::new()); } fn end_scope(&mut self) { diff --git a/crates/uplc/src/debruijn/bimap.rs b/crates/uplc/src/debruijn/bimap.rs new file mode 100644 index 00000000..af506095 --- /dev/null +++ b/crates/uplc/src/debruijn/bimap.rs @@ -0,0 +1,32 @@ +use std::collections::HashMap; + +use crate::ast::Unique; + +use super::Level; + +pub struct BiMap { + left: HashMap, + right: HashMap, +} + +impl BiMap { + pub(super) fn new() -> Self { + BiMap { + right: HashMap::new(), + left: HashMap::new(), + } + } + + pub(super) fn insert(&mut self, unique: Unique, level: Level) { + self.left.insert(unique, level); + self.right.insert(level, unique); + } + + pub(super) fn get(&self, unique: &Unique) -> Option<&Level> { + self.left.get(unique) + } + + pub(super) fn get_right(&self, level: &Level) -> Option<&Unique> { + self.right.get(level) + } +}