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;
#[derive(Debug, Clone, PartialEq)]
pub struct Program {
pub struct Program<T> {
pub version: (usize, usize, usize),
pub term: Term,
pub term: Term<T>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Term {
pub enum Term<T> {
// tag: 0
Var(Name),
Var(T),
// tag: 1
Delay(Box<Term>),
Delay(Box<Term<T>>),
// tag: 2
Lambda {
parameter_name: Name,
body: Box<Term>,
parameter_name: T,
body: Box<Term<T>>,
},
// tag: 3
Apply {
function: Box<Term>,
argument: Box<Term>,
function: Box<Term<T>>,
argument: Box<Term<T>>,
},
// tag: 4
Constant(Constant),
// tag: 5
Force(Box<Term>),
Force(Box<Term<T>>),
// tag: 6
Error,
// tag: 7
@ -53,3 +53,12 @@ pub struct Name {
pub text: String,
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 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
// directly to call programs flat function
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> {
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> {
let version = (usize::decode(d)?, usize::decode(d)?, usize::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> {
match self {
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> {
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)?))),
2 => Ok(Term::Lambda {
parameter_name: Name::decode(d)?,
parameter_name: T::decode(d)?,
body: Box::new(Term::decode(d)?),
}),
3 => Ok(Term::Apply {
@ -255,11 +264,13 @@ pub fn decode_constant_tag(d: &mut Decoder) -> Result<u8, String> {
mod test {
use flat::Flat;
use crate::ast::Name;
use super::{Constant, Program, Term};
#[test]
fn flat_encode_integer() {
let program = Program {
let program = Program::<Name> {
version: (11, 22, 33),
term: Term::Constant(Constant::Integer(11)),
};
@ -283,7 +294,7 @@ mod test {
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)
}

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 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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -151,7 +151,7 @@ where
.with(skip_many1(space()))
.with((many1(alpha_num()), skip_many1(space()), term()))
.map_input(
|(parameter_name, _, term): (String, _, Term), input| Term::Lambda {
|(parameter_name, _, term): (String, _, Term<Name>), input| Term::Lambda {
parameter_name: Name {
unique: input.state.intern(&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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
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
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,