1#![allow(clippy::all)]
2
3macro_rules! flat_mod {
4 ($($i:ident),+) => {
5 $(
6 mod $i;
7 pub use $i::*;
8 )+
9 }
10}
11
12use cl::Link;
13use derive_syn_parse::Parse;
14use error::Error;
15use proc_macro2::{Ident, TokenStream};
16use quote::{format_ident, quote, ToTokens};
17use syn::{
18 parse_macro_input, parse_quote, punctuated::Punctuated, DeriveInput, Generics, ItemStatic,
19 ItemType, Meta, Visibility, WhereClause, WherePredicate,
20};
21
22use crate::cl::Blaze;
23
24mod cl;
25mod context;
26mod error;
27mod num;
28mod utils;
29
30#[proc_macro_derive(NumOps, attributes(uninit))]
31pub fn derive_num_ops(items: proc_macro::TokenStream) -> proc_macro::TokenStream {
32 let items = parse_macro_input!(items as DeriveInput);
33 num::derive_ops(items).into()
34}
35
36#[proc_macro_derive(NumOpsAssign, attributes(uninit))]
37pub fn derive_num_ops_assign(items: proc_macro::TokenStream) -> proc_macro::TokenStream {
38 let items = parse_macro_input!(items as DeriveInput);
39 num::derive_ops_assign(items).into()
40}
41
42#[proc_macro_attribute]
43pub fn global_context(
44 _attrs: proc_macro::TokenStream,
45 items: proc_macro::TokenStream,
46) -> proc_macro::TokenStream {
47 let items = parse_macro_input!(items as ItemStatic);
48 context::global_context(items).into()
49}
50
51#[proc_macro]
52pub fn error(items: proc_macro::TokenStream) -> proc_macro::TokenStream {
53 let input = parse_macro_input!(items as Error);
54 input.to_token_stream().into()
55}
56
57#[proc_macro_attribute]
58pub fn newtype(
59 attrs: proc_macro::TokenStream,
60 items: proc_macro::TokenStream,
61) -> proc_macro::TokenStream {
62 fn extra_where(where_generics: Option<&WhereClause>, extra: WherePredicate) -> WhereClause {
63 match where_generics {
64 Some(x) => {
65 let mut x = x.clone();
66 x.predicates.push(extra);
67 return x;
68 }
69
70 None => {
71 let mut predicates = Punctuated::new();
72 predicates.push(extra);
73
74 WhereClause {
75 where_token: Default::default(),
76 predicates,
77 }
78 }
79 }
80 }
81
82 let inner_vis = parse_macro_input!(attrs as Visibility);
83 let ItemType {
84 attrs,
85 vis,
86 ident,
87 generics,
88 ty,
89 semi_token,
90 ..
91 } = parse_macro_input!(items as ItemType);
92 let (impl_generics, ty_generics, where_generics) = generics.split_for_impl();
93
94 let consumer_generics = extra_where(
95 r#where_generics,
96 parse_quote! { #ty: blaze_rs::event::Consumer },
97 );
98 let debug_generics = extra_where(r#where_generics, parse_quote! { #ty: ::core::fmt::Debug });
99 let clone_generics = extra_where(r#where_generics, parse_quote! { #ty: ::core::clone::Clone });
100 let copy_generics = extra_where(r#where_generics, parse_quote! { #ty: ::core::marker::Copy });
101
102 quote! {
103 #(#attrs)*
104 #vis struct #ident #impl_generics (#inner_vis #ty) #semi_token
105
106 impl #impl_generics blaze_rs::event::Consumer for #ident #ty_generics #consumer_generics {
107 type Output = <#ty as blaze_rs::event::Consumer>::Output;
108
109 #[inline(always)]
110 unsafe fn consume (self) -> blaze_rs::prelude::Result<Self::Output> {
111 <#ty as blaze_rs::event::Consumer>::consume(self.0)
112 }
113 }
114
115 impl #impl_generics ::core::fmt::Debug for #ident #ty_generics #debug_generics {
116 #[inline(always)]
117 fn fmt (&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
118 ::core::fmt::Debug::fmt(&self.0, f)
119 }
120 }
121
122 impl #impl_generics ::core::clone::Clone for #ident #ty_generics #clone_generics {
123 #[inline(always)]
124 fn clone (&self) -> Self {
125 Self(::core::clone::Clone::clone(&self.0))
126 }
127 }
128
129 impl #impl_generics ::core::marker::Copy for #ident #ty_generics #copy_generics {}
130 }
131 .into()
132}
133
134#[proc_macro]
135pub fn join_various_blocking(items: proc_macro::TokenStream) -> proc_macro::TokenStream {
136 #[derive(Parse)]
137 struct Input(#[call(Punctuated::parse_terminated)] Punctuated<syn::Expr, syn::Token![,]>);
138
139 let item = parse_macro_input!(items as Input).0.into_iter();
140 let idx = (0..item.len()).map(syn::Index::from).collect::<Vec<_>>();
141
142 quote! {{
143 let v = (#(blaze_rs::event::Event::into_parts(#item)),*);
144 let (raw, consumer) = ([#(v.#idx.0),*], (#(v.#idx.1),*));
145 blaze_rs::event::RawEvent::join_all_by_ref(&raw).and_then(|_| unsafe {
146 Ok((
147 #(
148 blaze_rs::event::Consumer::consume(consumer.#idx)?
149 ),*
150 ))
151 })
152 }}
153 .into()
154}
155
156#[proc_macro_attribute]
157pub fn blaze(
158 attrs: proc_macro::TokenStream,
159 items: proc_macro::TokenStream,
160) -> proc_macro::TokenStream {
161 let ident = parse_macro_input!(attrs as BlazeIdent);
162 let items = parse_macro_input!(items as Blaze);
163
164 let mut inner = None;
165 for attr in &items.attrs {
166 if attr.path.is_ident(&format_ident!("link")) {
167 let tokens = attr.tokens.clone().into();
168 let link = parse_macro_input!(tokens as Link);
169 inner = Some(link.meta);
170 break;
171 }
172 }
173
174 if let Some(inner) = inner {
175 return cl::blaze_c(ident.vis, ident.ident, ident.generics, items, inner).into();
176 }
177
178 panic!("No source code specified");
179}
180
181#[proc_macro_attribute]
182pub fn docfg(
183 attrs: proc_macro::TokenStream,
184 items: proc_macro::TokenStream,
185) -> proc_macro::TokenStream {
186 let attrs = parse_macro_input!(attrs as Meta);
187 let items = parse_macro_input!(items as TokenStream);
188
189 quote! {
190 #[cfg_attr(docsrs, doc(cfg(#attrs)))]
191 #[cfg(#attrs)]
192 #items
193 }
194 .into()
195}
196
197#[derive(Parse)]
198struct BlazeIdent {
199 vis: Visibility,
200 ident: Ident,
201 generics: Generics,
202}