feat: start debruijn conversion
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
parent
83d6b5243e
commit
f8edb5d519
|
@ -1,4 +1,4 @@
|
|||
use crate::builtins::DefaultFunction;
|
||||
use crate::{builtins::DefaultFunction, debruijn::Converter};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Program<T> {
|
||||
|
@ -6,6 +6,17 @@ pub struct Program<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)]
|
||||
pub enum Term<T> {
|
||||
// tag: 0
|
||||
|
@ -32,6 +43,22 @@ pub enum Term<T> {
|
|||
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)]
|
||||
pub enum Constant {
|
||||
// tag: 0
|
||||
|
@ -51,14 +78,66 @@ pub enum Constant {
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Name {
|
||||
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)]
|
||||
pub struct NamedDeBruijn {
|
||||
pub text: String,
|
||||
pub index: isize,
|
||||
pub index: DeBruijn,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct DeBruijn(isize);
|
||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ use flat::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
ast::{Constant, Name, Program, Term},
|
||||
ast::{Constant, Name, Program, Term, Unique},
|
||||
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 {
|
||||
fn encode(&self, e: &mut flat::en::Encoder) -> Result<(), String> {
|
||||
self.text.encode(e)?;
|
||||
|
@ -196,7 +210,7 @@ impl<'b> Decode<'b> for Name {
|
|||
fn decode(d: &mut Decoder) -> Result<Self, String> {
|
||||
Ok(Name {
|
||||
text: String::decode(d)?,
|
||||
unique: isize::decode(d)?,
|
||||
unique: Unique::decode(d)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub mod ast;
|
||||
pub mod builtins;
|
||||
mod debruijn;
|
||||
mod flat;
|
||||
pub mod parser;
|
||||
|
||||
|
|
|
@ -12,13 +12,13 @@ use combine::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
ast::{Constant, Name, Program, Term},
|
||||
ast::{Constant, Name, Program, Term, Unique},
|
||||
builtins::DefaultFunction,
|
||||
};
|
||||
|
||||
struct ParserState {
|
||||
identifiers: HashMap<String, isize>,
|
||||
current_unique: isize,
|
||||
identifiers: HashMap<String, Unique>,
|
||||
current: Unique,
|
||||
}
|
||||
|
||||
type StateStream<Input> = state::Stream<Input, ParserState>;
|
||||
|
@ -27,17 +27,20 @@ impl ParserState {
|
|||
fn new() -> Self {
|
||||
ParserState {
|
||||
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) {
|
||||
*u
|
||||
} else {
|
||||
let unique = self.current_unique;
|
||||
let unique = self.current;
|
||||
|
||||
self.identifiers.insert(text.to_string(), unique);
|
||||
self.current_unique += 1;
|
||||
|
||||
self.current.increment();
|
||||
|
||||
unique
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue