1#![feature(proc_macro_span)]
2moddef::moddef!(
3 flat (pub) mod {
4 },
5 flat (pub(crate)) mod {
6 state,
7 machine,
8 transition,
9 validators
10 }
11);
12
13use proc_macro::TokenStream;
14use crate::{ensure_machine_loaded, ensure_state_enum_loaded, MachinePath, StateModulePath};
15use syn::{ItemEnum, ItemImpl, ItemStruct, parse_macro_input};
16
17use module_path_extractor::get_pseudo_module_path;
18
19#[proc_macro_attribute]
20pub fn state(_attr: TokenStream, item: TokenStream) -> TokenStream {
21 let input = parse_macro_input!(item as ItemEnum);
22
23 if let Some(error) = validate_state_enum(&input) {
25 return error.into();
26 }
27
28 let enum_info = match EnumInfo::from_item_enum(&input) {
29 Ok(info) => info,
30 Err(err) => return err.to_compile_error().into(),
31 };
32
33 store_state_enum(&enum_info);
35
36 let expanded = generate_state_impls(&enum_info.module_path);
38
39 TokenStream::from(expanded)
40}
41
42#[proc_macro_attribute]
43pub fn machine(_attr: TokenStream, item: TokenStream) -> TokenStream {
44 let input = parse_macro_input!(item as ItemStruct);
45
46 let machine_info = MachineInfo::from_item_struct(&input);
47
48 if let Some(error) = validate_machine_struct(&input, &machine_info) {
50 return error.into();
51 }
52
53 store_machine_struct(&machine_info);
55
56 let expanded = generate_machine_impls(&machine_info);
58
59 TokenStream::from(expanded)
60}
61
62#[proc_macro_attribute]
63pub fn transition(
64 _attr: proc_macro::TokenStream,
65 item: proc_macro::TokenStream,
66) -> proc_macro::TokenStream {
67 let input = parse_macro_input!(item as ItemImpl);
68
69 let tr_impl = parse_transition_impl(&input);
71
72 let module_path = get_pseudo_module_path();
73
74 let state_path: StateModulePath = module_path.clone().into();
75 let machine_path: MachinePath = module_path.clone().into();
76 let _ = ensure_state_enum_loaded(&state_path);
77 let _ = ensure_machine_loaded(&machine_path);
78
79 let machine_map = get_machine_map().read().unwrap();
80
81 let machine_info = machine_map
84 .get(&machine_path)
85 .expect("Machine not found, even though we validated above");
86
87 if let Some(err) = validate_transition_functions(&tr_impl.functions, machine_info) {
88 return err.into();
89 }
90
91 let expanded = generate_transition_impl(&input, &tr_impl, machine_info, &module_path);
93
94 expanded.into()
97}
98
99#[proc_macro_attribute]
100pub fn validators(attr: TokenStream, item: TokenStream) -> TokenStream {
101 let module_path = get_pseudo_module_path();
102 parse_validators(attr, item, &module_path)
103}