diff --git a/Cargo.toml b/Cargo.toml index fec5756..4fddb38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,12 @@ strum = { version = "0.27", features = ["derive"] } thiserror = "2.0" rodio = { version = "0.20", default-features = false, optional = true } dasp_sample = { version = "0", optional = true } +log = "0" +env_logger = { version = "0", optional = true } [features] default = ["bin", "all-formats"] -bin = ["anyhow", "clap", "rodio", "dasp_sample"] +bin = ["anyhow", "clap", "rodio", "dasp_sample", "env_logger"] all-formats = ["mp3", "wav", "flac", "raw"] mp3 = ["mp3lame-encoder"] wav = ["hound"] diff --git a/src/cli/main.rs b/src/cli/main.rs index 253b52c..f4ed3f6 100644 --- a/src/cli/main.rs +++ b/src/cli/main.rs @@ -12,6 +12,7 @@ use dasp_sample::Sample; use rodio::{OutputStream, Sink, buffer::SamplesBuffer}; fn main() -> anyhow::Result<()> { + env_logger::init(); let cli = Cli::parse(); use Cli::*; match cli { diff --git a/src/compiler.rs b/src/compiler.rs index 9d2a117..071e4cd 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,5 +1,5 @@ use std::{ - any::{Any, TypeId}, + any::{Any, TypeId, type_name}, collections::{BTreeMap, HashMap}, f64, fmt::Debug, @@ -10,6 +10,7 @@ use cfg_if::cfg_if; use derive_new::new; use derive_wrapper::{AsRef, From}; use fasteval::{Compiler as _, EvalNamespace, Evaler, Instruction, Slab}; +use log::trace; use thiserror::Error; cfg_if! { @@ -20,8 +21,7 @@ cfg_if! { } } -#[derive(From, AsRef, Default)] -#[cfg_attr(test, derive(Debug))] +#[derive(Debug, From, AsRef, Default)] pub struct TokenVec(pub(crate) Vec>); impl IntoIterator for TokenVec { @@ -57,12 +57,6 @@ where } } -#[cfg(not(test))] -pub trait Token: Type { - fn apply(&self, context: Context) -> Result; -} - -#[cfg(test)] pub trait Token: Debug + Type { fn apply(&self, context: Context) -> Result; } @@ -74,43 +68,46 @@ impl PartialEq for TokenVec { } } -#[derive(Clone, Copy, Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct Silence; impl Token for Silence { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); let mut next = context.render(None)?; context.result.append(&mut next); Ok(context) } } -#[derive(Clone, Copy, Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct Marker; impl Token for Marker { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); context.result.clear(); Ok(context) } } -#[derive(Clone, Copy, Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct Note(pub u8); impl Token for Note { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); let mut next = context.render(Some(self.0))?; context.result.append(&mut next); Ok(context) } } -#[derive(Clone, Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Clone, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct VariableChange(pub char, pub Expression); impl AsRef for VariableChange { @@ -121,16 +118,18 @@ impl AsRef for VariableChange { impl Token for VariableChange { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); *context.get_mut(self.0)? = context.eval(self.1.as_ref())?; Ok(context) } } -#[derive(Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct Loop(pub LoopCount, pub TokenVec); -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug)] +#[cfg_attr(test, derive(PartialEq))] pub enum LoopCount { Litteral(usize), Variable(char), @@ -144,6 +143,7 @@ impl Default for LoopCount { impl Token for Loop { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); let mut old_result = context.result.clone(); let count = match self.0 { LoopCount::Litteral(n) => n, @@ -163,12 +163,13 @@ impl Token for Loop { } } -#[derive(Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct Tuplet(pub TokenVec); impl Token for Tuplet { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); let mut old_result = context.result.clone(); context.result.clear(); let mut new_context = self @@ -200,12 +201,13 @@ impl Token for Tuplet { } } -#[derive(new, Default)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, new, Default)] +#[cfg_attr(test, derive(PartialEq))] pub struct Slope(pub VariableChange, pub TokenVec); impl Token for Slope { fn apply(&self, mut context: Context) -> Result { + trace!("⚡ {}", type_name::()); context .slopes .push((self.0.as_ref().0, self.0.as_ref().1.as_ref().clone())); @@ -219,8 +221,7 @@ impl Token for Slope { } } -#[derive(new, Default)] -#[cfg_attr(any(debug_assertions, test), derive(Debug))] +#[derive(Debug, new, Default)] pub struct Expression { from: String, pub(crate) instruction: Instruction, @@ -263,8 +264,8 @@ impl FromStr for Expression { } } -#[derive(Clone, new)] -#[cfg_attr(test, derive(Debug, PartialEq))] +#[derive(Debug, Clone, new)] +#[cfg_attr(test, derive(PartialEq))] pub struct Context { note_length_variable: char, note_index_variable: char, diff --git a/src/parser.rs b/src/parser.rs index 9b64364..3987905 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,8 @@ -use std::{borrow::Borrow, collections::BTreeMap, marker::PhantomData}; +use std::{any::type_name, borrow::Borrow, collections::BTreeMap, marker::PhantomData}; use derive_new::new; use fasteval::Evaler; +use log::{debug, error}; use nom::{ AsChar, Compare, Finish, IResult, Input, Parser as NomParser, branch::alt, @@ -51,6 +52,7 @@ where &self, input: &'a str, ) -> Result>> { + debug!("parsing input \"{input}\""); token_parser(self) .parse_complete(LocatedSpan::new(input)) .finish() @@ -72,6 +74,7 @@ where SV: Borrow, V: AsRef<[char]>, { + debug!("making the TOKEN parser"); let space_or_comment = || { value( (), @@ -104,6 +107,7 @@ impl Silence { I: Input, ::Item: AsChar, { + debug!("making the {} parser", type_name::()); value(Self, char('.')) } } @@ -114,6 +118,7 @@ impl Marker { I: Input, ::Item: AsChar, { + debug!("making the {} parser", type_name::()); value(Marker, char('%')) } } @@ -127,20 +132,23 @@ impl Note { NS: AsRef, I: Input + for<'z> Compare<&'z str>, { + debug!("making the {} parser", type_name::()); let notes = { let mut sorted = notes .into_iter() .map(|s| s.as_ref().to_string()) .enumerate() .collect::>(); + debug!("got notes {sorted:?}"); sorted.sort_by_key(|(_, n)| n.len()); + sorted.reverse(); + debug!("sorted to {sorted:?}"); sorted }; move |input: I| { let mut parsers: Vec IResult>> = notes .clone() .drain(..) - .rev() .map(|(i, t)| { Box::new(move |input: I| { value(Note(i as u8), tag(t.clone().as_ref())).parse(input) @@ -159,6 +167,7 @@ impl VariableChange { ::Item: AsChar, V: AsRef<[char]>, { + debug!("making the {} parser", type_name::()); move |i: I| { preceded( char('$'), @@ -186,6 +195,7 @@ impl Loop { SV: Borrow, V: AsRef<[char]>, { + debug!("making the {} parser", type_name::()); move |input| { delimited( char('('), @@ -225,6 +235,7 @@ impl Tuplet { SV: Borrow, V: AsRef<[char]>, { + debug!("making the {} parser", type_name::()); |input| { delimited(char('['), token_parser(parser), char(']')) .map(Self) @@ -248,6 +259,7 @@ impl Slope { SV: Borrow, V: AsRef<[char]>, { + debug!("making the {} parser", type_name::()); move |input| { let slopes = { let mut vec = parser @@ -256,11 +268,13 @@ impl Slope { .into_iter() .map(|(s1, s2)| (s1.as_ref().to_string(), s2.borrow().clone())) .collect::>(); + debug!("got slopes {vec:?}"); vec.sort_by_key(|(name, _)| name.len()); + vec.reverse(); + debug!("sorted to {vec:?}"); vec }; - let iter: std::iter::Rev> = - slopes.into_iter().rev(); + let iter: std::vec::IntoIter<(String, VariableChange)> = slopes.into_iter(); delimited( char('{'), alt(iter @@ -286,22 +300,41 @@ where V: IntoIterator, C: Borrow, { + debug!("making the Expression parser"); let variables: Vec<(String, f64)> = variables .into_iter() .map(|v| (v.borrow().to_string(), 0.0)) .collect(); + debug!("got variables {variables:?}"); move |input: I| { take_while_map(|i: I| { - i.as_ref().parse::().ok().and_then(|e| { - e.instruction - .eval( - &e.slab, - &mut BTreeMap::from_iter(variables.clone().drain(..)), + i.as_ref() + .parse::() + .inspect_err(|e| { + error!( + "failed parsing expression {expr} with {err}", + expr = i.as_ref(), + err = e ) - .ok() - .is_some() - .then_some(e) - }) + }) + .ok() + .and_then(|e| { + e.instruction + .eval( + &e.slab, + &mut BTreeMap::from_iter(variables.clone().drain(..)), + ) + .inspect_err(|e| { + error!( + "failed expression evaluation {expr:?} with {err}", + expr = e, + err = e + ) + }) + .ok() + .is_some() + .then_some(e) + }) }) .parse(input) } @@ -314,16 +347,22 @@ where I: Input + Copy, F: Fn(I) -> Option, { + debug!("making take_while_map parser"); move |input: I| { let mut len = input.input_len(); + debug!( + "take_while_map will now match biggest munch from the rest of the input ({len} elements)" + ); while len > 0 { let result = take(len).map_opt(&cond).parse(input); if result.is_ok() { + debug!("found a match using {len} elements"); return result; } else { len -= 1; } } + error!("take_while_map found no match"); Err(nom::Err::Incomplete(nom::Needed::Unknown)) } }