feat: get program ready for debruijn
This commit is contained in:
parent
c7037ff8d9
commit
83d6b5243e
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(¶meter_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>,
|
||||
|
|
Loading…
Reference in New Issue