Blocks and flowgraph

This commit is contained in:
2026-03-11 18:40:58 +01:00
parent d0773783dc
commit 13d060776f
2 changed files with 136 additions and 0 deletions

View 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"

View 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
}