1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
//! Derive macros.

extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;

// #[cql::derive::Obj]
#[proc_macro_attribute]
#[allow(non_snake_case)]
pub fn Obj(_attr: TokenStream, inp: TokenStream) -> TokenStream {
    let mut out = obj_struct(inp.clone());
    out.extend(obj_impl(inp));
    out.into()
}

fn obj_struct(inp: TokenStream) -> TokenStream {
    let item = syn::parse_macro_input!(inp as syn::ItemStruct);
    let (ident, vis) = (&item.ident, &item.vis);

    let other_fields = match item.fields {
        syn::Fields::Named(ref fields) => Some(&fields.named),
        syn::Fields::Unit => None,
        syn::Fields::Unnamed(_) => panic!("syn::Fields::Unnamed not supported"),
    };

    let out = quote! {
        #vis struct #ident {
            proxy: crate::obj::ObjProxy,
            #other_fields
        }
    };

    out.into()
}

fn obj_impl(inp: TokenStream) -> TokenStream {
    let item = syn::parse_macro_input!(inp as syn::ItemStruct);
    let ident = &item.ident;

    let out = quote! {
        impl #ident {
            pub fn take_ch(&mut self) -> cql::c_h {
                self.proxy.take_ch()
            }
        }
    };

    out.into()
}

// #[cql::derive::Wgt]
#[proc_macro_attribute]
#[allow(non_snake_case)]
pub fn Wgt(_attr: TokenStream, inp: TokenStream) -> TokenStream {
    let mut out = wgt_struct(inp.clone());
    out.extend(wgt_impl(inp));
    out.into()
}

fn wgt_struct(inp: TokenStream) -> TokenStream {
    let item = syn::parse_macro_input!(inp as syn::ItemStruct);
    let (ident, vis) = (&item.ident, &item.vis);

    let other_fields = match item.fields {
        syn::Fields::Named(ref fields) => Some(&fields.named),
        syn::Fields::Unit => None,
        syn::Fields::Unnamed(_) => panic!("syn::Fields::Unnamed not supported"),
    };

    let out = quote! {
        #vis struct #ident {
            proxy: crate::wgt::WgtProxy,
            #other_fields
        }
    };

    out.into()
}

fn wgt_impl(inp: TokenStream) -> TokenStream {
    let item = syn::parse_macro_input!(inp as syn::ItemStruct);
    let ident = &item.ident;

    let out = quote! {
        impl crate::wgt::WgtObj for #ident {
            fn wgt(self) -> crate::wgt::Wgt {
                crate::wgt::Wgt::#ident(Box::new(self))
            }

            fn proxy(&self) -> &crate::wgt::WgtProxy {
                &self.proxy
            }

            fn proxy_mut(&mut self) -> &mut crate::wgt::WgtProxy {
                &mut self.proxy
            }
        }
    };

    out.into()
}

// eof