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)]
|
#[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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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::{
|
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)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue