feat: more debruijn stuff

This commit is contained in:
rvcas 2022-06-03 22:00:16 -04:00
parent f8edb5d519
commit 946937f945
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
5 changed files with 118 additions and 42 deletions

View File

@ -1,4 +1,7 @@
use uplc::parser; use uplc::{
ast::{NamedDeBruijn, Program},
parser,
};
use neptune::Cli; use neptune::Cli;
@ -13,13 +16,17 @@ fn main() -> anyhow::Result<()> {
let flat_bytes = program.to_flat()?; let flat_bytes = program.to_flat()?;
print!("flat bits: ");
for byte in flat_bytes { for byte in flat_bytes {
print!("{:08b} ", byte); print!("{:08b} ", byte);
} }
println!(); println!();
println!("{}", program.flat_hex()?); let program: Program<NamedDeBruijn> = program.try_into().unwrap();
println!("{:#?}", program);
Ok(()) Ok(())
} }

View File

@ -1,3 +1,3 @@
(program 11.22.33 (program 11.22.33
(con integer 11) (lam x x)
) )

View File

@ -6,17 +6,6 @@ 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
@ -43,22 +32,6 @@ 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
@ -141,3 +114,57 @@ impl From<DeBruijn> for NamedDeBruijn {
} }
} }
} }
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()?,
})
}
}
impl TryFrom<Program<NamedDeBruijn>> for Program<Name> {
type Error = String;
fn try_from(value: Program<NamedDeBruijn>) -> Result<Self, Self::Error> {
Ok(Program::<Name> {
version: value.version,
term: value.term.try_into()?,
})
}
}
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)
}
}
impl TryFrom<Term<NamedDeBruijn>> for Term<Name> {
type Error = String;
fn try_from(
value: Term<NamedDeBruijn>,
) -> Result<Self, <Term<Name> as TryFrom<Term<NamedDeBruijn>>>::Error> {
let mut converter = Converter::new();
let term = converter
.named_debruijn_to_name(value)
.map_err(|err| err.to_string())?;
Ok(term)
}
}

View File

@ -2,6 +2,7 @@ use std::collections::HashMap;
use crate::ast::{DeBruijn, Name, NamedDeBruijn, Term, Unique}; use crate::ast::{DeBruijn, Name, NamedDeBruijn, Term, Unique};
#[derive(Debug, Copy, Clone)]
struct Level(u64); struct Level(u64);
pub(crate) struct Converter { pub(crate) struct Converter {
@ -31,7 +32,21 @@ impl Converter {
parameter_name, parameter_name,
body, body,
} => { } => {
todo!() self.declare_unique(parameter_name.unique);
let index = self.get_index(parameter_name.unique)?;
let name = NamedDeBruijn {
text: parameter_name.text,
index,
};
self.with_scope();
Term::Lambda {
parameter_name: name,
body: Box::new(self.name_to_named_debruijn(*body)?),
}
} }
Term::Apply { function, argument } => Term::Apply { Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.name_to_named_debruijn(*function)?), function: Box::new(self.name_to_named_debruijn(*function)?),
@ -46,7 +61,10 @@ impl Converter {
Ok(converted_term) Ok(converted_term)
} }
pub(crate) fn named_debruijn_to_name(&mut self, term: Term<NamedDeBruijn>) -> Term<Name> { pub(crate) fn named_debruijn_to_name(
&mut self,
_term: Term<NamedDeBruijn>,
) -> anyhow::Result<Term<Name>> {
todo!() todo!()
} }
@ -59,4 +77,12 @@ impl Converter {
anyhow::bail!("Free unique: {}", isize::from(unique)); anyhow::bail!("Free unique: {}", isize::from(unique));
} }
} }
fn declare_unique(&mut self, unique: Unique) {
self.levels.insert(unique, self.current_level);
}
fn with_scope(&mut self) {
self.current_level = Level(self.current_level.0 + 1);
}
} }

View File

@ -102,6 +102,7 @@ where
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
opaque!(no_partial(choice(( opaque!(no_partial(choice((
attempt(var()),
attempt(delay()), attempt(delay()),
attempt(lambda()), attempt(lambda()),
attempt(apply()), attempt(apply()),
@ -112,6 +113,21 @@ where
)))) ))))
} }
fn var<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
(many1(alpha_num()), spaces()).map_input(
|(text, _): (String, _), input: &mut StateStream<Input>| {
Term::Var(Name {
unique: input.state.intern(&text),
text,
})
},
)
}
fn delay<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>> fn delay<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
@ -147,21 +163,21 @@ where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
let name = many1(alpha_num()).map_input(|text: String, input: &mut StateStream<Input>| Name {
unique: input.state.intern(&text),
text,
});
between( between(
token('('), token('('),
token(')'), token(')'),
string("lam") string("lam")
.with(skip_many1(space())) .with(skip_many1(space()))
.with((many1(alpha_num()), skip_many1(space()), term())) .with((name, skip_many1(space()), term()))
.map_input( .map(|(parameter_name, _, term)| Term::Lambda {
|(parameter_name, _, term): (String, _, Term<Name>), input| Term::Lambda { parameter_name,
parameter_name: Name {
unique: input.state.intern(&parameter_name),
text: parameter_name,
},
body: Box::new(term), body: Box::new(term),
}, }),
),
) )
} }