-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathfunctional_contribution.rs
More file actions
115 lines (107 loc) · 3.55 KB
/
Copy pathfunctional_contribution.rs
File metadata and controls
115 lines (107 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use quote::quote;
use syn::{DeriveInput, Ident};
pub(crate) fn expand_functional_contribution(
input: DeriveInput,
) -> syn::Result<proc_macro2::TokenStream> {
let ident = input.ident;
let variants = match input.data {
syn::Data::Enum(syn::DataEnum { ref variants, .. }) => variants,
_ => panic!("this derive macro only works on enums"),
};
let functional_contribution = impl_functional_contribution(&ident, variants);
let display = impl_display(&ident, variants);
let from = impl_from(&ident, variants);
Ok(quote! {
#functional_contribution
#display
#from
})
}
fn impl_functional_contribution(
ident: &Ident,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
let weight_functions = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.weight_functions(temperature)
}
});
let weight_functions_pdgt = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.weight_functions_pdgt(temperature)
}
});
let helmholtz_energy_density = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.helmholtz_energy_density(temperature, weighted_densities)
}
});
quote! {
impl FunctionalContribution for #ident {
fn weight_functions<N: DualNum<f64> + Copy+ScalarOperand>(&self, temperature: N) -> WeightFunctionInfo<N> {
match self {
#(#weight_functions,)*
}
}
fn weight_functions_pdgt<N: DualNum<f64> + Copy+ScalarOperand>(&self, temperature: N) -> WeightFunctionInfo<N> {
match self {
#(#weight_functions_pdgt,)*
}
}
fn helmholtz_energy_density<N: DualNum<f64> + Copy+ScalarOperand>(
&self,
temperature: N,
weighted_densities: ArrayView2<N>,
) -> EosResult<Array1<N>> {
match self {
#(#helmholtz_energy_density,)*
}
}
}
}
}
fn impl_display(
ident: &Ident,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
let fmt = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.fmt(f)
}
});
quote! {
impl std::fmt::Display for #ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#(#fmt,)*
}
}
}
}
}
fn impl_from(
ident: &Ident,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
let from = variants.iter().map(|v| {
let name = &v.ident;
let syn::Fields::Unnamed(syn::FieldsUnnamed { unnamed, .. }) = &v.fields else {
panic!("All variants must be tuple structs!")
};
let inner = &unnamed.first().unwrap().ty;
quote! {
impl From<#inner> for #ident {
fn from(variant: #inner) -> Self {
Self::#name(variant)
}
}
}
});
quote! {
#(#from)*
}
}