From fa49625f7f2edc4fcc3e1dbab6388f829cf60ae8 Mon Sep 17 00:00:00 2001 From: Breval Ferrari Date: Wed, 21 May 2025 12:00:35 +0200 Subject: [PATCH] test setup, silence & expression tests --- src/compiler.rs | 40 ++++++++++++++++++++++++++++++++++++--- src/parser.rs | 50 ++++++++++++++++++++++++++----------------------- 2 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 3c96842..3eea276 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,37 +1,61 @@ -use std::{collections::HashMap, str::FromStr}; +use std::{collections::HashMap, fmt::Debug, str::FromStr}; use derive_new::new; +use derive_wrapper::{AsRef, From}; use fasteval::{Compiler, Instruction, Slab}; -pub type TokenVec<'a> = Vec>; +#[derive(From, AsRef)] +#[cfg_attr(test, derive(Debug))] +pub struct TokenVec<'a>(Vec>); +#[cfg(not(test))] pub trait Token { fn apply(&self, context: Context) -> Context { todo!() } } +#[cfg(test)] +pub trait Token: Debug { + fn apply(&self, context: Context) -> Context { + todo!() + } +} + +#[cfg(test)] +impl PartialEq for TokenVec<'_> { + fn eq(&self, other: &Self) -> bool { + format!("{self:?}") == format!("{other:?}") + } +} + #[derive(Clone, Copy)] +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Silence; impl Token for Silence {} #[derive(Clone, Copy)] +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Marker; impl Token for Marker {} #[derive(Clone, Copy)] +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Note(pub u8); impl Token for Note {} +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct VariableChange(pub char, pub Expression); impl Token for VariableChange {} +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Loop<'a>(pub LoopCount, pub TokenVec<'a>); +#[cfg_attr(test, derive(Debug, PartialEq))] pub enum LoopCount { Litteral(usize), Variable(char), @@ -45,16 +69,18 @@ impl Default for LoopCount { impl Token for Loop<'_> {} +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Tuplet<'a>(pub TokenVec<'a>); impl Token for Tuplet<'_> {} +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Slope<'a>(pub &'a VariableChange, pub TokenVec<'a>); impl Token for Slope<'_> {} #[derive(new)] -#[cfg_attr(debug_assertions, derive(Debug))] +#[cfg_attr(any(debug_assertions, test), derive(Debug))] pub struct Expression { pub(crate) instruction: Instruction, pub(crate) slab: Slab, @@ -66,6 +92,13 @@ impl Clone for Expression { } } +#[cfg(test)] +impl PartialEq for Expression { + fn eq(&self, other: &Self) -> bool { + format!("{self:?}") == format!("{other:?}") + } +} + impl FromStr for Expression { type Err = fasteval::Error; fn from_str(s: &str) -> Result { @@ -78,6 +111,7 @@ impl FromStr for Expression { } } +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct Context { pub result: Vec, pub variables: HashMap, diff --git a/src/parser.rs b/src/parser.rs index 549af90..653b43f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -21,7 +21,8 @@ use nom::{ use nom_locate::LocatedSpan; use crate::compiler::{ - Expression, Loop, LoopCount, Marker, Note, Silence, Slope, Token, Tuplet, VariableChange, + Expression, Loop, LoopCount, Marker, Note, Silence, Slope, Token, TokenVec, Tuplet, + VariableChange, }; #[derive(Builder)] @@ -33,9 +34,7 @@ pub struct Parser<'i, 'n, 's, 'v> { } impl<'i, 's> Parser<'i, '_, 's, '_> { - pub fn parse_all( - &self, - ) -> Result>, Error>> { + pub fn parse_all(&self) -> Result, Error>> { token_parser(self) .parse_complete(LocatedSpan::new(self.input)) .finish() @@ -45,7 +44,7 @@ impl<'i, 's> Parser<'i, '_, 's, '_> { fn token_parser<'a, 's, I>( parser: &Parser<'_, '_, 's, '_>, -) -> impl NomParser>, Error = nom::error::Error> +) -> impl NomParser, Error = nom::error::Error> where I: Input + AsRef + for<'z> nom::Compare<&'z str>, ::Item: AsChar, @@ -70,6 +69,7 @@ where )), space_or_comment(), )) + .map(Into::into) } fn into_box<'a>(token: impl Token + 'a) -> Box { @@ -279,22 +279,26 @@ mod tests { } } - // #[test] - // fn silence() { - // let parser = |input: &'static str| Silence::parser().parse(input.into()); - // let mut working_cases = vec![(".", ()), ".dd", ".."]; - // let mut not_working_cases = vec![]; - // for (test, expected) in working_cases.drain(..) { - // let output = parser(test); - // if let Ok((result)) = output { - // assert_eq!(expected, result); - // } else { - // panic!("result was not Ok: {output:?}"); - // } - // } - // for test in not_working_cases.drain(..) { - // let output = parser(test); - // assert!(output.is_err(), "result was not Err: {output:?}"); - // } - // } + #[test] + fn silence() { + let parser = |input| Silence::parser().parse(input); + let mut working_cases = vec![ + (".", ("", Silence)), + (".dd", ("dd", Silence)), + ("..", (".", Silence)), + ]; + let mut not_working_cases = vec!["", ",", "d.", " "]; + for (test, expected) in working_cases.drain(..) { + let output = parser(test); + if let Ok(result) = output { + assert_eq!(expected, result); + } else { + panic!("result was not Ok: {output:?}"); + } + } + for test in not_working_cases.drain(..) { + let output = parser(test); + assert!(output.is_err(), "result was not Err: {output:?}"); + } + } }