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