implement Clone for Expression (really works)

This commit is contained in:
Breval Ferrari 2025-05-23 15:25:45 +02:00
parent 7e831c40ac
commit 4bc2e2b8ee

View file

@ -6,7 +6,7 @@ use std::{
use derive_new::new; use derive_new::new;
use derive_wrapper::{AsRef, From}; use derive_wrapper::{AsRef, From};
use fasteval::{Compiler, Evaler, Instruction, Slab}; use fasteval::{Compiler, EvalNamespace, Evaler, Instruction, Slab};
use thiserror::Error; use thiserror::Error;
const SAMPLE_RATE: u16 = 48000; const SAMPLE_RATE: u16 = 48000;
@ -118,13 +118,16 @@ impl Token for Slope<'_> {
#[derive(new)] #[derive(new)]
#[cfg_attr(any(debug_assertions, test), derive(Debug))] #[cfg_attr(any(debug_assertions, test), derive(Debug))]
pub struct Expression { pub struct Expression {
from: String,
pub(crate) instruction: Instruction, pub(crate) instruction: Instruction,
pub(crate) slab: Slab, pub(crate) slab: Slab,
} }
impl Clone for Expression { impl Clone for Expression {
fn clone(&self) -> Self { 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)? .parse(s, &mut slab.ps)?
.from(&slab.ps) .from(&slab.ps)
.compile(&slab.ps, &mut slab.cs); .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; *self.get_mut('t')? += 1f64 / SAMPLE_RATE as f64;
{ {
let changes = self let changes = self
.slopes .slopes
.iter() .iter()
.map( .map(
|(v, Expression { instruction, slab })| -> Result<(char, f64), fasteval::Error> { |(
Ok(( v,
*v, Expression {
instruction.eval( from: _,
instruction,
slab, slab,
&mut self },
.variables )|
.iter() -> Result<(char, f64), fasteval::Error> {
.map(|(c, f)| (c.to_string(), *f)) Ok((
.collect::<BTreeMap<String, f64>>(), *v,
)?, instruction.eval(
)) slab,
}, &mut self
) .variables
.collect::<Result<Vec<(char, f64)>, fasteval::Error>>()?; .iter()
.map(|(c, f)| (c.to_string(), *f))
.collect::<BTreeMap<String, f64>>(),
)?,
))
},
)
.collect::<Result<Vec<(char, f64)>, fasteval::Error>>()?;
for (variable, new_value) in changes { for (variable, new_value) in changes {
*self.get_mut(variable)? = new_value; *self.get_mut(variable)? = new_value;
} }
@ -229,11 +244,20 @@ impl Context {
.collect() .collect()
} }
pub fn eval( pub fn eval(&self, expr: &Expression) -> Result<f64, fasteval::Error> {
self.eval_with(expr, &mut self.namespace_generator())
}
pub fn eval_with(
&self, &self,
Expression { instruction, slab }: &Expression, Expression {
from: _,
instruction,
slab,
}: &Expression,
ns: &mut impl EvalNamespace,
) -> Result<f64, fasteval::Error> { ) -> Result<f64, fasteval::Error> {
instruction.eval(&slab, &mut self.namespace_generator()) instruction.eval(&slab, ns)
} }
pub fn render(&mut self, n: Option<u8>) -> Result<Vec<f64>, CompilerError> { pub fn render(&mut self, n: Option<u8>) -> Result<Vec<f64>, CompilerError> {
@ -242,13 +266,8 @@ impl Context {
let mut result = Vec::new(); let mut result = Vec::new();
while (self.current_length()? * SAMPLE_RATE as f64) > *self.get('t')? - curr_t { while (self.current_length()? * SAMPLE_RATE as f64) > *self.get('t')? - curr_t {
{ {
let Expression { instruction, slab } = &self.instrument; result.push(self.eval_with(&self.instrument, &mut {
result.push(instruction.eval(&slab, &mut { let mut map = self.namespace_generator();
let mut map = self
.variables
.iter()
.map(|(c, f)| (format!("{c}"), *f))
.collect::<BTreeMap<String, f64>>();
map.insert('n'.to_string(), note as f64); map.insert('n'.to_string(), note as f64);
map 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());
}
}