feat: get program ready for debruijn

This commit is contained in:
rvcas 2022-06-02 21:39:09 -04:00
parent c7037ff8d9
commit 83d6b5243e
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
3 changed files with 51 additions and 31 deletions

View File

@ -1,31 +1,31 @@
use crate::builtins::DefaultFunction; use crate::builtins::DefaultFunction;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Program { pub struct Program<T> {
pub version: (usize, usize, usize), pub version: (usize, usize, usize),
pub term: Term, pub term: Term<T>,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Term { pub enum Term<T> {
// tag: 0 // tag: 0
Var(Name), Var(T),
// tag: 1 // tag: 1
Delay(Box<Term>), Delay(Box<Term<T>>),
// tag: 2 // tag: 2
Lambda { Lambda {
parameter_name: Name, parameter_name: T,
body: Box<Term>, body: Box<Term<T>>,
}, },
// tag: 3 // tag: 3
Apply { Apply {
function: Box<Term>, function: Box<Term<T>>,
argument: Box<Term>, argument: Box<Term<T>>,
}, },
// tag: 4 // tag: 4
Constant(Constant), Constant(Constant),
// tag: 5 // tag: 5
Force(Box<Term>), Force(Box<Term<T>>),
// tag: 6 // tag: 6
Error, Error,
// tag: 7 // tag: 7
@ -53,3 +53,12 @@ pub struct Name {
pub text: String, pub text: String,
pub unique: isize, pub unique: isize,
} }
#[derive(Debug, Clone, PartialEq)]
pub struct NamedDeBruijn {
pub text: String,
pub index: isize,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeBruijn(isize);

View File

@ -15,9 +15,12 @@ const BUILTIN_TAG_WIDTH: u32 = 7;
const CONST_TAG_WIDTH: u32 = 4; const CONST_TAG_WIDTH: u32 = 4;
const TERM_TAG_WIDTH: u32 = 4; const TERM_TAG_WIDTH: u32 = 4;
impl<'b> Flat<'b> for Program {} impl<'b, T> Flat<'b> for Program<T> where T: Encode + Decode<'b> {}
impl Program { impl<'b, T> Program<T>
where
T: Encode + Decode<'b>,
{
// convenient so that people don't need to depend on the flat crate // convenient so that people don't need to depend on the flat crate
// directly to call programs flat function // directly to call programs flat function
pub fn to_flat(&self) -> anyhow::Result<Vec<u8>> { pub fn to_flat(&self) -> anyhow::Result<Vec<u8>> {
@ -33,7 +36,7 @@ impl Program {
} }
} }
impl Encode for Program { impl<T: Encode> Encode for Program<T> {
fn encode(&self, e: &mut Encoder) -> Result<(), String> { fn encode(&self, e: &mut Encoder) -> Result<(), String> {
let (major, minor, patch) = self.version; let (major, minor, patch) = self.version;
@ -47,7 +50,10 @@ impl Encode for Program {
} }
} }
impl<'b> Decode<'b> for Program { impl<'b, T> Decode<'b> for Program<T>
where
T: Decode<'b>,
{
fn decode(d: &mut Decoder) -> Result<Self, String> { fn decode(d: &mut Decoder) -> Result<Self, String> {
let version = (usize::decode(d)?, usize::decode(d)?, usize::decode(d)?); let version = (usize::decode(d)?, usize::decode(d)?, usize::decode(d)?);
let term = Term::decode(d)?; let term = Term::decode(d)?;
@ -55,7 +61,7 @@ impl<'b> Decode<'b> for Program {
} }
} }
impl Encode for Term { impl<T: Encode> Encode for Term<T> {
fn encode(&self, e: &mut Encoder) -> Result<(), String> { fn encode(&self, e: &mut Encoder) -> Result<(), String> {
match self { match self {
Term::Var(name) => { Term::Var(name) => {
@ -104,13 +110,16 @@ impl Encode for Term {
} }
} }
impl<'b> Decode<'b> for Term { impl<'b, T> Decode<'b> for Term<T>
where
T: Decode<'b>,
{
fn decode(d: &mut Decoder) -> Result<Self, String> { fn decode(d: &mut Decoder) -> Result<Self, String> {
match decode_term_tag(d)? { match decode_term_tag(d)? {
0 => Ok(Term::Var(Name::decode(d)?)), 0 => Ok(Term::Var(T::decode(d)?)),
1 => Ok(Term::Delay(Box::new(Term::decode(d)?))), 1 => Ok(Term::Delay(Box::new(Term::decode(d)?))),
2 => Ok(Term::Lambda { 2 => Ok(Term::Lambda {
parameter_name: Name::decode(d)?, parameter_name: T::decode(d)?,
body: Box::new(Term::decode(d)?), body: Box::new(Term::decode(d)?),
}), }),
3 => Ok(Term::Apply { 3 => Ok(Term::Apply {
@ -255,11 +264,13 @@ pub fn decode_constant_tag(d: &mut Decoder) -> Result<u8, String> {
mod test { mod test {
use flat::Flat; use flat::Flat;
use crate::ast::Name;
use super::{Constant, Program, Term}; use super::{Constant, Program, Term};
#[test] #[test]
fn flat_encode_integer() { fn flat_encode_integer() {
let program = Program { let program = Program::<Name> {
version: (11, 22, 33), version: (11, 22, 33),
term: Term::Constant(Constant::Integer(11)), term: Term::Constant(Constant::Integer(11)),
}; };
@ -283,7 +294,7 @@ mod test {
term: Term::Constant(Constant::Integer(11)), term: Term::Constant(Constant::Integer(11)),
}; };
let actual_program: Program = Program::unflat(&flat_encoded).unwrap(); let actual_program: Program<Name> = Program::unflat(&flat_encoded).unwrap();
assert_eq!(actual_program, expected_program) assert_eq!(actual_program, expected_program)
} }

View File

@ -43,7 +43,7 @@ impl ParserState {
} }
} }
pub fn program(src: &str) -> anyhow::Result<Program> { pub fn program(src: &str) -> anyhow::Result<Program<Name>> {
let mut parser = program_(); let mut parser = program_();
let result = parser.parse(state::Stream { let result = parser.parse(state::Stream {
@ -57,7 +57,7 @@ pub fn program(src: &str) -> anyhow::Result<Program> {
} }
} }
fn program_<Input>() -> impl Parser<StateStream<Input>, Output = Program> fn program_<Input>() -> impl Parser<StateStream<Input>, Output = Program<Name>>
where 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>,
@ -93,7 +93,7 @@ where
) )
} }
fn term<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn term<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -109,7 +109,7 @@ where
)))) ))))
} }
fn delay<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn delay<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -124,7 +124,7 @@ where
) )
} }
fn force<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn force<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -139,7 +139,7 @@ where
) )
} }
fn lambda<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn lambda<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -151,7 +151,7 @@ where
.with(skip_many1(space())) .with(skip_many1(space()))
.with((many1(alpha_num()), skip_many1(space()), term())) .with((many1(alpha_num()), skip_many1(space()), term()))
.map_input( .map_input(
|(parameter_name, _, term): (String, _, Term), input| Term::Lambda { |(parameter_name, _, term): (String, _, Term<Name>), input| Term::Lambda {
parameter_name: Name { parameter_name: Name {
unique: input.state.intern(&parameter_name), unique: input.state.intern(&parameter_name),
text: parameter_name, text: parameter_name,
@ -162,7 +162,7 @@ where
) )
} }
fn apply<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn apply<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -177,7 +177,7 @@ where
) )
} }
fn builtin<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn builtin<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -194,7 +194,7 @@ where
) )
} }
fn error<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn error<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,
@ -208,7 +208,7 @@ where
) )
} }
fn constant<Input>() -> impl Parser<StateStream<Input>, Output = Term> fn constant<Input>() -> impl Parser<StateStream<Input>, Output = Term<Name>>
where 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>,