error type for inflate, start serialize
This commit is contained in:
parent
b95ace9d8e
commit
0fcf937d51
9 changed files with 289 additions and 221 deletions
|
@ -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"]
|
||||
|
|
24
src/bng.rs
24
src/bng.rs
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
))
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// TODO: remove clap, use only a file or standard in
|
||||
use clap::Parser;
|
||||
|
||||
mod bng;
|
||||
|
|
Loading…
Reference in a new issue