Blocks and flowgraph
This commit is contained in:
12
oxydsp-flowgraph-macros/Cargo.toml
Normal file
12
oxydsp-flowgraph-macros/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "oxydsp-flowgraph-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.106"
|
||||
quote = "1.0.45"
|
||||
syn = "2.0.117"
|
||||
124
oxydsp-flowgraph-macros/src/lib.rs
Normal file
124
oxydsp-flowgraph-macros/src/lib.rs
Normal file
@ -0,0 +1,124 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{DeriveInput, Fields, Ident, parse_macro_input};
|
||||
|
||||
#[proc_macro_derive(BlockIO, attributes(input, output))]
|
||||
pub fn derive_block_io(item: TokenStream) -> TokenStream
|
||||
{
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
let inputs;
|
||||
let outputs;
|
||||
match input.data
|
||||
{
|
||||
syn::Data::Struct(data_struct) =>
|
||||
{
|
||||
inputs = derive_block_get_marked_idents(&data_struct.fields, "input");
|
||||
outputs = derive_block_get_marked_idents(&data_struct.fields, "output");
|
||||
}
|
||||
syn::Data::Enum(_) | syn::Data::Union(_) => unimplemented!("Enum/Unions not supported"),
|
||||
}
|
||||
|
||||
let struct_name = input.ident;
|
||||
let func_set_index = derive_block_set_index(&inputs, &outputs);
|
||||
let func_get_successors = derive_block_get_successors(&outputs);
|
||||
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics oxydsp_flowgraph::block::BlockIO for #struct_name #type_generics
|
||||
#where_clause
|
||||
{
|
||||
#func_set_index
|
||||
|
||||
#func_get_successors
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
fn derive_block_get_successors(outputs: &Vec<Ident>) -> proc_macro2::TokenStream
|
||||
{
|
||||
quote! {
|
||||
fn get_successors(&self) -> Vec<oxydsp_flowgraph::edge::BlockIOIndex>
|
||||
{
|
||||
let mut successors = Vec::new();
|
||||
#(
|
||||
if let Some(next) = self.#outputs.get_consumer_block()
|
||||
{
|
||||
successors.push(next);
|
||||
}
|
||||
)*
|
||||
successors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_block_io_count(inputs: &Vec<Ident>, outputs: &Vec<Ident>) -> proc_macro2::TokenStream
|
||||
{
|
||||
let input_count = inputs.len();
|
||||
let output_count = outputs.len();
|
||||
quote! {
|
||||
fn input_count(&self) -> usize
|
||||
{
|
||||
#input_count
|
||||
}
|
||||
|
||||
fn output_count(&self) -> usize
|
||||
{
|
||||
#output_count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_block_set_index(inputs: &Vec<Ident>, outputs: &Vec<Ident>) -> proc_macro2::TokenStream
|
||||
{
|
||||
quote! {
|
||||
fn set_index(&self, block_index: usize)
|
||||
{
|
||||
use oxydsp_flowgraph::edge::BlockIOIndex;
|
||||
let mut counter = 0;
|
||||
#(
|
||||
self.#inputs.set_block_index(
|
||||
BlockIOIndex
|
||||
{
|
||||
block_index,
|
||||
port_index: counter,
|
||||
}
|
||||
);
|
||||
counter += 1;
|
||||
)*
|
||||
counter = 0;
|
||||
#(
|
||||
self.#outputs.set_block_index(
|
||||
BlockIOIndex
|
||||
{
|
||||
block_index,
|
||||
port_index: counter,
|
||||
}
|
||||
);
|
||||
counter += 1;
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_block_get_marked_idents<S: AsRef<str>>(
|
||||
fields: &Fields,
|
||||
required_attribute: S,
|
||||
) -> Vec<Ident>
|
||||
{
|
||||
let mut idents = vec![];
|
||||
for field in fields
|
||||
{
|
||||
'inner: for attribute in field.attrs.iter()
|
||||
{
|
||||
if let Some(name) = attribute.meta.path().segments.first()
|
||||
&& name.ident == required_attribute.as_ref()
|
||||
{
|
||||
idents.push(field.ident.clone().unwrap());
|
||||
break 'inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idents
|
||||
}
|
||||
Reference in New Issue
Block a user