feat: better errors for debruijn converter
This commit is contained in:
@@ -25,7 +25,7 @@ fn main() -> anyhow::Result<()> {
|
||||
|
||||
println!();
|
||||
|
||||
let program_nd: Program<NamedDeBruijn> = program.try_into().unwrap();
|
||||
let program_nd: Program<NamedDeBruijn> = program.try_into()?;
|
||||
|
||||
println!("\nNamed De Bruijn:");
|
||||
println!("{:#?}", program_nd);
|
||||
|
||||
@@ -12,3 +12,4 @@ flat = { path = "../flat" }
|
||||
hex = "0.4.3"
|
||||
strum = "0.24.0"
|
||||
strum_macros = "0.24.0"
|
||||
thiserror = "1.0.31"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
(program 11.22.33
|
||||
(lam x (lam x x))
|
||||
(lam x (lam x y))
|
||||
)
|
||||
@@ -1,4 +1,9 @@
|
||||
use crate::{builtins::DefaultFunction, debruijn::Converter};
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::{
|
||||
builtins::DefaultFunction,
|
||||
debruijn::{self, Converter},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Program<T> {
|
||||
@@ -79,6 +84,12 @@ impl From<Unique> for isize {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Unique {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct NamedDeBruijn {
|
||||
pub text: String,
|
||||
@@ -122,7 +133,7 @@ impl From<DeBruijn> for NamedDeBruijn {
|
||||
}
|
||||
|
||||
impl TryFrom<Program<Name>> for Program<NamedDeBruijn> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(value: Program<Name>) -> Result<Self, Self::Error> {
|
||||
Ok(Program::<NamedDeBruijn> {
|
||||
@@ -133,23 +144,19 @@ impl TryFrom<Program<Name>> for Program<NamedDeBruijn> {
|
||||
}
|
||||
|
||||
impl TryFrom<Term<Name>> for Term<NamedDeBruijn> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(
|
||||
value: Term<Name>,
|
||||
) -> Result<Self, <Term<NamedDeBruijn> as TryFrom<Term<Name>>>::Error> {
|
||||
fn try_from(value: Term<Name>) -> Result<Self, debruijn::Error> {
|
||||
let mut converter = Converter::new();
|
||||
|
||||
let term = converter
|
||||
.name_to_named_debruijn(value)
|
||||
.map_err(|err| err.to_string())?;
|
||||
let term = converter.name_to_named_debruijn(value)?;
|
||||
|
||||
Ok(term)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Program<Name>> for Program<DeBruijn> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(value: Program<Name>) -> Result<Self, Self::Error> {
|
||||
Ok(Program::<DeBruijn> {
|
||||
@@ -160,21 +167,19 @@ impl TryFrom<Program<Name>> for Program<DeBruijn> {
|
||||
}
|
||||
|
||||
impl TryFrom<Term<Name>> for Term<DeBruijn> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(value: Term<Name>) -> Result<Self, <Term<DeBruijn> as TryFrom<Term<Name>>>::Error> {
|
||||
fn try_from(value: Term<Name>) -> Result<Self, debruijn::Error> {
|
||||
let mut converter = Converter::new();
|
||||
|
||||
let term = converter
|
||||
.name_to_debruijn(value)
|
||||
.map_err(|err| err.to_string())?;
|
||||
let term = converter.name_to_debruijn(value)?;
|
||||
|
||||
Ok(term)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Program<NamedDeBruijn>> for Program<Name> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(value: Program<NamedDeBruijn>) -> Result<Self, Self::Error> {
|
||||
Ok(Program::<Name> {
|
||||
@@ -185,16 +190,12 @@ impl TryFrom<Program<NamedDeBruijn>> for Program<Name> {
|
||||
}
|
||||
|
||||
impl TryFrom<Term<NamedDeBruijn>> for Term<Name> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(
|
||||
value: Term<NamedDeBruijn>,
|
||||
) -> Result<Self, <Term<Name> as TryFrom<Term<NamedDeBruijn>>>::Error> {
|
||||
fn try_from(value: Term<NamedDeBruijn>) -> Result<Self, debruijn::Error> {
|
||||
let mut converter = Converter::new();
|
||||
|
||||
let term = converter
|
||||
.named_debruijn_to_name(value)
|
||||
.map_err(|err| err.to_string())?;
|
||||
let term = converter.named_debruijn_to_name(value)?;
|
||||
|
||||
Ok(term)
|
||||
}
|
||||
@@ -218,7 +219,7 @@ impl From<Term<NamedDeBruijn>> for Term<DeBruijn> {
|
||||
}
|
||||
|
||||
impl TryFrom<Program<DeBruijn>> for Program<Name> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(value: Program<DeBruijn>) -> Result<Self, Self::Error> {
|
||||
Ok(Program::<Name> {
|
||||
@@ -229,16 +230,12 @@ impl TryFrom<Program<DeBruijn>> for Program<Name> {
|
||||
}
|
||||
|
||||
impl TryFrom<Term<DeBruijn>> for Term<Name> {
|
||||
type Error = String;
|
||||
type Error = debruijn::Error;
|
||||
|
||||
fn try_from(
|
||||
value: Term<DeBruijn>,
|
||||
) -> Result<Self, <Term<Name> as TryFrom<Term<DeBruijn>>>::Error> {
|
||||
fn try_from(value: Term<DeBruijn>) -> Result<Self, debruijn::Error> {
|
||||
let mut converter = Converter::new();
|
||||
|
||||
let term = converter
|
||||
.debruijn_to_name(value)
|
||||
.map_err(|err| err.to_string())?;
|
||||
let term = converter.debruijn_to_name(value)?;
|
||||
|
||||
Ok(term)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::ast::{DeBruijn, Name, NamedDeBruijn, Term, Unique};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Level(usize);
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Free Unique: `{0}`")]
|
||||
FreeUnique(Unique),
|
||||
}
|
||||
|
||||
pub struct Converter {
|
||||
current_level: Level,
|
||||
levels: Vec<HashMap<Unique, Level>>,
|
||||
@@ -21,7 +29,7 @@ impl Converter {
|
||||
pub fn name_to_named_debruijn(
|
||||
&mut self,
|
||||
term: Term<Name>,
|
||||
) -> anyhow::Result<Term<NamedDeBruijn>> {
|
||||
) -> Result<Term<NamedDeBruijn>, Error> {
|
||||
let converted_term = match term {
|
||||
Term::Var(Name { text, unique }) => Term::Var(NamedDeBruijn {
|
||||
text,
|
||||
@@ -65,7 +73,7 @@ impl Converter {
|
||||
Ok(converted_term)
|
||||
}
|
||||
|
||||
pub fn name_to_debruijn(&mut self, term: Term<Name>) -> anyhow::Result<Term<DeBruijn>> {
|
||||
pub fn name_to_debruijn(&mut self, term: Term<Name>) -> Result<Term<DeBruijn>, 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)?)),
|
||||
@@ -104,7 +112,7 @@ impl Converter {
|
||||
pub fn named_debruijn_to_name(
|
||||
&mut self,
|
||||
_term: Term<NamedDeBruijn>,
|
||||
) -> anyhow::Result<Term<Name>> {
|
||||
) -> Result<Term<Name>, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -130,7 +138,7 @@ impl Converter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debruijn_to_name(&mut self, _term: Term<DeBruijn>) -> anyhow::Result<Term<Name>> {
|
||||
pub fn debruijn_to_name(&mut self, _term: Term<DeBruijn>) -> Result<Term<Name>, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -156,7 +164,7 @@ impl Converter {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_index(&mut self, unique: Unique) -> anyhow::Result<DeBruijn> {
|
||||
fn get_index(&mut self, unique: Unique) -> Result<DeBruijn, Error> {
|
||||
for scope in self.levels.iter().rev() {
|
||||
if let Some(found_level) = scope.get(&unique) {
|
||||
let index = self.current_level.0 - found_level.0;
|
||||
@@ -165,7 +173,7 @@ impl Converter {
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::bail!("Free unique: {}", isize::from(unique))
|
||||
Err(Error::FreeUnique(unique))
|
||||
}
|
||||
|
||||
fn declare_unique(&mut self, unique: Unique) {
|
||||
|
||||
Reference in New Issue
Block a user