1 // Copyright © 2023 Collabora, Ltd.
2 // SPDX-License-Identifier: MIT
3
4 extern crate proc_macro;
5 extern crate proc_macro2;
6 #[macro_use]
7 extern crate quote;
8 extern crate syn;
9
10 use compiler_proc::as_slice::*;
11 use proc_macro::TokenStream;
12 use proc_macro2::{TokenStream as TokenStream2};
13 use syn::*;
14
15 #[proc_macro_derive(SrcsAsSlice, attributes(src_type))]
derive_srcs_as_slice(input: TokenStream) -> TokenStream16 pub fn derive_srcs_as_slice(input: TokenStream) -> TokenStream {
17 derive_as_slice(input, "Src", "src_type", "SrcType")
18 }
19
20 #[proc_macro_derive(DstsAsSlice, attributes(dst_type))]
derive_dsts_as_slice(input: TokenStream) -> TokenStream21 pub fn derive_dsts_as_slice(input: TokenStream) -> TokenStream {
22 derive_as_slice(input, "Dst", "dst_type", "DstType")
23 }
24
25 #[proc_macro_derive(DisplayOp)]
enum_derive_display_op(input: TokenStream) -> TokenStream26 pub fn enum_derive_display_op(input: TokenStream) -> TokenStream {
27 let DeriveInput { ident, data, .. } = parse_macro_input!(input);
28
29 if let Data::Enum(e) = data {
30 let mut fmt_dsts_cases = TokenStream2::new();
31 let mut fmt_op_cases = TokenStream2::new();
32 for v in e.variants {
33 let case = v.ident;
34 fmt_dsts_cases.extend(quote! {
35 #ident::#case(x) => x.fmt_dsts(f),
36 });
37 fmt_op_cases.extend(quote! {
38 #ident::#case(x) => x.fmt_op(f),
39 });
40 }
41 quote! {
42 impl DisplayOp for #ident {
43 fn fmt_dsts(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self {
45 #fmt_dsts_cases
46 }
47 }
48
49 fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 #fmt_op_cases
52 }
53 }
54 }
55 }
56 .into()
57 } else {
58 panic!("Not an enum type");
59 }
60 }
61
62 #[proc_macro_derive(FromVariants)]
derive_from_variants(input: TokenStream) -> TokenStream63 pub fn derive_from_variants(input: TokenStream) -> TokenStream {
64 let DeriveInput { ident, data, .. } = parse_macro_input!(input);
65 let enum_type = ident;
66
67 let mut impls = TokenStream2::new();
68
69 if let Data::Enum(e) = data {
70 for v in e.variants {
71 let var_ident = v.ident;
72 let from_type = match v.fields {
73 Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => unnamed,
74 _ => panic!("Expected Op(OpFoo)"),
75 };
76
77 let quote = quote! {
78 impl From<#from_type> for #enum_type {
79 fn from (op: #from_type) -> #enum_type {
80 #enum_type::#var_ident(op)
81 }
82 }
83 };
84
85 impls.extend(quote);
86 }
87 }
88
89 impls.into()
90 }
91