From 4102b936863a4901314e3f6c00d4413d9c718ecd Mon Sep 17 00:00:00 2001 From: Breval Ferrari Date: Fri, 23 May 2025 20:06:28 +0200 Subject: [PATCH] rest of Token.apply impls, Default for everyone --- src/compiler.rs | 129 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 14 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 4e73574..4fdcb8a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,4 +1,5 @@ use std::{ + any::{Any, TypeId}, collections::{BTreeMap, HashMap}, fmt::Debug, str::FromStr, @@ -7,21 +8,46 @@ use std::{ use derive_new::new; use derive_wrapper::{AsRef, From}; use fasteval::{Compiler, EvalNamespace, Evaler, Instruction, Slab}; +use lazy_static::lazy_static; use thiserror::Error; const SAMPLE_RATE: u16 = 48000; -#[derive(From, AsRef)] +#[derive(From, AsRef, Default)] #[cfg_attr(test, derive(Debug))] pub struct TokenVec<'a>(pub(crate) Vec>); +pub trait Type { + fn type_id(&self) -> TypeId; +} + +macro_rules! impl_type { + ($name:ty) => { + impl Type for $name { + fn type_id(&self) -> std::any::TypeId { + ::type_id(self) + } + } + }; +} + +macro_rules! impl_type_life { + ($name:ty) => { + impl Type for $name { + fn type_id(&self) -> TypeId { + <$name as Any>::type_id(&Default::default()) + } + } + }; +} + #[cfg(not(test))] -pub trait Token { +pub trait Token: Type { fn apply(&self, context: Context) -> Result; } #[cfg(test)] -pub trait Token: Debug { +pub trait Token: Debug + Type { fn apply(&self, context: Context) -> Result; } @@ -32,10 +58,12 @@ impl PartialEq for TokenVec<'_> { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Silence; +impl_type!(Silence); + impl Token for Silence { fn apply(&self, mut context: Context) -> Result { context.render(None)?; @@ -43,10 +71,12 @@ impl Token for Silence { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Marker; +impl_type!(Marker); + impl Token for Marker { fn apply(&self, mut context: Context) -> Result { context.result.clear(); @@ -54,10 +84,12 @@ impl Token for Marker { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Note(pub u8); +impl_type!(Note); + impl Token for Note { fn apply(&self, mut context: Context) -> Result { let mut next = context.render(Some(self.0))?; @@ -66,9 +98,12 @@ impl Token for Note { } } +#[derive(Clone, Default)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct VariableChange(pub char, pub Expression); +impl_type!(VariableChange); + impl Token for VariableChange { fn apply(&self, mut context: Context) -> Result { *context.get_mut(self.0)? = context.eval(&self.1)?; @@ -76,9 +111,12 @@ impl Token for VariableChange { } } +#[derive(Default)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Loop<'a>(pub LoopCount, pub TokenVec<'a>); +impl_type_life!(Loop<'_>); + #[cfg_attr(test, derive(Debug, PartialEq))] pub enum LoopCount { Litteral(usize), @@ -92,30 +130,92 @@ impl Default for LoopCount { } impl Token for Loop<'_> { - fn apply(&self, context: Context) -> Result { - todo!() + fn apply(&self, mut context: Context) -> Result { + let mut old_result = context.result.clone(); + let count = match self.0 { + LoopCount::Litteral(n) => n, + LoopCount::Variable(v) => *context.get(v)? as usize, + }; + context.result.clear(); + let new_context = self + .1 + .0 + .iter() + .try_fold(context, |context, t| t.apply(context))?; + old_result.append(&mut new_context.result.repeat(count)); + Ok(Context { + result: old_result, + ..new_context + }) } } +#[derive(Default)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Tuplet<'a>(pub TokenVec<'a>); +impl_type_life!(Tuplet<'_>); + impl Token for Tuplet<'_> { - fn apply(&self, context: Context) -> Result { - todo!() + fn apply(&self, mut context: Context) -> Result { + let mut old_result = context.result.clone(); + context.result.clear(); + let mut new_context = self + .0 + .0 + .iter() + .try_fold(context, |context, t| t.apply(context))?; + let len = new_context.result.len(); + new_context.result = new_context + .result + .into_iter() + .step_by( + len / self + .0 + .0 + .iter() + .filter(|t| { + t.as_ref().type_id() == Type::type_id(&Note(0u8)) + || t.as_ref().type_id() == Type::type_id(&Silence) + }) + .count(), + ) + .collect(); + old_result.append(&mut new_context.result); + Ok(Context { + result: old_result, + ..new_context + }) } } #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Slope<'a>(pub &'a VariableChange, pub TokenVec<'a>); -impl Token for Slope<'_> { - fn apply(&self, context: Context) -> Result { - todo!() +lazy_static! { + static ref VARIABLE_CHANGE_DEFAULT: VariableChange = Default::default(); +} + +impl Type for Slope<'_> { + fn type_id(&self) -> TypeId { + ::type_id(&Slope(&VARIABLE_CHANGE_DEFAULT, Default::default())) } } -#[derive(new)] +impl Token for Slope<'_> { + fn apply(&self, mut context: Context) -> Result { + context.slopes.insert(self.0.0, self.0.1.clone()); + context = self + .1 + .0 + .iter() + .try_fold(context, |context, t| t.apply(context))?; + context.slopes.remove(&self.0.0); + Ok(context) + } +} + +#[derive(new, Default)] #[cfg_attr(any(debug_assertions, test), derive(Debug))] pub struct Expression { from: String, @@ -154,6 +254,7 @@ impl FromStr for Expression { } } +#[derive(Clone)] #[cfg_attr(test, derive(Debug, PartialEq))] pub struct Context { pub result: Vec,