From 4bc2e2b8ee85764b0bd871c6b2bbb835161ec0c3 Mon Sep 17 00:00:00 2001 From: Breval Ferrari Date: Fri, 23 May 2025 15:25:45 +0200 Subject: [PATCH] implement Clone for Expression (really works) --- src/compiler.rs | 90 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 95c660b..4e73574 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -6,7 +6,7 @@ use std::{ use derive_new::new; use derive_wrapper::{AsRef, From}; -use fasteval::{Compiler, Evaler, Instruction, Slab}; +use fasteval::{Compiler, EvalNamespace, Evaler, Instruction, Slab}; use thiserror::Error; const SAMPLE_RATE: u16 = 48000; @@ -118,13 +118,16 @@ impl Token for Slope<'_> { #[derive(new)] #[cfg_attr(any(debug_assertions, test), derive(Debug))] pub struct Expression { + from: String, pub(crate) instruction: Instruction, pub(crate) slab: Slab, } impl Clone for Expression { fn clone(&self) -> Self { - unimplemented!() + self.from + .parse() + .expect(&format!("expression {self:?} have an invalid from")) } } @@ -143,7 +146,11 @@ impl FromStr for Expression { .parse(s, &mut slab.ps)? .from(&slab.ps) .compile(&slab.ps, &mut slab.cs); - Ok(Expression::new(instruction, slab)) + Ok(Expression::new( + s.trim_start().trim_end().to_string(), + instruction, + slab, + )) } } @@ -197,24 +204,32 @@ impl Context { *self.get_mut('t')? += 1f64 / SAMPLE_RATE as f64; { let changes = self - .slopes - .iter() - .map( - |(v, Expression { instruction, slab })| -> Result<(char, f64), fasteval::Error> { - Ok(( - *v, - instruction.eval( + .slopes + .iter() + .map( + |( + v, + Expression { + from: _, + instruction, slab, - &mut self - .variables - .iter() - .map(|(c, f)| (c.to_string(), *f)) - .collect::>(), - )?, - )) - }, - ) - .collect::, fasteval::Error>>()?; + }, + )| + -> Result<(char, f64), fasteval::Error> { + Ok(( + *v, + instruction.eval( + slab, + &mut self + .variables + .iter() + .map(|(c, f)| (c.to_string(), *f)) + .collect::>(), + )?, + )) + }, + ) + .collect::, fasteval::Error>>()?; for (variable, new_value) in changes { *self.get_mut(variable)? = new_value; } @@ -229,11 +244,20 @@ impl Context { .collect() } - pub fn eval( + pub fn eval(&self, expr: &Expression) -> Result { + self.eval_with(expr, &mut self.namespace_generator()) + } + + pub fn eval_with( &self, - Expression { instruction, slab }: &Expression, + Expression { + from: _, + instruction, + slab, + }: &Expression, + ns: &mut impl EvalNamespace, ) -> Result { - instruction.eval(&slab, &mut self.namespace_generator()) + instruction.eval(&slab, ns) } pub fn render(&mut self, n: Option) -> Result, CompilerError> { @@ -242,13 +266,8 @@ impl Context { let mut result = Vec::new(); while (self.current_length()? * SAMPLE_RATE as f64) > *self.get('t')? - curr_t { { - let Expression { instruction, slab } = &self.instrument; - result.push(instruction.eval(&slab, &mut { - let mut map = self - .variables - .iter() - .map(|(c, f)| (format!("{c}"), *f)) - .collect::>(); + result.push(self.eval_with(&self.instrument, &mut { + let mut map = self.namespace_generator(); map.insert('n'.to_string(), note as f64); map })?); @@ -264,3 +283,14 @@ impl Context { } } } + +#[cfg(test)] +mod tests { + use crate::compiler::Expression; + + #[test] + fn expression_is_clone() { + let expr: Expression = "1 + 5 / x".parse().unwrap(); + assert_eq!(expr, expr.clone()); + } +}