rest of Token.apply impls, Default for everyone
This commit is contained in:
parent
4bc2e2b8ee
commit
4102b93686
1 changed files with 115 additions and 14 deletions
129
src/compiler.rs
129
src/compiler.rs
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
collections::{BTreeMap, HashMap},
|
collections::{BTreeMap, HashMap},
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
@ -7,21 +8,46 @@ use std::{
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use derive_wrapper::{AsRef, From};
|
use derive_wrapper::{AsRef, From};
|
||||||
use fasteval::{Compiler, EvalNamespace, Evaler, Instruction, Slab};
|
use fasteval::{Compiler, EvalNamespace, Evaler, Instruction, Slab};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
const SAMPLE_RATE: u16 = 48000;
|
const SAMPLE_RATE: u16 = 48000;
|
||||||
|
|
||||||
#[derive(From, AsRef)]
|
#[derive(From, AsRef, Default)]
|
||||||
#[cfg_attr(test, derive(Debug))]
|
#[cfg_attr(test, derive(Debug))]
|
||||||
pub struct TokenVec<'a>(pub(crate) Vec<Box<dyn Token + 'a>>);
|
pub struct TokenVec<'a>(pub(crate) Vec<Box<dyn Token + 'a>>);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
<Self as std::any::Any>::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))]
|
#[cfg(not(test))]
|
||||||
pub trait Token {
|
pub trait Token: Type {
|
||||||
fn apply(&self, context: Context) -> Result<Context, CompilerError>;
|
fn apply(&self, context: Context) -> Result<Context, CompilerError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub trait Token: Debug {
|
pub trait Token: Debug + Type {
|
||||||
fn apply(&self, context: Context) -> Result<Context, CompilerError>;
|
fn apply(&self, context: Context) -> Result<Context, CompilerError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,10 +58,12 @@ impl PartialEq for TokenVec<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Silence;
|
pub struct Silence;
|
||||||
|
|
||||||
|
impl_type!(Silence);
|
||||||
|
|
||||||
impl Token for Silence {
|
impl Token for Silence {
|
||||||
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
context.render(None)?;
|
context.render(None)?;
|
||||||
|
@ -43,10 +71,12 @@ impl Token for Silence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Marker;
|
pub struct Marker;
|
||||||
|
|
||||||
|
impl_type!(Marker);
|
||||||
|
|
||||||
impl Token for Marker {
|
impl Token for Marker {
|
||||||
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
context.result.clear();
|
context.result.clear();
|
||||||
|
@ -54,10 +84,12 @@ impl Token for Marker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Note(pub u8);
|
pub struct Note(pub u8);
|
||||||
|
|
||||||
|
impl_type!(Note);
|
||||||
|
|
||||||
impl Token for Note {
|
impl Token for Note {
|
||||||
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
let mut next = context.render(Some(self.0))?;
|
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))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct VariableChange(pub char, pub Expression);
|
pub struct VariableChange(pub char, pub Expression);
|
||||||
|
|
||||||
|
impl_type!(VariableChange);
|
||||||
|
|
||||||
impl Token for VariableChange {
|
impl Token for VariableChange {
|
||||||
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
*context.get_mut(self.0)? = context.eval(&self.1)?;
|
*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))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Loop<'a>(pub LoopCount, pub TokenVec<'a>);
|
pub struct Loop<'a>(pub LoopCount, pub TokenVec<'a>);
|
||||||
|
|
||||||
|
impl_type_life!(Loop<'_>);
|
||||||
|
|
||||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub enum LoopCount {
|
pub enum LoopCount {
|
||||||
Litteral(usize),
|
Litteral(usize),
|
||||||
|
@ -92,30 +130,92 @@ impl Default for LoopCount {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token for Loop<'_> {
|
impl Token for Loop<'_> {
|
||||||
fn apply(&self, context: Context) -> Result<Context, CompilerError> {
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
todo!()
|
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))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Tuplet<'a>(pub TokenVec<'a>);
|
pub struct Tuplet<'a>(pub TokenVec<'a>);
|
||||||
|
|
||||||
|
impl_type_life!(Tuplet<'_>);
|
||||||
|
|
||||||
impl Token for Tuplet<'_> {
|
impl Token for Tuplet<'_> {
|
||||||
fn apply(&self, context: Context) -> Result<Context, CompilerError> {
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
todo!()
|
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))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Slope<'a>(pub &'a VariableChange, pub TokenVec<'a>);
|
pub struct Slope<'a>(pub &'a VariableChange, pub TokenVec<'a>);
|
||||||
|
|
||||||
impl Token for Slope<'_> {
|
lazy_static! {
|
||||||
fn apply(&self, context: Context) -> Result<Context, CompilerError> {
|
static ref VARIABLE_CHANGE_DEFAULT: VariableChange = Default::default();
|
||||||
todo!()
|
}
|
||||||
|
|
||||||
|
impl Type for Slope<'_> {
|
||||||
|
fn type_id(&self) -> TypeId {
|
||||||
|
<Slope as Any>::type_id(&Slope(&VARIABLE_CHANGE_DEFAULT, Default::default()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(new)]
|
impl Token for Slope<'_> {
|
||||||
|
fn apply(&self, mut context: Context) -> Result<Context, CompilerError> {
|
||||||
|
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))]
|
#[cfg_attr(any(debug_assertions, test), derive(Debug))]
|
||||||
pub struct Expression {
|
pub struct Expression {
|
||||||
from: String,
|
from: String,
|
||||||
|
@ -154,6 +254,7 @@ impl FromStr for Expression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub result: Vec<f64>,
|
pub result: Vec<f64>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue