error type for inflate, start serialize

This commit is contained in:
Ponj 2024-10-26 19:45:11 -04:00
parent b95ace9d8e
commit 0fcf937d51
Signed by: p6nj
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"
fasteval = "0.2.4"
nom = "7.1.3"
serde = "1.0.209"
serde = { version = "1.0.209", features = ["derive"] }
serde_yml = "0.0.12"
splines = "4.3.1"
strum = { version = "0.26", features = ["derive"] }
@ -19,6 +19,8 @@ strum_macros = "0.26"
tinyaudio = { version = "0.1", optional = true }
bng_macros = { path = "bng_macros" }
const_format = "0.2.33"
thiserror = "1.0.64"
derive-new = "0.7.0"
[features]
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 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 fasteval::Instruction;
use serde::Serialize;
#[derive(Deref)]
use super::InstructionWrapper as Instruction;
#[derive(Serialize, Deref)]
pub struct Instrument(Instruction);

View file

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

View file

@ -4,7 +4,7 @@ use std::{
};
use clap::builder::TypedValueParser;
use fasteval::{Compiler, Instruction};
use fasteval::Compiler;
use nom::{
branch::alt,
bytes::complete::{take_till, take_till1},
@ -15,7 +15,10 @@ use nom::{
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)]
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| {
let parser = fasteval::Parser::new();
let mut slab = fasteval::Slab::new();
Result::<Instruction, nom::error::Error<&str>>::Ok(
Result::<Instruction, nom::error::Error<&str>>::Ok(Instruction::new(
parser
.parse(s, &mut slab.ps)
.map_err(|_| {
@ -73,7 +76,7 @@ fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Erro
})?
.from(&slab.ps)
.compile(&slab.ps, &mut slab.cs),
)
))
}),
),
),

View file

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

View file

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

View file

@ -10,24 +10,26 @@ mod inflate {
fn instruction() -> Instruction {
let parser = fasteval::Parser::new();
let mut slab = fasteval::Slab::new();
parser
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
.unwrap()
.from(&slab.ps)
.compile(&slab.ps, &mut slab.cs)
Instruction::new(
parser
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
.unwrap()
.from(&slab.ps)
.compile(&slab.ps, &mut slab.cs),
)
}
#[test]
fn inflate_flat() {
assert_eq!(
vec![
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,
@ -42,10 +44,10 @@ mod inflate {
#[test]
fn inflate_loop_l1() {
assert_eq!(
vec![Atom::Loop(
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),
@ -58,7 +60,7 @@ mod inflate {
#[test]
fn inflate_tuple_l1() {
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![
FlatAtom::TupleStarts,
FlatAtom::Note(2),
@ -71,11 +73,11 @@ mod inflate {
#[test]
fn inflate_slope_l1() {
assert_eq!(
vec![Atom::Slope(
Ok(vec![Atom::Slope(
SlopeModifier::Note,
instruction(),
vec![Atom::Note(2), Atom::Note(3)]
)],
)]),
inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::Note(2),
@ -88,13 +90,13 @@ mod inflate {
#[test]
fn inflate_loop_l2() {
assert_eq!(
vec![Atom::Loop(
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) }),
@ -109,10 +111,10 @@ mod inflate {
#[test]
fn inflate_tuple_l2() {
assert_eq!(
vec![Atom::Tuple(vec![Atom::Tuple(vec![
Ok(vec![Atom::Tuple(vec![Atom::Tuple(vec![
Atom::Note(2),
Atom::Note(3)
])])],
])])]),
inflate(vec![
FlatAtom::TupleStarts,
FlatAtom::TupleStarts,
@ -127,7 +129,7 @@ mod inflate {
#[test]
fn inflate_slope_l2() {
assert_eq!(
vec![Atom::Slope(
Ok(vec![Atom::Slope(
SlopeModifier::Note,
instruction(),
vec![Atom::Slope(
@ -135,7 +137,7 @@ mod inflate {
instruction(),
vec![Atom::Note(2), Atom::Note(3)]
)]
)],
)]),
inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
@ -150,7 +152,7 @@ mod inflate {
#[test]
fn mixed() {
assert_eq!(
vec![Atom::Slope(
Ok(vec![Atom::Slope(
SlopeModifier::Note,
instruction(),
vec![Atom::Slope(
@ -166,7 +168,7 @@ mod inflate {
)
]
)]
)],
)]),
inflate(vec![
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
@ -187,24 +189,26 @@ mod inflate {
}
#[test]
#[should_panic]
fn mixed_panic() {
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,
]);
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,
])
)
}
}

View file

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