fecund_font_flounder_macros/lib.rs
1#![allow(unused_imports)]
2
3use proc_macro2::TokenStream;
4use quote::{quote, quote_spanned};
5use syn::spanned::Spanned;
6use syn::{
7 parse_macro_input, parse_quote, Data, DeriveInput, Fields, GenericParam, Generics, Index, Type,
8};
9use utils::{add_gen, div_gen, sub_gen};
10
11
12mod utils;
13
14
15///Naively implements the Add and AddAssign traits, adding every field to each other.
16#[proc_macro_attribute]
17pub fn naive_add(_att: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
18
19 let mut ory_item = item.clone();
20
21 let input = parse_macro_input!(item as DeriveInput);
22 let name = input.ident;
23
24 let adding = add_gen(&input.data);
25
26 let expanded = quote!{
27
28 impl std::ops::AddAssign for #name{
29 fn add_assign(&mut self, rhs: Self) {
30 #adding
31 }
32 }
33
34 impl std::ops::Add for #name {
35 type Output = #name;
36 fn add(self, rhs: Self) -> Self::Output {
37 let mut mself = self;
38 mself += rhs;
39 mself
40 }
41 }
42
43 };
44
45
46 let t = proc_macro::TokenStream::from(expanded);
47
48 ory_item.extend(t);
49 ory_item
50
51}
52
53
54
55
56
57///Naively implements the Sub and SubAssign traits, adding every field to each other.
58#[proc_macro_attribute]
59pub fn naive_sub(_att: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
60
61 let mut ory_item = item.clone();
62
63 let input = parse_macro_input!(item as DeriveInput);
64 let name = input.ident;
65
66 let subing = sub_gen(&input.data);
67
68 let expanded = quote!{
69
70 impl std::ops::SubAssign for #name {
71 fn sub_assign(&mut self, rhs: Self) {
72 #subing
73 }
74 }
75
76 impl std::ops::Sub for #name {
77 type Output = #name;
78 fn sub(self, rhs: Self) -> Self::Output {
79 let mut mself = self;
80 mself -= rhs;
81 mself
82 }
83 }
84
85 };
86
87
88 let t = proc_macro::TokenStream::from(expanded);
89
90 ory_item.extend(t);
91 ory_item
92
93}
94
95
96
97/// Naively implements the Div and DivAssign traits. Allows division by the given type in the
98/// attribute.
99#[proc_macro_attribute]
100pub fn naive_div(att: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
101
102 let mut ory_item = item.clone();
103
104 let input = parse_macro_input!(item as DeriveInput);
105 let att = parse_macro_input!(att as Type);
106
107 let name = input.ident;
108
109 let dividing = div_gen(&input.data);
110
111 let expanded = quote!{
112
113 impl std::ops::DivAssign< #att > for #name {
114 fn div_assign(&mut self, rhs: #att ) {
115 #dividing
116 }
117 }
118 impl std::ops::Div< #att > for #name {
119 type Output = #name;
120 fn div(self, rhs: #att) -> Self::Output {
121 let mut mself = self;
122 mself /= rhs;
123 mself
124 }
125 }
126
127 };
128
129
130 let t = proc_macro::TokenStream::from(expanded);
131
132 ory_item.extend(t);
133 ory_item
134
135}
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156//// Add a bound `T: HeapSize` to every type parameter T.
157//fn add_trait_bounds(mut generics: Generics) -> Generics {
158 //for param in &mut generics.params {
159 //if let GenericParam::Type(ref mut type_param) = *param {
160 //type_param.bounds.push(parse_quote!(heapsize::HeapSize));
161 //}
162 //}
163 //generics
164//}
165
166//// Generate an expression to sum up the heap size of each field.
167//fn heap_size_sum(data: &Data) -> TokenStream {
168 //match *data {
169 //Data::Struct(ref data) => {
170 //match data.fields {
171 //Fields::Named(ref fields) => {
172 //// Expands to an expression like
173 ////
174 //// 0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size()
175 ////
176 //// but using fully qualified function call syntax.
177 ////
178 //// We take some care to use the span of each `syn::Field` as
179 //// the span of the corresponding `heap_size_of_children`
180 //// call. This way if one of the field types does not
181 //// implement `HeapSize` then the compiler's error message
182 //// underlines which field it is. An example is shown in the
183 //// readme of the parent directory.
184 //let recurse = fields.named.iter().map(|f| {
185 //let name = &f.ident;
186 //quote_spanned! {f.span()=>
187 //heapsize::HeapSize::heap_size_of_children(&self.#name)
188 //}
189 //});
190 //quote! {
191 //0 #(+ #recurse)*
192 //}
193 //}
194 //Fields::Unnamed(ref fields) => {
195 //// Expands to an expression like
196 ////
197 //// 0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size()
198 //let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
199 //let index = Index::from(i);
200 //quote_spanned! {f.span()=>
201 //heapsize::HeapSize::heap_size_of_children(&self.#index)
202 //}
203 //});
204 //quote! {
205 //0 #(+ #recurse)*
206 //}
207 //}
208 //Fields::Unit => {
209 //// Unit structs cannot own more than 0 bytes of heap memory.
210 //quote!(0)
211 //}
212 //}
213 //}
214 //Data::Enum(_) | Data::Union(_) => unimplemented!(),
215 //}
216//}