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 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}