no more FlatAtoms
This commit is contained in:
parent
9c910b8076
commit
1c91b113fb
7 changed files with 105 additions and 603 deletions
|
@ -23,17 +23,15 @@ use serde::{
|
|||
};
|
||||
use strum::EnumDiscriminants;
|
||||
use thiserror::Error;
|
||||
use utils::{inflate, InflateError};
|
||||
|
||||
mod de;
|
||||
mod lex;
|
||||
mod utils;
|
||||
pub use de::*;
|
||||
|
||||
use super::Expression as Instruction;
|
||||
|
||||
#[derive(Deref, From, Default)]
|
||||
#[cfg_attr(debug_assertions, derive(Serialize, Debug))]
|
||||
#[cfg_attr(debug_assertions, derive(Serialize, Debug, PartialEq))]
|
||||
pub struct Atoms(Vec<Atom>);
|
||||
|
||||
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
||||
|
@ -43,12 +41,21 @@ pub enum Atom {
|
|||
StartHere,
|
||||
Modifier(Modifier),
|
||||
QuickModifier(QuickModifier),
|
||||
Loop(NonZeroU8, Vec<Atom>),
|
||||
Tuple(Vec<Atom>),
|
||||
Slope(SlopeModifier, Instruction, Vec<Atom>),
|
||||
Loop(NonZeroU8, Atoms),
|
||||
Tuple(Atoms),
|
||||
Slope(SlopeModifier, Instruction, Atoms),
|
||||
Comment,
|
||||
}
|
||||
|
||||
impl Clone for Atom {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Self::Rest => Self::Rest,
|
||||
_ => unimplemented!("variant can't be cloned right now"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
impl Serialize for Atom {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -59,37 +66,6 @@ impl Serialize for Atom {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
||||
pub(super) enum FlatAtom {
|
||||
Note(u8),
|
||||
Rest,
|
||||
StartHere,
|
||||
Modifier(Modifier),
|
||||
QuickModifier(QuickModifier),
|
||||
LoopStarts(NonZeroU8),
|
||||
LoopEnds,
|
||||
TupleStarts,
|
||||
TupleEnds,
|
||||
SlopeStarts(SlopeModifier, Instruction),
|
||||
SlopeEnds,
|
||||
Comment,
|
||||
}
|
||||
|
||||
impl Clone for FlatAtom {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Self::Rest => Self::Rest,
|
||||
Self::Comment => Self::Comment,
|
||||
Self::LoopEnds => Self::LoopEnds,
|
||||
Self::SlopeEnds => Self::SlopeEnds,
|
||||
Self::StartHere => Self::StartHere,
|
||||
Self::TupleEnds => Self::TupleEnds,
|
||||
Self::TupleStarts => Self::TupleStarts,
|
||||
_ => unimplemented!("variant can't be cloned"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, ModifierParser)]
|
||||
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
||||
pub enum Modifier {
|
||||
|
|
|
@ -22,18 +22,7 @@ use thiserror::Error;
|
|||
|
||||
use crate::bng::score::lex::lexer::root;
|
||||
|
||||
use super::{
|
||||
utils::{inflate, InflateError},
|
||||
Atoms, FlatAtom,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum AtomsSerializeError {
|
||||
#[error("sheet parsing error:\n{0}")]
|
||||
Parsing(String),
|
||||
#[error("sheet semantics: {0}")]
|
||||
Inflation(#[from] InflateError),
|
||||
}
|
||||
use super::{Atom, Atoms};
|
||||
|
||||
impl<'de> Deserialize<'de> for Atoms {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
|
@ -55,16 +44,10 @@ impl<'de> Deserialize<'de> for Atoms {
|
|||
if sheet.is_empty() {
|
||||
Ok(Default::default())
|
||||
} else {
|
||||
root(&sheet, ¬es)
|
||||
all_consuming(root(¬es))(&sheet)
|
||||
.map_err(|e| pretty_verbose_err.curry().call1(sheet.as_str()).call1(e))
|
||||
.map_err(AtomsSerializeError::Parsing)
|
||||
.map_err(de::Error::custom)
|
||||
.and_then(|(_, v)| {
|
||||
inflate(v)
|
||||
.map_err(AtomsSerializeError::from)
|
||||
.map_err(de::Error::custom)
|
||||
})
|
||||
.map(Atoms)
|
||||
.map(|(i, r)| r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier};
|
||||
use super::{Atom, Modifier, QuickModifier, SlopeModifier};
|
||||
|
||||
pub(super) mod lexer;
|
||||
|
||||
|
|
|
@ -16,12 +16,14 @@ use nom::{
|
|||
Err, IResult, Parser,
|
||||
};
|
||||
|
||||
use crate::bng::score::Atoms;
|
||||
|
||||
use super::{
|
||||
super::super::Expression as Instruction, Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier,
|
||||
super::super::Expression as Instruction, Atom, Modifier, QuickModifier, SlopeModifier,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
// #[cfg(test)]
|
||||
// mod tests;
|
||||
|
||||
fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec<char>, E>
|
||||
where
|
||||
|
@ -30,123 +32,121 @@ where
|
|||
context("yml white space", many0(one_of(" \t\r\n")))
|
||||
}
|
||||
|
||||
pub fn root<'a, E>(i: &'a str, notes: &'a str) -> IResult<&'a str, Vec<FlatAtom>, E>
|
||||
pub fn root<'a, E>(notes: &'a str) -> impl Parser<&'a str, Atoms, E>
|
||||
where
|
||||
E: ParseError<&'a str>
|
||||
+ ContextError<&'a str>
|
||||
+ FromExternalError<&'a str, TryFromIntError>
|
||||
+ FromExternalError<&'a str, E>,
|
||||
{
|
||||
all_consuming(terminated(
|
||||
terminated(
|
||||
many1(preceded(maybe_yml_str_space(), atom(notes))),
|
||||
maybe_yml_str_space(),
|
||||
))(i)
|
||||
)
|
||||
.map(Atoms)
|
||||
}
|
||||
|
||||
fn note<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E>
|
||||
fn note<'a, E>(notes: &'a str) -> impl Parser<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str> + FromExternalError<&'a str, TryFromIntError>,
|
||||
{
|
||||
context(
|
||||
"note",
|
||||
map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note),
|
||||
map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from),
|
||||
)
|
||||
.map(Atom::Note)
|
||||
}
|
||||
|
||||
fn rest<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn rest<'a, E>(i: &'a str) -> IResult<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
context("rest", value(FlatAtom::Rest, char(Atom::REST)))(i)
|
||||
value(Atom::Rest, context("rest", char(Atom::REST))).parse(i)
|
||||
}
|
||||
|
||||
fn start_here<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn start_here<'a, E>(i: &'a str) -> IResult<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
context(
|
||||
"start_here",
|
||||
value(FlatAtom::StartHere, char(Atom::START_HERE)),
|
||||
)(i)
|
||||
value(
|
||||
Atom::StartHere,
|
||||
context("start_here", char(Atom::START_HERE)),
|
||||
)
|
||||
.parse(i)
|
||||
}
|
||||
|
||||
fn modifier<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn modifier<'a, E>(i: &'a str) -> IResult<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
use super::super::modifier;
|
||||
context(
|
||||
"modifier",
|
||||
preceded(char(Atom::MODIFIER), modifier).map(FlatAtom::Modifier),
|
||||
)(i)
|
||||
context("modifier", preceded(char(Atom::MODIFIER), modifier))
|
||||
.map(Atom::Modifier)
|
||||
.parse(i)
|
||||
}
|
||||
|
||||
fn quick_modifier<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn quick_modifier<'a, E>(i: &'a str) -> IResult<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
use super::super::quick_modifier;
|
||||
context(
|
||||
"quick_modifier",
|
||||
quick_modifier.map(FlatAtom::QuickModifier),
|
||||
)(i)
|
||||
context("quick_modifier", quick_modifier)
|
||||
.map(Atom::QuickModifier)
|
||||
.parse(i)
|
||||
}
|
||||
|
||||
fn loop_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn r#loop<'a, E>(notes: &'a str) -> impl Parser<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
E: ParseError<&'a str>
|
||||
+ ContextError<&'a str>
|
||||
+ FromExternalError<&'a str, TryFromIntError>
|
||||
+ FromExternalError<&'a str, E>,
|
||||
{
|
||||
context(
|
||||
"loop_starts",
|
||||
preceded(
|
||||
"loop",
|
||||
delimited(
|
||||
char(Atom::LOOP.0),
|
||||
map_opt(opt(u8), |n| {
|
||||
if let Some(n) = n {
|
||||
NonZeroU8::new(n)
|
||||
} else {
|
||||
unsafe { Some(NonZeroU8::new_unchecked(2)) }
|
||||
}
|
||||
}),
|
||||
)
|
||||
.map(FlatAtom::LoopStarts),
|
||||
)(i)
|
||||
pair(
|
||||
map_opt(opt(u8), |n| {
|
||||
if let Some(n) = n {
|
||||
NonZeroU8::new(n)
|
||||
} else {
|
||||
unsafe { Some(NonZeroU8::new_unchecked(2)) }
|
||||
}
|
||||
}),
|
||||
root(notes),
|
||||
),
|
||||
char(Atom::LOOP.1),
|
||||
),
|
||||
)
|
||||
.map(|(n, v)| Atom::Loop(n, v))
|
||||
}
|
||||
|
||||
fn loop_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn tuple<'a, E>(notes: &'a str) -> impl Parser<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
context("loop_ends", value(FlatAtom::LoopEnds, char(Atom::LOOP.1)))(i)
|
||||
}
|
||||
|
||||
fn tuple_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
E: ParseError<&'a str>
|
||||
+ ContextError<&'a str>
|
||||
+ FromExternalError<&'a str, TryFromIntError>
|
||||
+ FromExternalError<&'a str, E>,
|
||||
{
|
||||
context(
|
||||
"tuple_starts",
|
||||
value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)),
|
||||
)(i)
|
||||
"tuple",
|
||||
delimited(char(Atom::TUPLE.0), root(notes), char(Atom::TUPLE.1)),
|
||||
)
|
||||
.map(Atom::Tuple)
|
||||
}
|
||||
|
||||
fn tuple_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn slope<'a, E>(notes: &'a str) -> impl Parser<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
context(
|
||||
"tuple_ends",
|
||||
value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)),
|
||||
)(i)
|
||||
}
|
||||
|
||||
fn slope_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str> + FromExternalError<&'a str, E>,
|
||||
E: ParseError<&'a str>
|
||||
+ ContextError<&'a str>
|
||||
+ FromExternalError<&'a str, TryFromIntError>
|
||||
+ FromExternalError<&'a str, E>,
|
||||
{
|
||||
use super::super::slope_modifier;
|
||||
context(
|
||||
"slope_starts",
|
||||
terminated(
|
||||
separated_pair(
|
||||
preceded(
|
||||
char(Atom::SLOPE.0),
|
||||
separated_pair(
|
||||
|
@ -159,29 +159,20 @@ where
|
|||
),
|
||||
),
|
||||
char(','),
|
||||
)
|
||||
.map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)),
|
||||
)(i)
|
||||
root(notes),
|
||||
),
|
||||
)
|
||||
.map(|((sm, i), v)| Atom::Slope(sm, i, v))
|
||||
}
|
||||
|
||||
fn slope_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
context(
|
||||
"slope_ends",
|
||||
value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)),
|
||||
)(i)
|
||||
}
|
||||
|
||||
fn comment<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E>
|
||||
fn comment<'a, E>(i: &'a str) -> IResult<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str> + ContextError<&'a str>,
|
||||
{
|
||||
context(
|
||||
"comment",
|
||||
value(
|
||||
FlatAtom::Comment,
|
||||
Atom::Comment,
|
||||
delimited(
|
||||
char(Atom::COMMENT.0),
|
||||
take_till(|c| c == Atom::COMMENT.1),
|
||||
|
@ -191,7 +182,7 @@ where
|
|||
)(i)
|
||||
}
|
||||
|
||||
fn atom<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E>
|
||||
fn atom<'a, E>(notes: &'a str) -> impl Parser<&'a str, Atom, E>
|
||||
where
|
||||
E: ParseError<&'a str>
|
||||
+ ContextError<&'a str>
|
||||
|
@ -206,12 +197,9 @@ where
|
|||
start_here,
|
||||
modifier,
|
||||
quick_modifier,
|
||||
loop_starts,
|
||||
loop_ends,
|
||||
tuple_starts,
|
||||
tuple_ends,
|
||||
slope_starts,
|
||||
slope_ends,
|
||||
r#loop(¬es),
|
||||
tuple(¬es),
|
||||
slope(¬es),
|
||||
comment,
|
||||
)),
|
||||
)
|
||||
|
|
|
@ -15,7 +15,7 @@ mod flat_atom {
|
|||
use nom::Parser;
|
||||
|
||||
use super::super::{
|
||||
super::super::super::Expression as Instruction, super::UP, atom, Atom, FlatAtom, Modifier,
|
||||
super::super::super::Expression as Instruction, super::UP, atom, Atom, Modifier,
|
||||
QuickModifier, SlopeModifier,
|
||||
};
|
||||
use super::*;
|
||||
|
@ -34,7 +34,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn note() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::Note(2))),
|
||||
Ok((SAMPLE_STR, Atom::Note(2))),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!('c', SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn rest() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::Rest)),
|
||||
Ok((SAMPLE_STR, Atom::Rest)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::REST, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn start_here() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::StartHere)),
|
||||
Ok((SAMPLE_STR, Atom::StartHere)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::START_HERE, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ mod flat_atom {
|
|||
assert_eq!(
|
||||
Ok((
|
||||
SAMPLE_STR,
|
||||
FlatAtom::Modifier(Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) }))
|
||||
Atom::Modifier(Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) }))
|
||||
)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(
|
||||
Atom::MODIFIER,
|
||||
|
@ -74,10 +74,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn quick_modifier() {
|
||||
assert_eq!(
|
||||
Ok((
|
||||
SAMPLE_STR,
|
||||
FlatAtom::QuickModifier(QuickModifier::Length(UP))
|
||||
)),
|
||||
Ok((SAMPLE_STR, Atom::QuickModifier(QuickModifier::Length(UP)))),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(QuickModifier::LENGTH.0, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -87,14 +84,14 @@ mod flat_atom {
|
|||
assert_eq!(
|
||||
Ok((
|
||||
SAMPLE_STR,
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) })
|
||||
Atom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) })
|
||||
)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::LOOP.0, 3u8, SAMPLE_STR))
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((
|
||||
SAMPLE_STR,
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) })
|
||||
Atom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) })
|
||||
)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::LOOP.0, SAMPLE_STR))
|
||||
);
|
||||
|
@ -110,7 +107,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn loop_ends() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::LoopEnds)),
|
||||
Ok((SAMPLE_STR, Atom::LoopEnds)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::LOOP.1, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -118,7 +115,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn tuple_starts() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::TupleStarts)),
|
||||
Ok((SAMPLE_STR, Atom::TupleStarts)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::TUPLE.0, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -126,7 +123,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn tuple_ends() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::TupleEnds)),
|
||||
Ok((SAMPLE_STR, Atom::TupleEnds)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::TUPLE.1, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -136,7 +133,7 @@ mod flat_atom {
|
|||
assert_eq!(
|
||||
Ok((
|
||||
SAMPLE_STR,
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Note, FASTEVAL_INSTRUCTION.parse().unwrap())
|
||||
Atom::SlopeStarts(SlopeModifier::Note, FASTEVAL_INSTRUCTION.parse().unwrap())
|
||||
)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(
|
||||
Atom::SLOPE.0,
|
||||
|
@ -152,7 +149,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn slope_ends() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::SlopeEnds)),
|
||||
Ok((SAMPLE_STR, Atom::SlopeEnds)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(Atom::SLOPE.1, SAMPLE_STR))
|
||||
)
|
||||
}
|
||||
|
@ -160,7 +157,7 @@ mod flat_atom {
|
|||
#[test]
|
||||
fn comment() {
|
||||
assert_eq!(
|
||||
Ok((SAMPLE_STR, FlatAtom::Comment)),
|
||||
Ok((SAMPLE_STR, Atom::Comment)),
|
||||
atom::<Error<&str>>("abcdefg").parse(concatcp!(
|
||||
Atom::COMMENT.0,
|
||||
"hi I'm a little pony",
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
use super::*;
|
||||
use strum::Display;
|
||||
use thiserror::Error;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[derive(Debug, EnumDiscriminants)]
|
||||
#[strum_discriminants(derive(Display))]
|
||||
pub enum Wrapper {
|
||||
Loop(NonZeroU8),
|
||||
Tuple,
|
||||
Slope(SlopeModifier, Instruction),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub enum InflateError {
|
||||
#[error("misplaced {0} end symbol")]
|
||||
MismatchedEnd(WrapperDiscriminants),
|
||||
}
|
||||
|
||||
pub fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Result<Vec<Atom>, InflateError> {
|
||||
type Error = InflateError;
|
||||
let mut result = Vec::with_capacity(flat_atoms.len());
|
||||
let mut loop_stack: Vec<Vec<Atom>> = Vec::new();
|
||||
let mut tuple_stack: Vec<Vec<Atom>> = Vec::new();
|
||||
let mut slope_stack: Vec<Vec<Atom>> = Vec::new();
|
||||
let mut stack_history: Vec<Wrapper> = Vec::new();
|
||||
for mut atom in flat_atoms.into_iter() {
|
||||
#[cfg(test)]
|
||||
{
|
||||
dbg!(&atom);
|
||||
dbg!(&loop_stack);
|
||||
dbg!(&tuple_stack);
|
||||
dbg!(&slope_stack);
|
||||
dbg!(&stack_history);
|
||||
}
|
||||
match stack_history.last().map(WrapperDiscriminants::from) {
|
||||
Some(WrapperDiscriminants::Loop) => match atom {
|
||||
FlatAtom::Note(n) => {
|
||||
unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Note(n))
|
||||
}
|
||||
FlatAtom::Rest => {
|
||||
unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Rest)
|
||||
}
|
||||
FlatAtom::StartHere => {
|
||||
unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::StartHere)
|
||||
}
|
||||
FlatAtom::Modifier(m) => {
|
||||
unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Modifier(m))
|
||||
}
|
||||
FlatAtom::QuickModifier(q) => {
|
||||
unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::QuickModifier(q))
|
||||
}
|
||||
FlatAtom::LoopStarts(n) => {
|
||||
loop_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Loop(n));
|
||||
}
|
||||
FlatAtom::LoopEnds => {
|
||||
let popped = unsafe { loop_stack.pop().unwrap_unchecked() };
|
||||
if stack_history.len() > 1 {
|
||||
match WrapperDiscriminants::from(
|
||||
stack_history.get(stack_history.len() - 2).unwrap(),
|
||||
) {
|
||||
WrapperDiscriminants::Loop => &mut loop_stack,
|
||||
WrapperDiscriminants::Tuple => &mut tuple_stack,
|
||||
WrapperDiscriminants::Slope => &mut slope_stack,
|
||||
}
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.push(Atom::Loop(
|
||||
match stack_history.pop().unwrap() {
|
||||
Wrapper::Loop(n) => n,
|
||||
_ => unreachable!("this one is proven to be a loop"),
|
||||
},
|
||||
popped,
|
||||
))
|
||||
} else {
|
||||
result.push(Atom::Loop(
|
||||
match stack_history.pop().unwrap() {
|
||||
Wrapper::Loop(n) => n,
|
||||
_ => unreachable!("this one is proven to be a loop"),
|
||||
},
|
||||
popped,
|
||||
))
|
||||
}
|
||||
}
|
||||
FlatAtom::TupleStarts => {
|
||||
tuple_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Tuple);
|
||||
}
|
||||
FlatAtom::TupleEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple));
|
||||
}
|
||||
FlatAtom::SlopeStarts(s, i) => {
|
||||
slope_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Slope(s, i));
|
||||
}
|
||||
FlatAtom::SlopeEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope));
|
||||
}
|
||||
FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment),
|
||||
},
|
||||
Some(WrapperDiscriminants::Tuple) => match atom {
|
||||
FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)),
|
||||
FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest),
|
||||
FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere),
|
||||
FlatAtom::Modifier(m) => tuple_stack.last_mut().unwrap().push(Atom::Modifier(m)),
|
||||
FlatAtom::QuickModifier(q) => {
|
||||
tuple_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
|
||||
}
|
||||
FlatAtom::LoopStarts(n) => {
|
||||
loop_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Loop(n));
|
||||
}
|
||||
FlatAtom::LoopEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop));
|
||||
}
|
||||
FlatAtom::TupleStarts => {
|
||||
tuple_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Tuple);
|
||||
}
|
||||
FlatAtom::TupleEnds => {
|
||||
let popped = tuple_stack.pop().unwrap();
|
||||
if stack_history.len() > 1 {
|
||||
match WrapperDiscriminants::from(
|
||||
stack_history.get(stack_history.len() - 2).unwrap(),
|
||||
) {
|
||||
WrapperDiscriminants::Loop => &mut loop_stack,
|
||||
WrapperDiscriminants::Tuple => &mut tuple_stack,
|
||||
WrapperDiscriminants::Slope => &mut slope_stack,
|
||||
}
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.push({
|
||||
stack_history.pop();
|
||||
Atom::Tuple(popped)
|
||||
})
|
||||
} else {
|
||||
result.push(Atom::Tuple(popped))
|
||||
}
|
||||
}
|
||||
FlatAtom::SlopeStarts(s, i) => {
|
||||
slope_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Slope(s, i));
|
||||
}
|
||||
FlatAtom::SlopeEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope));
|
||||
}
|
||||
FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment),
|
||||
},
|
||||
Some(WrapperDiscriminants::Slope) => match atom {
|
||||
FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)),
|
||||
FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest),
|
||||
FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere),
|
||||
FlatAtom::Modifier(m) => slope_stack.last_mut().unwrap().push(Atom::Modifier(m)),
|
||||
FlatAtom::QuickModifier(q) => {
|
||||
slope_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
|
||||
}
|
||||
FlatAtom::LoopStarts(n) => {
|
||||
loop_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Loop(n));
|
||||
}
|
||||
FlatAtom::LoopEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop));
|
||||
}
|
||||
FlatAtom::TupleStarts => {
|
||||
tuple_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Tuple);
|
||||
}
|
||||
FlatAtom::TupleEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple));
|
||||
}
|
||||
FlatAtom::SlopeStarts(s, i) => {
|
||||
slope_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Slope(s, i));
|
||||
}
|
||||
FlatAtom::SlopeEnds => {
|
||||
let popped = slope_stack.pop().unwrap();
|
||||
if stack_history.len() > 1 {
|
||||
match WrapperDiscriminants::from(
|
||||
stack_history.get(stack_history.len() - 2).unwrap(),
|
||||
) {
|
||||
WrapperDiscriminants::Loop => &mut loop_stack,
|
||||
WrapperDiscriminants::Tuple => &mut tuple_stack,
|
||||
WrapperDiscriminants::Slope => &mut slope_stack,
|
||||
}
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.push(match stack_history.pop().unwrap() {
|
||||
Wrapper::Slope(m, i) => Atom::Slope(m, i, popped),
|
||||
_ => unreachable!("this one is proven to be a slope"),
|
||||
})
|
||||
} else {
|
||||
result.push(match stack_history.pop().unwrap() {
|
||||
Wrapper::Slope(m, i) => Atom::Slope(m, i, popped),
|
||||
_ => unreachable!("this one is proven to be a slope"),
|
||||
})
|
||||
}
|
||||
}
|
||||
FlatAtom::Comment => slope_stack.last_mut().unwrap().push(Atom::Comment),
|
||||
},
|
||||
None => match atom {
|
||||
FlatAtom::Note(n) => result.push(Atom::Note(n)),
|
||||
FlatAtom::Rest => result.push(Atom::Rest),
|
||||
FlatAtom::StartHere => result.push(Atom::StartHere),
|
||||
FlatAtom::Modifier(m) => result.push(Atom::Modifier(m)),
|
||||
FlatAtom::QuickModifier(q) => result.push(Atom::QuickModifier(q)),
|
||||
FlatAtom::LoopStarts(n) => {
|
||||
loop_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Loop(n));
|
||||
}
|
||||
FlatAtom::LoopEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop));
|
||||
}
|
||||
FlatAtom::TupleStarts => {
|
||||
tuple_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Tuple);
|
||||
}
|
||||
FlatAtom::TupleEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple));
|
||||
}
|
||||
FlatAtom::SlopeStarts(s, i) => {
|
||||
slope_stack.push(Vec::new());
|
||||
stack_history.push(Wrapper::Slope(s, i));
|
||||
}
|
||||
FlatAtom::SlopeEnds => {
|
||||
return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope));
|
||||
}
|
||||
FlatAtom::Comment => result.push(Atom::Comment),
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
|
@ -1,206 +0,0 @@
|
|||
#[cfg(test)]
|
||||
mod inflate {
|
||||
use fasteval::Compiler;
|
||||
use lex::{ON, UP};
|
||||
|
||||
use super::{super::*, inflate};
|
||||
|
||||
const FASTEVAL_INSTRUCTION: &str = "1-cos((PI*x)/2)";
|
||||
|
||||
fn instruction() -> Instruction {
|
||||
FASTEVAL_INSTRUCTION.parse().unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_flat() {
|
||||
assert_eq!(
|
||||
Ok(vec![
|
||||
Atom::Note(2),
|
||||
Atom::Rest,
|
||||
Atom::StartHere,
|
||||
Atom::Modifier(Modifier::Volume(2)),
|
||||
Atom::QuickModifier(QuickModifier::Volume(UP)),
|
||||
Atom::Comment
|
||||
]),
|
||||
inflate(vec![
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Rest,
|
||||
FlatAtom::StartHere,
|
||||
FlatAtom::Modifier(Modifier::Volume(2)),
|
||||
FlatAtom::QuickModifier(QuickModifier::Volume(UP)),
|
||||
FlatAtom::Comment
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_loop_l1() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Loop(
|
||||
unsafe { NonZeroU8::new_unchecked(3) },
|
||||
vec![Atom::Note(2), Atom::Note(3)]
|
||||
)]),
|
||||
inflate(vec![
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }),
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::LoopEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_tuple_l1() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Tuple(vec![Atom::Note(2), Atom::Note(3)])]),
|
||||
inflate(vec![
|
||||
FlatAtom::TupleStarts,
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::TupleEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_slope_l1() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Slope(
|
||||
SlopeModifier::Note,
|
||||
instruction(),
|
||||
vec![Atom::Note(2), Atom::Note(3)]
|
||||
)]),
|
||||
inflate(vec![
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::SlopeEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_loop_l2() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Loop(
|
||||
unsafe { NonZeroU8::new_unchecked(2) },
|
||||
vec![Atom::Loop(
|
||||
unsafe { NonZeroU8::new_unchecked(3) },
|
||||
vec![Atom::Note(2), Atom::Note(3)]
|
||||
)]
|
||||
)]),
|
||||
inflate(vec![
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) }),
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }),
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::LoopEnds,
|
||||
FlatAtom::LoopEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_tuple_l2() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Tuple(vec![Atom::Tuple(vec![
|
||||
Atom::Note(2),
|
||||
Atom::Note(3)
|
||||
])])]),
|
||||
inflate(vec![
|
||||
FlatAtom::TupleStarts,
|
||||
FlatAtom::TupleStarts,
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::TupleEnds,
|
||||
FlatAtom::TupleEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inflate_slope_l2() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Slope(
|
||||
SlopeModifier::Note,
|
||||
instruction(),
|
||||
vec![Atom::Slope(
|
||||
SlopeModifier::Length,
|
||||
instruction(),
|
||||
vec![Atom::Note(2), Atom::Note(3)]
|
||||
)]
|
||||
)]),
|
||||
inflate(vec![
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::SlopeEnds,
|
||||
FlatAtom::SlopeEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed() {
|
||||
assert_eq!(
|
||||
Ok(vec![Atom::Slope(
|
||||
SlopeModifier::Note,
|
||||
instruction(),
|
||||
vec![Atom::Slope(
|
||||
SlopeModifier::Length,
|
||||
instruction(),
|
||||
vec![
|
||||
Atom::Note(2),
|
||||
Atom::Tuple(vec![Atom::Rest, Atom::Note(6)]),
|
||||
Atom::Note(3),
|
||||
Atom::Loop(
|
||||
unsafe { NonZeroU8::new_unchecked(9) },
|
||||
vec![Atom::QuickModifier(QuickModifier::Pizz(ON)), Atom::Note(0)]
|
||||
)
|
||||
]
|
||||
)]
|
||||
)]),
|
||||
inflate(vec![
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::TupleStarts,
|
||||
FlatAtom::Rest,
|
||||
FlatAtom::Note(6),
|
||||
FlatAtom::TupleEnds,
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(9) }),
|
||||
FlatAtom::QuickModifier(QuickModifier::Pizz(ON)),
|
||||
FlatAtom::Note(0),
|
||||
FlatAtom::LoopEnds,
|
||||
FlatAtom::SlopeEnds,
|
||||
FlatAtom::SlopeEnds
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_mismatched_end() {
|
||||
assert_eq!(
|
||||
Err(InflateError::MismatchedEnd(WrapperDiscriminants::Slope)),
|
||||
inflate(vec![
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
|
||||
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
|
||||
FlatAtom::Note(2),
|
||||
FlatAtom::TupleStarts,
|
||||
FlatAtom::Rest,
|
||||
FlatAtom::SlopeEnds, // mismatched slope end while in a tuple
|
||||
FlatAtom::Note(6),
|
||||
FlatAtom::TupleEnds,
|
||||
FlatAtom::Note(3),
|
||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(9) }),
|
||||
FlatAtom::QuickModifier(QuickModifier::Pizz(ON)),
|
||||
FlatAtom::Note(0),
|
||||
FlatAtom::LoopEnds,
|
||||
FlatAtom::SlopeEnds,
|
||||
FlatAtom::SlopeEnds,
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue