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"
|
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"]
|
||||||
|
|
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 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>,
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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),
|
||||||
)
|
))
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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();
|
||||||
|
Instruction::new(
|
||||||
parser
|
parser
|
||||||
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
|
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.from(&slab.ps)
|
.from(&slab.ps)
|
||||||
.compile(&slab.ps, &mut slab.cs)
|
.compile(&slab.ps, &mut slab.cs),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
)),
|
)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(
|
flat_atom_parser("abcdefg").parse(concatcp!(
|
||||||
|
|
|
@ -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))]
|
|
||||||
enum CurrentStack {
|
|
||||||
Loop(NonZeroU8),
|
Loop(NonZeroU8),
|
||||||
Tuple,
|
Tuple,
|
||||||
Slope(SlopeModifier, Instruction),
|
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,35 +36,42 @@ 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::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) => {
|
FlatAtom::QuickModifier(q) => {
|
||||||
loop_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
|
unsafe { loop_stack.last_mut().unwrap_unchecked() }.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 => {
|
FlatAtom::LoopEnds => {
|
||||||
let popped = loop_stack.pop().unwrap();
|
let popped = unsafe { loop_stack.pop().unwrap_unchecked() };
|
||||||
if stack_history.len() > 1 {
|
if stack_history.len() > 1 {
|
||||||
match CurrentStackDiscriminants::from(
|
match WrapperDiscriminants::from(
|
||||||
stack_history.get(stack_history.len() - 2).unwrap(),
|
stack_history.get(stack_history.len() - 2).unwrap(),
|
||||||
) {
|
) {
|
||||||
CurrentStackDiscriminants::Loop => &mut loop_stack,
|
WrapperDiscriminants::Loop => &mut loop_stack,
|
||||||
CurrentStackDiscriminants::Tuple => &mut tuple_stack,
|
WrapperDiscriminants::Tuple => &mut tuple_stack,
|
||||||
CurrentStackDiscriminants::Slope => &mut slope_stack,
|
WrapperDiscriminants::Slope => &mut slope_stack,
|
||||||
}
|
}
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push(Atom::Loop(
|
.push(Atom::Loop(
|
||||||
match stack_history.pop().unwrap() {
|
match stack_history.pop().unwrap() {
|
||||||
CurrentStack::Loop(n) => n,
|
Wrapper::Loop(n) => n,
|
||||||
_ => unreachable!("this one is proven to be a loop"),
|
_ => unreachable!("this one is proven to be a loop"),
|
||||||
},
|
},
|
||||||
popped,
|
popped,
|
||||||
|
@ -62,7 +79,7 @@ fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Vec<Atom> {
|
||||||
} else {
|
} else {
|
||||||
result.push(Atom::Loop(
|
result.push(Atom::Loop(
|
||||||
match stack_history.pop().unwrap() {
|
match stack_history.pop().unwrap() {
|
||||||
CurrentStack::Loop(n) => n,
|
Wrapper::Loop(n) => n,
|
||||||
_ => unreachable!("this one is proven to be a loop"),
|
_ => unreachable!("this one is proven to be a loop"),
|
||||||
},
|
},
|
||||||
popped,
|
popped,
|
||||||
|
@ -71,44 +88,48 @@ fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Vec<Atom> {
|
||||||
}
|
}
|
||||||
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 in a loop"),
|
|
||||||
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 in a loop"),
|
|
||||||
FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment),
|
FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment),
|
||||||
},
|
},
|
||||||
CurrentStackDiscriminants::Tuple => match atom {
|
Some(WrapperDiscriminants::Tuple) => match atom {
|
||||||
FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)),
|
FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)),
|
||||||
FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest),
|
FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest),
|
||||||
FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere),
|
FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere),
|
||||||
FlatAtom::Modifier(m) => {
|
FlatAtom::Modifier(m) => tuple_stack.last_mut().unwrap().push(Atom::Modifier(m)),
|
||||||
tuple_stack.last_mut().unwrap().push(Atom::Modifier(m))
|
|
||||||
}
|
|
||||||
FlatAtom::QuickModifier(q) => {
|
FlatAtom::QuickModifier(q) => {
|
||||||
tuple_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
|
tuple_stack.last_mut().unwrap().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 in a tuple"),
|
|
||||||
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 => {
|
FlatAtom::TupleEnds => {
|
||||||
let popped = tuple_stack.pop().unwrap();
|
let popped = tuple_stack.pop().unwrap();
|
||||||
if stack_history.len() > 1 {
|
if stack_history.len() > 1 {
|
||||||
match CurrentStackDiscriminants::from(
|
match WrapperDiscriminants::from(
|
||||||
stack_history.get(stack_history.len() - 2).unwrap(),
|
stack_history.get(stack_history.len() - 2).unwrap(),
|
||||||
) {
|
) {
|
||||||
CurrentStackDiscriminants::Loop => &mut loop_stack,
|
WrapperDiscriminants::Loop => &mut loop_stack,
|
||||||
CurrentStackDiscriminants::Tuple => &mut tuple_stack,
|
WrapperDiscriminants::Tuple => &mut tuple_stack,
|
||||||
CurrentStackDiscriminants::Slope => &mut slope_stack,
|
WrapperDiscriminants::Slope => &mut slope_stack,
|
||||||
}
|
}
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -122,63 +143,65 @@ fn inflate(mut flat_atoms: Vec<FlatAtom>) -> Vec<Atom> {
|
||||||
}
|
}
|
||||||
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 in a tuple"),
|
|
||||||
FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment),
|
FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment),
|
||||||
},
|
},
|
||||||
CurrentStackDiscriminants::Slope => match atom {
|
Some(WrapperDiscriminants::Slope) => match atom {
|
||||||
FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)),
|
FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)),
|
||||||
FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest),
|
FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest),
|
||||||
FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere),
|
FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere),
|
||||||
FlatAtom::Modifier(m) => {
|
FlatAtom::Modifier(m) => slope_stack.last_mut().unwrap().push(Atom::Modifier(m)),
|
||||||
slope_stack.last_mut().unwrap().push(Atom::Modifier(m))
|
|
||||||
}
|
|
||||||
FlatAtom::QuickModifier(q) => {
|
FlatAtom::QuickModifier(q) => {
|
||||||
slope_stack.last_mut().unwrap().push(Atom::QuickModifier(q))
|
slope_stack.last_mut().unwrap().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 => {
|
FlatAtom::SlopeEnds => {
|
||||||
let popped = slope_stack.pop().unwrap();
|
let popped = slope_stack.pop().unwrap();
|
||||||
if stack_history.len() > 1 {
|
if stack_history.len() > 1 {
|
||||||
match CurrentStackDiscriminants::from(
|
match WrapperDiscriminants::from(
|
||||||
stack_history.get(stack_history.len() - 2).unwrap(),
|
stack_history.get(stack_history.len() - 2).unwrap(),
|
||||||
) {
|
) {
|
||||||
CurrentStackDiscriminants::Loop => &mut loop_stack,
|
WrapperDiscriminants::Loop => &mut loop_stack,
|
||||||
CurrentStackDiscriminants::Tuple => &mut tuple_stack,
|
WrapperDiscriminants::Tuple => &mut tuple_stack,
|
||||||
CurrentStackDiscriminants::Slope => &mut slope_stack,
|
WrapperDiscriminants::Slope => &mut slope_stack,
|
||||||
}
|
}
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push(match stack_history.pop().unwrap() {
|
.push(match stack_history.pop().unwrap() {
|
||||||
CurrentStack::Slope(m, i) => Atom::Slope(m, i, popped),
|
Wrapper::Slope(m, i) => Atom::Slope(m, i, popped),
|
||||||
_ => unreachable!("this one is proven to be a slope"),
|
_ => unreachable!("this one is proven to be a slope"),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
result.push(match stack_history.pop().unwrap() {
|
result.push(match stack_history.pop().unwrap() {
|
||||||
CurrentStack::Slope(m, i) => Atom::Slope(m, i, popped),
|
Wrapper::Slope(m, i) => Atom::Slope(m, i, popped),
|
||||||
_ => unreachable!("this one is proven to be a slope"),
|
_ => 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),
|
||||||
},
|
},
|
||||||
}
|
None => match atom {
|
||||||
} else {
|
|
||||||
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),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Ok(result)
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
Instruction::new(
|
||||||
parser
|
parser
|
||||||
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
|
.parse(FASTEVAL_INSTRUCTION, &mut slab.ps)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.from(&slab.ps)
|
.from(&slab.ps)
|
||||||
.compile(&slab.ps, &mut slab.cs)
|
.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,8 +189,9 @@ mod inflate {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
fn mixed_mismatched_end() {
|
||||||
fn mixed_panic() {
|
assert_eq!(
|
||||||
|
Err(InflateError::MismatchedEnd(WrapperDiscriminants::Slope)),
|
||||||
inflate(vec![
|
inflate(vec![
|
||||||
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
|
FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()),
|
||||||
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
|
FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()),
|
||||||
|
@ -205,6 +208,7 @@ mod inflate {
|
||||||
FlatAtom::LoopEnds,
|
FlatAtom::LoopEnds,
|
||||||
FlatAtom::SlopeEnds,
|
FlatAtom::SlopeEnds,
|
||||||
FlatAtom::SlopeEnds,
|
FlatAtom::SlopeEnds,
|
||||||
]);
|
])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/// TODO: remove clap, use only a file or standard in
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
mod bng;
|
mod bng;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue