feat: start debruijn conversion

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
rvcas 2022-06-03 00:36:21 -04:00
parent 83d6b5243e
commit f8edb5d519
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
5 changed files with 173 additions and 14 deletions

View File

@ -1,4 +1,4 @@
use crate::builtins::DefaultFunction; use crate::{builtins::DefaultFunction, debruijn::Converter};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Program<T> { pub struct Program<T> {
@ -6,6 +6,17 @@ pub struct Program<T> {
pub term: Term<T>, pub term: Term<T>,
} }
impl TryFrom<Program<Name>> for Program<NamedDeBruijn> {
type Error = String;
fn try_from(value: Program<Name>) -> Result<Self, Self::Error> {
Ok(Program::<NamedDeBruijn> {
version: value.version,
term: value.term.try_into()?,
})
}
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Term<T> { pub enum Term<T> {
// tag: 0 // tag: 0
@ -32,6 +43,22 @@ pub enum Term<T> {
Builtin(DefaultFunction), Builtin(DefaultFunction),
} }
impl TryFrom<Term<Name>> for Term<NamedDeBruijn> {
type Error = String;
fn try_from(
value: Term<Name>,
) -> Result<Self, <Term<NamedDeBruijn> as TryFrom<Term<Name>>>::Error> {
let mut converter = Converter::new();
let term = converter
.name_to_named_debruijn(value)
.map_err(|err| err.to_string())?;
Ok(term)
}
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Constant { pub enum Constant {
// tag: 0 // tag: 0
@ -51,14 +78,66 @@ pub enum Constant {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Name { pub struct Name {
pub text: String, pub text: String,
pub unique: isize, pub unique: Unique,
}
#[derive(Debug, Clone, PartialEq, Copy, Eq, Hash)]
pub struct Unique(isize);
impl Unique {
pub fn new(unique: isize) -> Self {
Unique(unique)
}
pub fn increment(&mut self) {
self.0 += 1;
}
}
impl From<isize> for Unique {
fn from(i: isize) -> Self {
Unique(i)
}
}
impl From<Unique> for isize {
fn from(d: Unique) -> Self {
d.0
}
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct NamedDeBruijn { pub struct NamedDeBruijn {
pub text: String, pub text: String,
pub index: isize, pub index: DeBruijn,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Copy)]
pub struct DeBruijn(isize); pub struct DeBruijn(u64);
impl From<u64> for DeBruijn {
fn from(i: u64) -> Self {
DeBruijn(i)
}
}
impl From<DeBruijn> for u64 {
fn from(d: DeBruijn) -> Self {
d.0
}
}
impl From<NamedDeBruijn> for DeBruijn {
fn from(n: NamedDeBruijn) -> Self {
n.index
}
}
impl From<DeBruijn> for NamedDeBruijn {
fn from(index: DeBruijn) -> Self {
NamedDeBruijn {
text: String::from("i"),
index,
}
}
}

View File

@ -0,0 +1,62 @@
use std::collections::HashMap;
use crate::ast::{DeBruijn, Name, NamedDeBruijn, Term, Unique};
struct Level(u64);
pub(crate) struct Converter {
current_level: Level,
levels: HashMap<Unique, Level>,
}
impl Converter {
pub(crate) fn new() -> Self {
Converter {
current_level: Level(0),
levels: HashMap::new(),
}
}
pub(crate) fn name_to_named_debruijn(
&mut self,
term: Term<Name>,
) -> anyhow::Result<Term<NamedDeBruijn>> {
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,
} => {
todo!()
}
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(crate) fn named_debruijn_to_name(&mut self, term: Term<NamedDeBruijn>) -> Term<Name> {
todo!()
}
fn get_index(&mut self, unique: Unique) -> anyhow::Result<DeBruijn> {
if let Some(found_level) = self.levels.get(&unique) {
let index = self.current_level.0 - found_level.0;
Ok(index.into())
} else {
anyhow::bail!("Free unique: {}", isize::from(unique));
}
}
}

View File

@ -7,7 +7,7 @@ use flat::{
}; };
use crate::{ use crate::{
ast::{Constant, Name, Program, Term}, ast::{Constant, Name, Program, Term, Unique},
builtins::DefaultFunction, builtins::DefaultFunction,
}; };
@ -183,6 +183,20 @@ impl<'b> Decode<'b> for Constant {
} }
} }
impl Encode for Unique {
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
isize::from(*self).encode(e)?;
Ok(())
}
}
impl<'b> Decode<'b> for Unique {
fn decode(d: &mut Decoder) -> Result<Self, String> {
Ok(isize::decode(d)?.into())
}
}
impl Encode for Name { impl Encode for Name {
fn encode(&self, e: &mut flat::en::Encoder) -> Result<(), String> { fn encode(&self, e: &mut flat::en::Encoder) -> Result<(), String> {
self.text.encode(e)?; self.text.encode(e)?;
@ -196,7 +210,7 @@ impl<'b> Decode<'b> for Name {
fn decode(d: &mut Decoder) -> Result<Self, String> { fn decode(d: &mut Decoder) -> Result<Self, String> {
Ok(Name { Ok(Name {
text: String::decode(d)?, text: String::decode(d)?,
unique: isize::decode(d)?, unique: Unique::decode(d)?,
}) })
} }
} }

View File

@ -1,5 +1,6 @@
pub mod ast; pub mod ast;
pub mod builtins; pub mod builtins;
mod debruijn;
mod flat; mod flat;
pub mod parser; pub mod parser;

View File

@ -12,13 +12,13 @@ use combine::{
}; };
use crate::{ use crate::{
ast::{Constant, Name, Program, Term}, ast::{Constant, Name, Program, Term, Unique},
builtins::DefaultFunction, builtins::DefaultFunction,
}; };
struct ParserState { struct ParserState {
identifiers: HashMap<String, isize>, identifiers: HashMap<String, Unique>,
current_unique: isize, current: Unique,
} }
type StateStream<Input> = state::Stream<Input, ParserState>; type StateStream<Input> = state::Stream<Input, ParserState>;
@ -27,17 +27,20 @@ impl ParserState {
fn new() -> Self { fn new() -> Self {
ParserState { ParserState {
identifiers: HashMap::new(), identifiers: HashMap::new(),
current_unique: 0, current: Unique::new(0),
} }
} }
fn intern(&mut self, text: &str) -> isize { fn intern(&mut self, text: &str) -> Unique {
if let Some(u) = self.identifiers.get(text) { if let Some(u) = self.identifiers.get(text) {
*u *u
} else { } else {
let unique = self.current_unique; let unique = self.current;
self.identifiers.insert(text.to_string(), unique); self.identifiers.insert(text.to_string(), unique);
self.current_unique += 1;
self.current.increment();
unique unique
} }
} }