1#[macro_use]
2extern crate quote;
3#[macro_use]
4extern crate syn;
5
6extern crate proc_macro;
7extern crate proc_macro2;
8
9use proc_macro::TokenStream;
10use quote::TokenStreamExt;
11use syn::DeriveInput;
12
13mod aspect;
14mod components;
15mod services;
16mod system;
17mod systems;
18
19#[proc_macro_derive(Aspect, attributes(aspect, components))]
20pub fn derive_aspect(input: TokenStream) -> TokenStream {
21 let ast = parse_macro_input!(input as DeriveInput);
23
24 let result = aspect::impl_aspect(ast);
26
27 result.into()
30}
31
32#[proc_macro_derive(ComponentManager, attributes(hot, cold))]
33pub fn derive_components(input: TokenStream) -> TokenStream {
34 let ast = parse_macro_input!(input as DeriveInput);
36
37 let result = components::impl_components(ast);
39
40 result.into()
42}
43
44#[proc_macro_derive(ServiceManager)]
45pub fn derive_services(input: TokenStream) -> TokenStream {
46 let ast = parse_macro_input!(input as DeriveInput);
48
49 let result = services::impl_services(ast);
51
52 result.into()
54}
55
56#[proc_macro_derive(
57 System,
58 attributes(
59 data,
60 system_type,
61 process,
62 aspect,
63 aspect_a,
64 aspect_b,
65 interval,
66 timed_interval,
67 activated,
68 reactivated,
69 deactivated
70 )
71)]
72pub fn derive_system(input: TokenStream) -> TokenStream {
73 let ast = parse_macro_input!(input as DeriveInput);
75
76 let result = system::impl_system(ast);
78
79 result.into()
81}
82
83#[proc_macro_derive(SystemManager, attributes(data, passive))]
84pub fn derive_systems(input: TokenStream) -> TokenStream {
85 let ast = parse_macro_input!(input as DeriveInput);
87
88 let result = systems::impl_systems(ast);
90
91 result.into()
93}
94
95fn improper_attr_format(attr: &str, module: &str) -> ! {
96 panic!(
97 "{} was not in the correct format. Please refer to the {} \
98 module documentation for more information.",
99 attr, module
100 )
101}
102
103fn read_path_item<F>(attr: &syn::Meta, fail: F) -> String
104where
105 F: FnOnce(),
106{
107 match attr {
108 syn::Meta::Word(word) => word.to_string(),
109 syn::Meta::List(list) => {
110 let items = &list.nested;
111 if items.len() != 1 {
112 fail();
113 unreachable!();
114 }
115
116 match items[0] {
117 syn::NestedMeta::Literal(syn::Lit::Str(ref value)) => value.value(),
118 syn::NestedMeta::Meta(syn::Meta::Word(ref word)) => word.to_string(),
119 _ => {
120 fail();
121 unreachable!();
122 }
123 }
124 }
125 syn::Meta::NameValue(syn::MetaNameValue {
126 lit: syn::Lit::Str(ref value),
127 ..
128 }) => value.value(),
129 _ => {
130 fail();
131 unreachable!();
132 }
133 }
134}
135
136fn quote_path(path: &str) -> proc_macro2::TokenStream {
137 let mut tokens = proc_macro2::TokenStream::new();
138 for (i, part) in path.split("::").enumerate() {
139 use proc_macro2::{Ident, Punct, Spacing, Span};
140 if i != 0 {
141 tokens.append_all(&[
142 Punct::new(':', Spacing::Joint),
143 Punct::new(':', Spacing::Joint),
144 ]);
145 }
146 if part.len() > 0 {
147 tokens.append(Ident::new(part, Span::call_site()));
148 }
149 }
150 tokens
151}