error type for inflate, start serialize

This commit is contained in:
Breval Ferrari 2024-10-26 19:45:11 -04:00
parent b95ace9d8e
commit 0fcf937d51
No known key found for this signature in database
GPG key ID: 6FED68D87C479A59
9 changed files with 289 additions and 221 deletions

View file

@ -11,7 +11,7 @@ clap = { version = "4.5", features = ["derive"] }
derived-deref = "2.1.0" derived-deref = "2.1.0"
fasteval = "0.2.4" fasteval = "0.2.4"
nom = "7.1.3" nom = "7.1.3"
serde = "1.0.209" serde = { version = "1.0.209", features = ["derive"] }
serde_yml = "0.0.12" serde_yml = "0.0.12"
splines = "4.3.1" splines = "4.3.1"
strum = { version = "0.26", features = ["derive"] } strum = { version = "0.26", features = ["derive"] }
@ -19,6 +19,8 @@ strum_macros = "0.26"
tinyaudio = { version = "0.1", optional = true } tinyaudio = { version = "0.1", optional = true }
bng_macros = { path = "bng_macros" } bng_macros = { path = "bng_macros" }
const_format = "0.2.33" const_format = "0.2.33"
thiserror = "1.0.64"
derive-new = "0.7.0"
[features] [features]
default = ["play", "save"] default = ["play", "save"]

View file

@ -1,2 +1,26 @@
use derive_new::new;
use derived_deref::Deref;
use fasteval::Instruction;
use instrument::Instrument;
use serde::Serialize;
mod instrument; mod instrument;
mod score; mod score;
#[derive(new, Debug, PartialEq)]
pub struct InstructionWrapper(Instruction);
impl Serialize for InstructionWrapper {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let expr_str = String::new();
serializer.serialize_str(&format!("{:#?}", self.0))
}
}
#[derive(Serialize)]
struct BngFile {
instruments: Vec<Instrument>,
}

View file

@ -1,5 +1,7 @@
use derived_deref::Deref; use derived_deref::Deref;
use fasteval::Instruction; use serde::Serialize;
#[derive(Deref)] use super::InstructionWrapper as Instruction;
#[derive(Serialize, Deref)]
pub struct Instrument(Instruction); pub struct Instrument(Instruction);

View file

@ -2,12 +2,13 @@ use std::num::{NonZeroU16, NonZeroU8};
use anyhow::Context; use anyhow::Context;
use bng_macros::{QuickModifierParser, SlopeModifierParser}; use bng_macros::{QuickModifierParser, SlopeModifierParser};
use fasteval::Instruction;
use strum::EnumDiscriminants; use strum::EnumDiscriminants;
mod lex; mod lex;
mod utils; mod utils;
use super::InstructionWrapper as Instruction;
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))] #[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
pub(super) enum Atom { pub(super) enum Atom {
Note(u8), Note(u8),

View file

@ -4,7 +4,7 @@ use std::{
}; };
use clap::builder::TypedValueParser; use clap::builder::TypedValueParser;
use fasteval::{Compiler, Instruction}; use fasteval::Compiler;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{take_till, take_till1}, bytes::complete::{take_till, take_till1},
@ -15,7 +15,10 @@ use nom::{
Err, IResult, Parser, Err, IResult, Parser,
}; };
use crate::bng::score::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier}; use super::{
super::super::InstructionWrapper as Instruction,
{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier},
};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -65,7 +68,7 @@ fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Erro
map_res(take_till1(|c| c == ','), |s| { map_res(take_till1(|c| c == ','), |s| {
let parser = fasteval::Parser::new(); let parser = fasteval::Parser::new();
let mut slab = fasteval::Slab::new(); let mut slab = fasteval::Slab::new();
Result::<Instruction, nom::error::Error<&str>>::Ok( Result::<Instruction, nom::error::Error<&str>>::Ok(Instruction::new(
parser parser
.parse(s, &mut slab.ps) .parse(s, &mut slab.ps)
.map_err(|_| { .map_err(|_| {
@ -73,7 +76,7 @@ fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Erro
})? })?
.from(&slab.ps) .from(&slab.ps)
.compile(&slab.ps, &mut slab.cs), .compile(&slab.ps, &mut slab.cs),
) ))
}), }),
), ),
), ),

View file

