Structure the Harmony core to rely on a DAG for declaring & executing Scores
This commit is contained in:
11
harmony-derive/Cargo.toml
Normal file
11
harmony-derive/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "harmony-derive"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0.40"
|
||||
syn = "2.0.106"
|
||||
58
harmony-derive/src/lib.rs
Normal file
58
harmony-derive/src/lib.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Attribute, Ident, ItemStruct, parse_macro_input};
|
||||
|
||||
// This was an attempt to get a derive macro to simplify implementing new scores
|
||||
//
|
||||
// The goal was to get a syntax similar to this:
|
||||
// #[derive(Score)]
|
||||
// #[interpret(MyInterpret)]
|
||||
// #[dependencies(OtherScore("foo"), OtherScore("bar"), ExtraScore("baz"))]
|
||||
// struct MyScore {
|
||||
// foo: LinkedValue<String>,
|
||||
// bar: LinkedValue<String>,
|
||||
// baz: LinkedValue<Vec<u32>>,
|
||||
// }
|
||||
|
||||
#[proc_macro_derive(Score, attributes(interpret))]
|
||||
pub fn score_derive(input: TokenStream) -> TokenStream {
|
||||
let input_struct = parse_macro_input!(input as ItemStruct);
|
||||
let score_name = &input_struct.ident;
|
||||
|
||||
let interpret_name = get_interpret_name(&input_struct.attrs);
|
||||
|
||||
let expanded = quote! {
|
||||
#[derive(Debug)]
|
||||
pub struct #interpret_name {
|
||||
score: #score_name,
|
||||
}
|
||||
|
||||
impl<T: Topology> crate::Score<T> for #score_name {
|
||||
fn create_interpret(&self) -> Box<dyn crate::Interpret<T>> {
|
||||
Box::new(#interpret_name {
|
||||
score: self.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
fn get_interpret_name(attrs: &Vec<Attribute>) -> Ident {
|
||||
for attr in attrs {
|
||||
if attr.path().is_ident("interpret") {
|
||||
let nested_meta = attr
|
||||
.parse_args_with(
|
||||
syn::punctuated::Punctuated::<syn::Ident, syn::Token![,]>::parse_terminated,
|
||||
)
|
||||
.unwrap();
|
||||
if let Some(ident) = nested_meta.first() {
|
||||
return ident.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return a default or panic if the attribute is not found
|
||||
Ident::new("DefaultInterpret", proc_macro::Span::call_site().into())
|
||||
}
|
||||
Reference in New Issue
Block a user