diff --git a/src/bng/score.rs b/src/bng/score.rs index 6a4a68e..515b814 100644 --- a/src/bng/score.rs +++ b/src/bng/score.rs @@ -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); #[cfg_attr(debug_assertions, derive(Debug, PartialEq))] @@ -43,12 +41,21 @@ pub enum Atom { StartHere, Modifier(Modifier), QuickModifier(QuickModifier), - Loop(NonZeroU8, Vec), - Tuple(Vec), - Slope(SlopeModifier, Instruction, Vec), + 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(&self, serializer: S) -> Result @@ -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 { diff --git a/src/bng/score/de.rs b/src/bng/score/de.rs index 9756e9b..6659557 100644 --- a/src/bng/score/de.rs +++ b/src/bng/score/de.rs @@ -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(deserializer: D) -> Result @@ -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) } } } diff --git a/src/bng/score/lex.rs b/src/bng/score/lex.rs index bb580a8..948dd89 100644 --- a/src/bng/score/lex.rs +++ b/src/bng/score/lex.rs @@ -1,4 +1,4 @@ -use super::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier}; +use super::{Atom, Modifier, QuickModifier, SlopeModifier}; pub(super) mod lexer; diff --git a/src/bng/score/lex/lexer.rs b/src/bng/score/lex/lexer.rs index 45bf7ad..b3fbd0e 100644 --- a/src/bng/score/lex/lexer.rs +++ b/src/bng/score/lex/lexer.rs @@ -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, 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, 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, )), ) diff --git a/src/bng/score/lex/lexer/tests.rs b/src/bng/score/lex/lexer/tests.rs index f7a8bcf..3c3cc58 100644 --- a/src/bng/score/lex/lexer/tests.rs +++ b/src/bng/score/lex/lexer/tests.rs @@ -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::>("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::>("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::>("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::>("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::>("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::>("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::>("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::>("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::>("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::>("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::>("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::>("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::>("abcdefg").parse(concatcp!( Atom::COMMENT.0, "hi I'm a little pony", diff --git a/src/bng/score/utils.rs b/src/bng/score/utils.rs deleted file mode 100644 index e7bb56d..0000000 --- a/src/bng/score/utils.rs +++ /dev/null @@ -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) -> Result, InflateError> { - type Error = InflateError; - let mut result = Vec::with_capacity(flat_atoms.len()); - let mut loop_stack: Vec> = Vec::new(); - let mut tuple_stack: Vec> = Vec::new(); - let mut slope_stack: Vec> = Vec::new(); - let mut stack_history: Vec = 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) -} diff --git a/src/bng/score/utils/tests.rs b/src/bng/score/utils/tests.rs deleted file mode 100644 index 88d08b9..0000000 --- a/src/bng/score/utils/tests.rs +++ /dev/null @@ -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, - ]) - ) - } -}