@ -14,11 +14,11 @@ mod flat_atom {
use fasteval::Compiler; use fasteval::Compiler;
use nom::Parser; use nom::Parser;
use super::*; use super::super::{
use crate::bng::score::{ super::super::super::InstructionWrapper as Instruction, super::UP, flat_atom_parser, Atom,
lex::{lexer::flat_atom_parser, UP}, FlatAtom, Modifier, QuickModifier, SlopeModifier,
Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier,
}; };
use super::*;
pub(super) const SAMPLE_STR: &str = concatcp!( pub(super) const SAMPLE_STR: &str = concatcp!(
Atom::TUPLE.0, Atom::TUPLE.0,
@ -139,11 +139,13 @@ mod flat_atom {
FlatAtom::SlopeStarts(SlopeModifier::Note, { FlatAtom::SlopeStarts(SlopeModifier::Note, {
let parser = fasteval::Parser::new(); let parser = fasteval::Parser::new();
let mut slab = fasteval::Slab::new(); let mut slab = fasteval::Slab::new();
parser Instruction::new(
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps) parser
.unwrap() .parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
.from(&slab.ps) .unwrap()
.compile(&slab.ps, &mut slab.cs) .from(&slab.ps)
.compile(&slab.ps, &mut slab.cs),
)
}) })
)), )),
flat_atom_parser("abcdefg").parse(concatcp!( flat_atom_parser("abcdefg").parse(concatcp!(

View file

@ -1,22 +1,32 @@
use super::*; use super::*;
use strum::Display;
use thiserror::Error;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
// TODO: replace panics with custom error type #[derive(Debug, EnumDiscriminants)]
fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Vec<Atom> { #[strum_discriminants(derive(Display))]
#[derive(EnumDiscriminants)] enum Wrapper {
#[cfg_attr(debug_assertions, derive(Debug))] Loop(NonZeroU8),
enum CurrentStack { Tuple,
Loop(NonZeroU8), Slope(SlopeModifier, Instruction),
Tuple, }
Slope(SlopeModifier, Instruction),
} #[derive(Debug, Error)]
#[cfg_attr(test, derive(PartialEq))]
enum InflateError {
#[error("misplaced {0} end symbol")]
MismatchedEnd(WrapperDiscriminants),
}
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 result = Vec::with_capacity(flat_atoms.len());
let mut loop_stack: Vec<Vec<Atom>> = Vec::new(); let mut loop_stack: Vec<Vec<Atom>> = Vec::new();
let mut tuple_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 slope_stack: Vec<Vec<Atom>> = Vec::new();
let mut stack_history: Vec<CurrentStack> = Vec::new(); let mut stack_history: Vec<Wrapper> = Vec::new();
for mut atom in flat_atoms.into_iter() { for mut atom in flat_atoms.into_iter() {
#[cfg(test)] #[cfg(test)]
{ {
@ -26,159 +36,172 @@ fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Vec<Atom> {
dbg!(&slope_stack); dbg!(&slope_stack);
dbg!(&stack_history); dbg!(&stack_history);
} }
if let Some(stack) = stack_history.last() { match stack_history.last().map(WrapperDiscriminants::from) {
match CurrentStackDiscriminants::from(stack) { Some(WrapperDiscriminants::Loop) => match atom {
CurrentStackDiscriminants::Loop => match atom { FlatAtom::Note(n) => {
FlatAtom::Note(n) => loop_stack.last_mut().unwrap().push(Atom::Note(n)), unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Note(n))
FlatAtom::Rest => loop_stack.last_mut().unwrap().push(Atom::Rest), }
FlatAtom::StartHere => loop_stack.last_mut().unwrap().push(Atom::StartHere), FlatAtom::Rest => {
FlatAtom::Modifier(m) => loop_stack.last_mut().unwrap().push(Atom::Modifier(m)), unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Rest)
FlatAtom::QuickModifier(q) => { }
loop_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) FlatAtom::StartHere => {
} unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::StartHere)
FlatAtom::LoopStarts(n) => { }
loop_stack.push(Vec::new()); FlatAtom::Modifier(m) => {
stack_history.push(CurrentStack::Loop(n)); unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Modifier(m))
} }
FlatAtom::LoopEnds => { FlatAtom::QuickModifier(q) => {
let popped = loop_stack.pop().unwrap(); unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::QuickModifier(q))
if stack_history.len() > 1 { }
match CurrentStackDiscriminants::from( FlatAtom::LoopStarts(n) => {
stack_history.get(stack_history.len() - 2).unwrap(), loop_stack.push(Vec::new());
) { stack_history.push(Wrapper::Loop(n));
CurrentStackDiscriminants::Loop => &mut loop_stack, }
CurrentStackDiscriminants::Tuple => &mut tuple_stack, FlatAtom::LoopEnds => {
CurrentStackDiscriminants::Slope => &mut slope_stack, let popped = unsafe { loop_stack.pop().unwrap_unchecked() };
} if stack_history.len() > 1 {
.last_mut() match WrapperDiscriminants::from(
.unwrap() stack_history.get(stack_history.len() - 2).unwrap(),
.push(Atom::Loop( ) {
match stack_history.pop().unwrap() { WrapperDiscriminants::Loop => &mut loop_stack,
CurrentStack::Loop(n) => n, WrapperDiscriminants::Tuple => &mut tuple_stack,
_ => unreachable!("this one is proven to be a loop"), WrapperDiscriminants::Slope => &mut slope_stack,
},
popped,
))
} else {
result.push(Atom::Loop(
match stack_history.pop().unwrap() {
CurrentStack::Loop(n) => n,
_ => unreachable!("this one is proven to be a loop"),
},
popped,
))
} }
.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()); FlatAtom::TupleStarts => {
stack_history.push(CurrentStack::Tuple); tuple_stack.push(Vec::new());
} stack_history.push(Wrapper::Tuple);
FlatAtom::TupleEnds => panic!("unmatched end tuple in a loop"), }
FlatAtom::SlopeStarts(s, i) => { FlatAtom::TupleEnds => {
slope_stack.push(Vec::new()); return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple));
stack_history.push(CurrentStack::Slope(s, i)); }
} FlatAtom::SlopeStarts(s, i) => {
FlatAtom::SlopeEnds => panic!("unmatched end slope in a loop"), slope_stack.push(Vec::new());
FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment), stack_history.push(Wrapper::Slope(s, i));
}, }
CurrentStackDiscriminants::Tuple => match atom { FlatAtom::SlopeEnds => {
FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)), return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope));
FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest), }
FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere), FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment),
FlatAtom::Modifier(m) => { },
tuple_stack.last_mut().unwrap().push(Atom::Modifier(m)) Some(WrapperDiscriminants::Tuple) => match atom {
} FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)),
FlatAtom::QuickModifier(q) => { FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest),
tuple_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere),
} FlatAtom::Modifier(m) => tuple_stack.last_mut().unwrap().push(Atom::Modifier(m)),
FlatAtom::LoopStarts(n) => { FlatAtom::QuickModifier(q) => {
loop_stack.push(Vec::new()); tuple_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
stack_history.push(CurrentStack::Loop(n)); }
} FlatAtom::LoopStarts(n) => {
FlatAtom::LoopEnds => panic!("unmatched end loop in a tuple"), loop_stack.push(Vec::new());
FlatAtom::TupleStarts => { stack_history.push(Wrapper::Loop(n));
tuple_stack.push(Vec::new()); }
stack_history.push(CurrentStack::Tuple); FlatAtom::LoopEnds => {
} return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop));
FlatAtom::TupleEnds => { }
let popped = tuple_stack.pop().unwrap(); FlatAtom::TupleStarts => {
if stack_history.len() > 1 { tuple_stack.push(Vec::new());
match CurrentStackDiscriminants::from( stack_history.push(Wrapper::Tuple);
stack_history.get(stack_history.len() - 2).unwrap(), }
) { FlatAtom::TupleEnds => {
CurrentStackDiscriminants::Loop => &mut loop_stack, let popped = tuple_stack.pop().unwrap();
CurrentStackDiscriminants::Tuple => &mut tuple_stack, if stack_history.len() > 1 {
CurrentStackDiscriminants::Slope => &mut slope_stack, match WrapperDiscriminants::from(
} stack_history.get(stack_history.len() - 2).unwrap(),
.last_mut() ) {
.unwrap() WrapperDiscriminants::Loop => &mut loop_stack,
.push({ WrapperDiscriminants::Tuple => &mut tuple_stack,
stack_history.pop(); WrapperDiscriminants::Slope => &mut slope_stack,
Atom::Tuple(popped)
})
} else {
result.push(Atom::Tuple(popped))
} }
.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()); FlatAtom::SlopeStarts(s, i) => {
stack_history.push(CurrentStack::Slope(s, i)); slope_stack.push(Vec::new());
} stack_history.push(Wrapper::Slope(s, i));
FlatAtom::SlopeEnds => panic!("unmatched end slope in a tuple"), }
FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment), FlatAtom::SlopeEnds => {
}, return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope));
CurrentStackDiscriminants::Slope => match atom { }
FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)), FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment),
FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest), },
FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere), Some(WrapperDiscriminants::Slope) => match atom {
FlatAtom::Modifier(m) => { FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)),
slope_stack.last_mut().unwrap().push(Atom::Modifier(m)) FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest),
} FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere),
FlatAtom::QuickModifier(q) => { FlatAtom::Modifier(m) => slope_stack.last_mut().unwrap().push(Atom::Modifier(m)),
slope_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) FlatAtom::QuickModifier(q) => {
} slope_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
FlatAtom::LoopStarts(n) => { }
loop_stack.push(Vec::new()); FlatAtom::LoopStarts(n) => {
stack_history.push(CurrentStack::Loop(n)); loop_stack.push(Vec::new());
} stack_history.push(Wrapper::Loop(n));
FlatAtom::LoopEnds => panic!("unmatched end loop"), }
FlatAtom::TupleStarts => { FlatAtom::LoopEnds => {
tuple_stack.push(Vec::new()); return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop));
stack_history.push(CurrentStack::Tuple); }
} FlatAtom::TupleStarts => {
FlatAtom::TupleEnds => panic!("unmatched end tuple"), tuple_stack.push(Vec::new());
FlatAtom::SlopeStarts(s, i) => { stack_history.push(Wrapper::Tuple);
slope_stack.push(Vec::new()); }
stack_history.push(CurrentStack::Slope(s, i)); FlatAtom::TupleEnds => {
} return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple));
FlatAtom::SlopeEnds => { }
let popped = slope_stack.pop().unwrap(); FlatAtom::SlopeStarts(s, i) => {
if stack_history.len() > 1 { slope_stack.push(Vec::new());
match CurrentStackDiscriminants::from( stack_history.push(Wrapper::Slope(s, i));
stack_history.get(stack_history.len() - 2).unwrap(), }
) { FlatAtom::SlopeEnds => {
CurrentStackDiscriminants::Loop => &mut loop_stack, let popped = slope_stack.pop().unwrap();
CurrentStackDiscriminants::Tuple => &mut tuple_stack, if stack_history.len() > 1 {
CurrentStackDiscriminants::Slope => &mut slope_stack, match WrapperDiscriminants::from(
} stack_history.get(stack_history.len() - 2).unwrap(),
.last_mut() ) {
.unwrap() WrapperDiscriminants::Loop => &mut loop_stack,
.push(match stack_history.pop().unwrap() { WrapperDiscriminants::Tuple => &mut tuple_stack,
CurrentStack::Slope(m, i) => Atom::Slope(m, i, popped), WrapperDiscriminants::Slope => &mut slope_stack,
_ => unreachable!("this one is proven to be a slope"),
})
} else {
result.push(match stack_history.pop().unwrap() {
CurrentStack::Slope(m, i) => Atom::Slope(m, i, popped),
_ => unreachable!("this one is proven to be a slope"),
})
} }
.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), }
}, FlatAtom::Comment => slope_stack.last_mut().unwrap().push(Atom::Comment),
} },
} else { None => match atom {
match atom {
FlatAtom::Note(n) => result.push(Atom::Note(n)), FlatAtom::Note(n) => result.push(Atom::Note(n)),
FlatAtom::Rest => result.push(Atom::Rest), FlatAtom::Rest => result.push(Atom::Rest),
FlatAtom::StartHere => result.push(Atom::StartHere), FlatAtom::StartHere => result.push(Atom::StartHere),
@ -186,22 +209,28 @@ fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Vec<Atom> {
FlatAtom::QuickModifier(q) => result.push(Atom::QuickModifier(q)), FlatAtom::QuickModifier(q) => result.push(Atom::QuickModifier(q)),
FlatAtom::LoopStarts(n) => { FlatAtom::LoopStarts(n) => {
loop_stack.push(Vec::new()); loop_stack.push(Vec::new());
stack_history.push(CurrentStack::Loop(n)); stack_history.push(Wrapper::Loop(n));
}
FlatAtom::LoopEnds => {
return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop));
} }
FlatAtom::LoopEnds => panic!("unmatched end loop"),
FlatAtom::TupleStarts => { FlatAtom::TupleStarts => {
tuple_stack.push(Vec::new()); tuple_stack.push(Vec::new());
stack_history.push(CurrentStack::Tuple); stack_history.push(Wrapper::Tuple);
}
FlatAtom::TupleEnds => {
return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple));
} }
FlatAtom::TupleEnds => panic!("unmatched end tuple"),
FlatAtom::SlopeStarts(s, i) => { FlatAtom::SlopeStarts(s, i) => {
slope_stack.push(Vec::new()); slope_stack.push(Vec::new());
stack_history.push(CurrentStack::Slope(s, i)); stack_history.push(Wrapper::Slope(s, i));
}
FlatAtom::SlopeEnds => {
return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope));
} }
FlatAtom::SlopeEnds => panic!("unmatched end slope"),
FlatAtom::Comment => result.push(Atom::Comment), FlatAtom::Comment => result.push(Atom::Comment),
} },
} }
} }
result Ok(result)
} }

