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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//! Do not use this crate directly. Instead, use [`::macro_rules_attribute`](
//! https://docs.rs/macro_rules_attribute)

extern crate proc_macro; use ::proc_macro::*;

/// Applies the given `macro_rules!` macro to the decorated item.
///
/// This, as with any `proc_macro_attribute`, **consumes** the item it
/// decorates: it is the `macro_rules!` macro job to generate it (_it is thus
/// able to modify it_!).
///
/// For a version with "read-only" access to the item it decorates, see
/// [`macro_rules_derive`].
///
/// # Example
///
/// Deriving getters for a (non-generic) `struct`:
///
/// ```rust
/// # macro_rules! ignore {($($tt:tt)*) => () }
/// # ignore! {
/// #[macro_use]
/// extern crate macro_rules_attribute;
/// # }
///
/// macro_rules! make_getters {(
///     $(#[$struct_meta:meta])*
///     $struct_vis:vis
///     struct $StructName:ident {
///         $(
///             $(#[$field_meta:meta])*
///             $field_vis:vis // this visibility will be applied to the getters instead
///             $field_name:ident : $field_ty:ty
///         ),* $(,)?
///     }
/// ) => (
///     // First, generate the struct definition we have been given, but with
///     // private fields instead.
///     $(#[$struct_meta])*
///     $struct_vis
///     struct $StructName {
///         $(
///             $(#[$field_meta])*
///             // notice the lack of visibility => private fields
///             $field_name: $field_ty,
///         )*
///     }
///
///     // Then, implement the getters:
///     impl $StructName {
///         $(
///             #[inline]
///             $field_vis
///             fn $field_name (self: &'_ Self)
///                 -> &'_ $field_ty
///             {
///                 &self.$field_name
///             }
///         )*
///     }
/// )}
///
/// mod example {
/// # use ::macro_rules_attribute_proc_macro::macro_rules_attribute;
///     #[macro_rules_attribute(make_getters!)]
///     /// The macro handles meta attributes such as docstrings
///     pub
///     struct Person {
///         pub
///         name: String,
///
///         pub
///         age: u8,
///     }
/// }
/// use example::Person;
///
/// fn is_new_born (person: &'_ Person)
///     -> bool
/// {
///     // person.age == 0
///     // ^ error[E0616]: field `age` of struct `example::Person` is private
///     *person.age() == 0
/// }
/// ```
#[proc_macro_attribute] pub
fn macro_rules_attribute (
    attrs: TokenStream,
    input: TokenStream,
)   -> TokenStream
{
    // check that `attrs` is indeed of the form `$macro_name:path !`
    {
        // FIXME: do this properly
        match attrs.clone().into_iter().last() {
            | Some(TokenTree::Punct(ref punct))
                if punct.as_char() == '!'
            => {},

            | _ => {
                panic!("Expected a parameter of the form `macro_name !`");
            },
        }
    }
    let mut ret = attrs;
    ret.extend(::std::iter::once(
        TokenTree::Group(Group::new(
            Delimiter::Brace,
            // FIXME: directly using `input` makes the token stream be seen
            // as a single token tree by the declarative macro !??
            input.into_iter().collect(),
        ))
    ));
    #[cfg(feature = "verbose-expansions")]
    eprintln!("{}", ret);
    ret
}

/// Applies the given `macro_rules!` macro to the decorated item.
///
/// This, as with any `#[derive(...)]`, **does not consume** the item it
/// decorates: instead, it only generates code on top of it.
///
/// # Example
///
/// Implementing `Into<Int>` for a given `#[repr(Int)]` `enum`:
///
/// ```rust
/// # macro_rules! ignore {($($tt:tt)*) => () }
/// # ignore! {
/// #[macro_use]
/// extern crate macro_rules_attribute;
/// # }
///
/// macro_rules! ToInteger {(
///     #[repr($Int:ident)]
///     $(#[$enum_meta:meta])*
///     $pub:vis
///     enum $Enum:ident {
///         $(
///             $Variant:ident $(= $value:expr)?
///         ),* $(,)?
///     }
/// ) => (
///     impl ::core::convert::From<$Enum> for $Int {
///         #[inline]
///         fn from (x: $Enum)
///             -> Self
///         {
///             x as _
///         }
///     }
/// )}
///
/// # use ::macro_rules_attribute_proc_macro::macro_rules_derive;
/// #[macro_rules_derive(ToInteger!)]
/// #[repr(u32)]
/// enum Bool {
///     False,
///     True,
/// }
///
/// fn main ()
/// {
///     assert_eq!(u32::from(Bool::False), 0);
///     assert_eq!(u32::from(Bool::True), 1);
///     // assert_eq!(u8::from(Bool::False), 0);
///     // ^ error[E0277]: the trait bound `u8: std::convert::From<main::Bool>` is not satisfied
/// }
/// ```
#[proc_macro_attribute] pub
fn macro_rules_derive (
    attrs: TokenStream,
    input: TokenStream,
)   -> TokenStream
{
    let mut ret = input.clone();
    ret.extend(macro_rules_attribute(attrs, input));
    ret
}