1#![deny(warnings, clippy::all)]
2#![allow(non_snake_case)] mod derive_enum;
4mod derive_struct;
5
6use proc_macro::TokenStream;
7use proc_macro2::TokenStream as TokenStream2;
8use quote::quote;
9use syn::{parse_macro_input, DeriveInput};
10
11#[derive(Clone)]
12struct Types {
13 LogixTypeDescriptor: TokenStream2,
14 LogixValueDescriptor: TokenStream2,
15 LogixType: TokenStream2,
16 LogixVfs: TokenStream2,
17 LogixParser: TokenStream2,
18 ParseResult: TokenStream2,
19 ParseError: TokenStream2,
20 Wanted: TokenStream2,
21 Value: TokenStream2,
22 Token: TokenStream2,
23 Brace: TokenStream2,
24 Delim: TokenStream2,
25}
26
27struct Shared<'a> {
28 prefix: TokenStream2,
29 type_name_str: String,
30 type_name: syn::Ident,
31 types: Types,
32 impl_gen: syn::ImplGenerics<'a>,
33}
34
35#[proc_macro_derive(LogixType)]
37pub fn impl_logix_type(input: TokenStream) -> TokenStream {
38 let input = parse_macro_input!(input as DeriveInput);
39
40 let (impl_gen, ty_gen, where_gen) = input.generics.split_for_impl();
41
42 let shared = Shared {
43 prefix: quote!(),
44 type_name_str: input.ident.to_string(),
45 type_name: input.ident,
46 types: Types {
47 LogixTypeDescriptor: quote!(::logix_type::type_trait::LogixTypeDescriptor),
48 LogixValueDescriptor: quote!(::logix_type::type_trait::LogixValueDescriptor),
49 LogixType: quote!(::logix_type::LogixType),
50 LogixVfs: quote!(::logix_vfs::LogixVfs),
51 LogixParser: quote!(::logix_type::LogixParser),
52 ParseResult: quote!(::logix_type::error::Result),
53 ParseError: quote!(::logix_type::error::ParseError),
54 Wanted: quote!(::logix_type::error::Wanted),
55 Value: quote!(::logix_type::type_trait::Value),
56 Token: quote!(::logix_type::token::Token),
57 Brace: quote!(::logix_type::token::Brace),
58 Delim: quote!(::logix_type::token::Delim),
59 },
60 impl_gen,
61 };
62 let Shared {
63 prefix: _,
64 type_name_str,
65 type_name,
66 types:
67 Types {
68 LogixTypeDescriptor,
69 LogixType,
70 LogixVfs,
71 LogixParser,
72 ParseResult,
73 Value,
74 ..
75 },
76 impl_gen,
77 } = &shared;
78
79 let (value_desc, parse) = match input.data {
80 syn::Data::Struct(data) => derive_struct::do_any(&shared, data.fields, false),
81 syn::Data::Enum(data) => derive_enum::do_any(&shared, data.variants),
82 syn::Data::Union(..) => return quote!(compile_error!("Union is not supported")).into(),
83 };
84
85 let descriptor = quote!(
86 #LogixTypeDescriptor {
87 name: #type_name_str,
88 doc: "",
89 value: #value_desc,
90 }
91 );
92
93 let tokens = quote! {
94 impl #impl_gen #LogixType for #type_name #ty_gen #where_gen {
95 fn descriptor() -> &'static #LogixTypeDescriptor{
96 static RET: std::sync::OnceLock<#LogixTypeDescriptor> = std::sync::OnceLock::new();
98 RET.get_or_init(|| #descriptor)
99 }
100
101 fn default_value() -> Option<Self> {
102 None
103 }
104
105 fn logix_parse<FS: #LogixVfs>(p: &mut #LogixParser<FS>) -> #ParseResult<#Value<Self>> {
106 #parse
107 }
108 }
109 };
110
111 tokens.into()
112}