View file

@ -10,24 +10,26 @@ mod inflate {
fn instruction() -> Instruction { fn instruction() -> Instruction {
let parser = fasteval::Parser::new(); let parser = fasteval::Parser::new();
let mut slab = fasteval::Slab::new(); let mut slab = fasteval::Slab::new();
parser Instruction::new(
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps) parser
.unwrap() .parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
.from(&slab.ps) .unwrap()
.compile(&slab.ps, &mut slab.cs) .from(&slab.ps)
.compile(&slab.ps, &mut slab.cs),
)
} }
#[test] #[test]
fn inflate_flat() { fn inflate_flat() {
assert_eq!( assert_eq!(
vec![ Ok(vec![
Atom::Note(2), Atom::Note(2),
Atom::Rest, Atom::Rest,
Atom::StartHere, Atom::StartHere,
Atom::Modifier(Modifier::Volume(2)), Atom::Modifier(Modifier::Volume(2)),
Atom::QuickModifier(QuickModifier::Volume(UP)), Atom::QuickModifier(QuickModifier::Volume(UP)),
Atom::Comment Atom::Comment
], ]),
inflate(vec![ inflate(vec![
FlatAtom::Note(2), FlatAtom::Note(2),
FlatAtom::Rest, FlatAtom::Rest,
@ -42,10 +44,10 @@ mod inflate {
#[test] #[test]
fn inflate_loop_l1() { fn inflate_loop_l1() {
assert_eq!( assert_eq!(
vec![Atom::Loop( Ok(vec![Atom::Loop(
unsafe { NonZeroU8::new_unchecked(3) }, unsafe { NonZeroU8::new_unchecked(3) },
vec![Atom::Note(2), Atom::Note(3)] vec![Atom::Note(2), Atom::Note(3)]
)], )]),
inflate(vec![ inflate(vec![
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }), FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }),
FlatAtom::Note(2), FlatAtom::Note(2),
@ -58,7 +60,7 @@ mod inflate {
#[test] #[test]
fn inflate_tuple_l1() { fn inflate_tuple_l1() {
assert_eq!( assert_eq!(
vec![Atom::Tuple(vec![Atom::Note(2), Atom::Note(3)])], Ok(vec![Atom::Tuple(vec![Atom::Note(2), Atom::Note(3)])]),
inflate(vec![ inflate(vec![
FlatAtom::TupleStarts, FlatAtom::TupleStarts,
FlatAtom::Note(2), FlatAtom::Note(2),
@ -71,11 +73,11 @@ mod inflate {
#[test] #[test]
fn inflate_slope_l1() { fn inflate_slope_l1() {
assert_eq!( assert_eq!(
vec![Atom::Slope( Ok(vec![Atom::Slope(
SlopeModifier::Note, SlopeModifier::Note,
instruction(), instruction(),
vec![Atom::Note(2), Atom::Note(3)] vec![Atom::Note(2), Atom::Note(3)]
)], )]),
inflate(vec![ inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::Note(2), FlatAtom::Note(2),
@ -88,13 +90,13 @@ mod inflate {
#[test] #[test]
fn inflate_loop_l2() { fn inflate_loop_l2() {
assert_eq!( assert_eq!(
vec![Atom::Loop( Ok(vec![Atom::Loop(
unsafe { NonZeroU8::new_unchecked(2) }, unsafe { NonZeroU8::new_unchecked(2) },
vec![Atom::Loop( vec![Atom::Loop(
unsafe { NonZeroU8::new_unchecked(3) }, unsafe { NonZeroU8::new_unchecked(3) },
vec![Atom::Note(2), Atom::Note(3)] vec![Atom::Note(2), Atom::Note(3)]
)] )]
)], )]),
inflate(vec![ inflate(vec![
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) }), FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) }),
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }), FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }),
@ -109,10 +111,10 @@ mod inflate {
#[test] #[test]
fn inflate_tuple_l2() { fn inflate_tuple_l2() {
assert_eq!( assert_eq!(
vec![Atom::Tuple(vec![Atom::Tuple(vec![ Ok(vec![Atom::Tuple(vec![Atom::Tuple(vec![
Atom::Note(2), Atom::Note(2),
Atom::Note(3) Atom::Note(3)
])])], ])])]),
inflate(vec![ inflate(vec![
FlatAtom::TupleStarts, FlatAtom::TupleStarts,
FlatAtom::TupleStarts, FlatAtom::TupleStarts,
@ -127,7 +129,7 @@ mod inflate {
#[test] #[test]
fn inflate_slope_l2() { fn inflate_slope_l2() {
assert_eq!( assert_eq!(
vec![Atom::Slope( Ok(vec![Atom::Slope(
SlopeModifier::Note, SlopeModifier::Note,
instruction(), instruction(),
vec![Atom::Slope( vec![Atom::Slope(
@ -135,7 +137,7 @@ mod inflate {
instruction(), instruction(),
vec![Atom::Note(2), Atom::Note(3)] vec![Atom::Note(2), Atom::Note(3)]
)] )]
)], )]),
inflate(vec![ inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
@ -150,7 +152,7 @@ mod inflate {
#[test] #[test]
fn mixed() { fn mixed() {
assert_eq!( assert_eq!(
vec![Atom::Slope( Ok(vec![Atom::Slope(
SlopeModifier::Note, SlopeModifier::Note,
instruction(), instruction(),
vec![Atom::Slope( vec![Atom::Slope(
@ -166,7 +168,7 @@ mod inflate {
) )
] ]
)] )]
)], )]),
inflate(vec![ inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
@ -187,24 +189,26 @@ mod inflate {
} }
#[test] #[test]
#[should_panic] fn mixed_mismatched_end() {
fn mixed_panic() { assert_eq!(
inflate(vec![ Err(InflateError::MismatchedEnd(WrapperDiscriminants::Slope)),
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::Note(2), FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
FlatAtom::TupleStarts, FlatAtom::Note(2),
FlatAtom::Rest, FlatAtom::TupleStarts,
FlatAtom::SlopeEnds, // mismatched slope end while in a tuple FlatAtom::Rest,
FlatAtom::Note(6), FlatAtom::SlopeEnds, // mismatched slope end while in a tuple
FlatAtom::TupleEnds, FlatAtom::Note(6),
FlatAtom::Note(3), FlatAtom::TupleEnds,
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(9) }), FlatAtom::Note(3),
FlatAtom::QuickModifier(QuickModifier::Pizz(ON)), FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(9) }),
FlatAtom::Note(0), FlatAtom::QuickModifier(QuickModifier::Pizz(ON)),
FlatAtom::LoopEnds, FlatAtom::Note(0),
FlatAtom::SlopeEnds, FlatAtom::LoopEnds,
FlatAtom::SlopeEnds, FlatAtom::SlopeEnds,
]); FlatAtom::SlopeEnds,
])
)
} }
} }

View file

@ -1,3 +1,4 @@
/// TODO: remove clap, use only a file or standard in
use clap::Parser; use clap::Parser;
mod bng; mod bng;