reflect_internal/
lib.rs

1#![allow(clippy::cast_lossless, clippy::enum_glob_use)]
2
3use proc_macro::TokenStream;
4use proc_macro2::{Span, TokenStream as TokenStream2};
5use quote::quote;
6use syn::parse::{Parse, ParseStream, Result};
7use syn::punctuated::Punctuated;
8use syn::{braced, parenthesized, parse_macro_input, token, Ident, Token};
9
10struct Input {
11    crates: Vec<ItemMod>,
12}
13
14enum Item {
15    Mod(ItemMod),
16    Type(ItemType),
17    Impl(ItemImpl),
18    Trait(ItemTrait),
19    Macro(ItemMacro),
20}
21
22struct ItemMod {
23    name: Ident,
24    items: Vec<Item>,
25}
26
27struct ItemType {
28    name: Ident,
29}
30
31struct ItemImpl {
32    name: Ident,
33    functions: Vec<Function>,
34}
35
36struct ItemTrait {
37    name: Ident,
38    functions: Vec<Function>,
39}
40
41struct Function {
42    name: Ident,
43    receiver: Receiver,
44    args: Vec<Type>,
45    ret: Option<Type>,
46}
47
48struct ItemMacro {
49    name: Ident,
50}
51
52enum Receiver {
53    None,
54    ByValue,
55    ByRef,
56    ByMut,
57}
58
59enum Type {
60    Tuple(Vec<Type>),
61    Ident(Ident),
62    TraitObject(Vec<Ident>),
63    Reference(Box<Type>),
64    ReferenceMut(Box<Type>),
65}
66
67impl Parse for Input {
68    fn parse(input: ParseStream) -> Result<Self> {
69        let mut crates = Vec::new();
70        while !input.is_empty() {
71            let lookahead = input.lookahead1();
72            if lookahead.peek(Token![use]) {
73                input.parse::<Token![use]>()?;
74            } else {
75                input.parse::<Token![extern]>()?;
76                input.parse::<Token![crate]>()?;
77            }
78            let name: Ident = input.parse()?;
79            let items = ItemMod::parse_items(input)?;
80            crates.push(ItemMod { name, items });
81        }
82        Ok(Input { crates })
83    }
84}
85
86impl Parse for Item {
87    fn parse(input: ParseStream) -> Result<Self> {
88        let lookahead = input.lookahead1();
89        if lookahead.peek(Token![mod]) {
90            input.parse().map(Item::Mod)
91        } else if lookahead.peek(Token![type]) {
92            input.parse().map(Item::Type)
93        } else if lookahead.peek(Token![impl]) {
94            input.parse().map(Item::Impl)
95        } else if lookahead.peek(Token![trait]) {
96            input.parse().map(Item::Trait)
97        } else if lookahead.peek(Token![macro]) {
98            input.parse().map(Item::Macro)
99        } else {
100            Err(lookahead.error())
101        }
102    }
103}
104
105impl ItemMod {
106    fn parse_items(input: ParseStream) -> Result<Vec<Item>> {
107        let content;
108        braced!(content in input);
109        let mut items = Vec::new();
110        while !content.is_empty() {
111            items.push(content.parse()?);
112        }
113        Ok(items)
114    }
115}
116
117impl Parse for ItemMod {
118    fn parse(input: ParseStream) -> Result<Self> {
119        input.parse::<Token![mod]>()?;
120        let name: Ident = input.parse()?;
121        let items = ItemMod::parse_items(input)?;
122        Ok(ItemMod { name, items })
123    }
124}
125
126impl Parse for ItemType {
127    fn parse(input: ParseStream) -> Result<Self> {
128        input.parse::<Token![type]>()?;
129        let name: Ident = input.parse()?;
130        input.parse::<Token![;]>()?;
131        Ok(ItemType { name })
132    }
133}
134
135impl Parse for ItemImpl {
136    fn parse(input: ParseStream) -> Result<Self> {
137        input.parse::<Token![impl]>()?;
138        let name: Ident = input.parse()?;
139
140        let content;
141        braced!(content in input);
142        let mut functions = Vec::new();
143        while !content.is_empty() {
144            functions.push(content.parse()?);
145        }
146
147        Ok(ItemImpl { name, functions })
148    }
149}
150
151impl Parse for ItemTrait {
152    fn parse(input: ParseStream) -> Result<Self> {
153        input.parse::<Token![trait]>()?;
154        let name: Ident = input.parse()?;
155
156        let content;
157        braced!(content in input);
158        let mut functions = Vec::new();
159        while !content.is_empty() {
160            functions.push(content.parse()?);
161        }
162
163        Ok(ItemTrait { name, functions })
164    }
165}
166
167impl Parse for Function {
168    fn parse(input: ParseStream) -> Result<Self> {
169        input.parse::<Token![fn]>()?;
170        let name: Ident = input.parse()?;
171
172        let argument_list;
173        parenthesized!(argument_list in input);
174
175        let receiver: Receiver = argument_list.parse()?;
176        if !(receiver.is_none() || argument_list.is_empty()) {
177            argument_list.parse::<Token![,]>()?;
178        }
179
180        let mut args = Vec::new();
181        while !argument_list.is_empty() {
182            args.push(argument_list.parse()?);
183            if argument_list.is_empty() {
184                break;
185            }
186            argument_list.parse::<Token![,]>()?;
187        }
188
189        let ret = if input.peek(Token![->]) {
190            input.parse::<Token![->]>()?;
191            Some(input.parse()?)
192        } else {
193            None
194        };
195
196        input.parse::<Token![;]>()?;
197
198        Ok(Function {
199            name,
200            receiver,
201            args,
202            ret,
203        })
204    }
205}
206
207impl Parse for Receiver {
208    fn parse(input: ParseStream) -> Result<Self> {
209        if input.peek(Token![self]) {
210            input.parse::<Token![self]>()?;
211            Ok(Receiver::ByValue)
212        } else if input.peek(Token![&]) && input.peek2(Token![self]) {
213            input.parse::<Token![&]>()?;
214            input.parse::<Token![self]>()?;
215            Ok(Receiver::ByRef)
216        } else if input.peek(Token![&]) && input.peek2(Token![mut]) && input.peek3(Token![self]) {
217            input.parse::<Token![&]>()?;
218            input.parse::<Token![mut]>()?;
219            input.parse::<Token![self]>()?;
220            Ok(Receiver::ByMut)
221        } else {
222            Ok(Receiver::None)
223        }
224    }
225}
226
227impl Parse for Type {
228    fn parse(input: ParseStream) -> Result<Self> {
229        let lookahead = input.lookahead1();
230        if lookahead.peek(token::Paren) {
231            let content;
232            parenthesized!(content in input);
233            let content: Punctuated<Type, Token![,]> = Punctuated::parse_terminated(&content)?;
234            if content.len() == 1 && !content.trailing_punct() {
235                // It is not a tuple. The parentheses were just used to
236                // disambiguate the type.
237                Ok(content.into_iter().next().unwrap())
238            } else {
239                Ok(Type::Tuple(content.into_iter().collect()))
240            }
241        } else if lookahead.peek(Token![&]) {
242            input.parse::<Token![&]>()?;
243            let mut_token: Option<Token![mut]> = input.parse()?;
244            let inner: Type = input.parse()?;
245            if mut_token.is_some() {
246                Ok(Type::ReferenceMut(Box::new(inner)))
247            } else {
248                Ok(Type::Reference(Box::new(inner)))
249            }
250        } else if lookahead.peek(Token![dyn]) {
251            let _: Token![dyn] = input.parse()?;
252            let bounds: Punctuated<Ident, Token![+]> = Punctuated::parse_terminated(input)?;
253            Ok(Type::TraitObject(bounds.into_iter().collect()))
254        } else if lookahead.peek(Ident) {
255            input.parse().map(Type::Ident)
256        } else {
257            Err(lookahead.error())
258        }
259    }
260}
261
262impl Parse for ItemMacro {
263    fn parse(input: ParseStream) -> Result<Self> {
264        input.parse::<Token![macro]>()?;
265
266        let name: Ident = input.parse()?;
267        input.parse::<Token![;]>()?;
268
269        Ok(Self { name })
270    }
271}
272
273impl Receiver {
274    fn is_none(&self) -> bool {
275        use self::Receiver::*;
276        match self {
277            None => true,
278            ByValue | ByRef | ByMut => false,
279        }
280    }
281}
282
283#[proc_macro]
284pub fn library(input: TokenStream) -> TokenStream {
285    let input = parse_macro_input!(input as Input);
286
287    let modules = input.crates.iter().map(declare_mod);
288
289    TokenStream::from(quote! {
290        #[allow(non_snake_case)]
291        mod RUNTIME {
292            extern crate reflect as _reflect;
293
294            #[allow(dead_code, non_snake_case)]
295            pub fn MODULE() -> _reflect::Module {
296                _reflect::Module::root()
297            }
298
299            #(
300                #modules
301            )*
302        }
303    })
304}
305
306fn declare_mod(module: &ItemMod) -> TokenStream2 {
307    let name = &module.name;
308    let name_str = name.to_string();
309    let items = module.items.iter().map(declare_item);
310
311    quote! {
312        pub mod #name {
313            extern crate reflect as _reflect;
314
315            #[allow(unused_imports)]
316            use self::_reflect::runtime::prelude::*;
317
318            #[allow(dead_code, non_snake_case)]
319            pub fn MODULE() -> _reflect::Module {
320                super::MODULE().get_module(#name_str)
321            }
322
323            struct __Indirect<T>(T);
324
325            #(
326                #items
327            )*
328        }
329    }
330}
331
332fn declare_item(item: &Item) -> TokenStream2 {
333    match item {
334        Item::Mod(item) => declare_mod(item),
335        Item::Type(item) => declare_type(item),
336        Item::Impl(item) => declare_impl(item),
337        Item::Trait(item) => declare_trait(item),
338        Item::Macro(item) => declare_macro(item),
339    }
340}
341
342fn declare_type(item: &ItemType) -> TokenStream2 {
343    let name = &item.name;
344    let name_str = name.to_string();
345
346    quote! {
347        #[derive(Copy, Clone)]
348        #[allow(non_camel_case_types)]
349        pub struct #name;
350
351        impl _reflect::runtime::RuntimeType for #name {
352            fn SELF(self) -> _reflect::Type {
353                MODULE().get_type(#name_str)
354            }
355        }
356    }
357}
358
359fn declare_impl(item: &ItemImpl) -> TokenStream2 {
360    let parent = &item.name;
361    let functions = item.functions.iter().map(|f| declare_function(parent, f));
362
363    quote! {
364        #(
365            #functions
366        )*
367    }
368}
369
370fn declare_trait(item: &ItemTrait) -> TokenStream2 {
371    let d_type = declare_type(&ItemType {
372        name: item.name.clone(),
373    });
374    let name = &item.name;
375    let name_str = name.to_string();
376
377    let parent = &item.name;
378    let functions = item.functions.iter().map(|f| declare_function(parent, f));
379
380    quote! {
381        #d_type
382
383        impl _reflect::runtime::RuntimeTrait for #name {
384            fn SELF(self) -> _reflect::Path {
385                MODULE().get_path(#name_str)
386            }
387        }
388        #(
389            #functions
390        )*
391    }
392}
393
394fn declare_function(parent: &Ident, function: &Function) -> TokenStream2 {
395    let name = &function.name;
396    let name_str = name.to_string();
397    let setup_receiver = match function.receiver {
398        Receiver::None => None,
399        Receiver::ByValue => Some(quote! {
400            sig.set_self_by_value();
401        }),
402        Receiver::ByRef => Some(quote! {
403            sig.set_self_by_reference();
404        }),
405        Receiver::ByMut => Some(quote! {
406            sig.set_self_by_reference_mut();
407        }),
408    };
409    let setup_inputs = function.args.iter().map(|arg| {
410        let ty = to_runtime_type(arg);
411        quote! {
412            sig.add_input(#ty);
413        }
414    });
415    let set_output = function.ret.as_ref().map(|ty| {
416        let ty = to_runtime_type(ty);
417        quote!(sig.set_output(#ty);)
418    });
419    let vars = (0..(!function.receiver.is_none() as usize + function.args.len()))
420        .map(|i| Ident::new(&format!("v{}", i), Span::call_site()));
421    let vars2 = vars.clone();
422
423    quote! {
424        impl __Indirect<#parent> {
425            #[allow(dead_code)]
426            fn #name() {
427                #[allow(non_camel_case_types)]
428                #[derive(Copy, Clone)]
429                pub struct #name;
430
431                impl _reflect::runtime::RuntimeFunction for #name {
432                    fn SELF(self) -> _reflect::Function {
433                        let mut sig = _reflect::Signature::new();
434                        #setup_receiver
435                        #(
436                            #setup_inputs
437                        )*
438                        #set_output
439                        _reflect::runtime::RuntimeType::SELF(#parent).get_function(#name_str, sig)
440                    }
441                }
442
443                impl #name {
444                    pub fn INVOKE(
445                        self,
446                        #(
447                            #vars: _reflect::Value,
448                        )*
449                    ) -> _reflect::Value {
450                        _reflect::runtime::RuntimeFunction::SELF(self).invoke(&[#(#vars2),*])
451                    }
452                }
453
454                #[allow(unknown_lints, non_local_definitions)]
455                impl #parent {
456                    #[allow(non_upper_case_globals)]
457                    pub const #name: #name = #name;
458                }
459            }
460        }
461    }
462}
463
464fn declare_macro(item: &ItemMacro) -> TokenStream2 {
465    let name = &item.name;
466    let macro_name = name.to_string();
467
468    quote! {
469        #[allow(non_camel_case_types)]
470        #[derive(Copy, Clone)]
471        pub struct #name;
472
473        impl #name {
474            #[allow(non_upper_case_globals)]
475            pub const #name: #name = #name;
476
477            pub fn INVOKE(
478                self,
479                values: &[_reflect::Value],
480            ) -> _reflect::Value {
481                MODULE().invoke_macro(#macro_name, values)
482            }
483        }
484    }
485}
486
487fn to_runtime_type(ty: &Type) -> TokenStream2 {
488    match ty {
489        Type::Tuple(types) => {
490            let types = types.iter().map(to_runtime_type);
491            quote! {
492                _reflect::Type::tuple(&[#(#types),*])
493            }
494        }
495        Type::Ident(ident) => quote! {
496            _reflect::runtime::RuntimeType::SELF(#ident)
497        },
498        Type::TraitObject(bounds) => {
499            quote! {
500                _reflect::runtime::RuntimeTraitObject::SELF(&[
501                    #(_reflect::runtime::RuntimeTrait::SELF(#bounds)),*
502                ] as &[_])
503            }
504        }
505        Type::Reference(inner) => {
506            let inner = to_runtime_type(inner);
507            quote! {
508                #inner.reference()
509            }
510        }
511        Type::ReferenceMut(inner) => {
512            let inner = to_runtime_type(inner);
513            quote! {
514                #inner.reference_mut()
515            }
516        }
517    }
518}