Skip to main content

plusplus_macros/
lib.rs

1use proc_macro_crate::{FoundCrate, crate_name};
2use proc_macro2::{Span, TokenStream};
3use quote::{format_ident, quote};
4use syn::Token;
5use syn::parse::{Parse, ParseStream};
6use syn::token::Brace;
7use syn::{
8    Attribute, Field, FnArg, Ident, ImplItemFn, Pat, Type, Visibility, braced,
9    parse_macro_input, parse_quote,
10};
11
12mod kw {
13    syn::custom_keyword!(class);
14}
15
16#[derive(Debug, Clone)]
17struct OverrideItem {
18    _override_token: Token![override],
19    override_class: Type,
20    _brace_token: Brace,
21    items: Vec<ImplItemFn>,
22}
23
24fn correct_priv_vis(vis: Visibility) -> Visibility {
25    match vis {
26        Visibility::Public(p) => Visibility::Public(p),
27        Visibility::Restricted(mut restricted) => {
28            if restricted.path.segments.get(0) != Some(&parse_quote!(crate)) {
29                restricted.path.segments.insert(0, parse_quote!(super));
30            }
31            Visibility::Restricted(restricted)
32        }
33        Visibility::Inherited => {
34            parse_quote!(pub(super))
35        }
36    }
37}
38
39impl Parse for OverrideItem {
40    fn parse(input: ParseStream) -> syn::Result<Self> {
41        let content;
42        let override_token = input.parse()?;
43        let override_class = input.parse()?;
44        let brace_token = braced!(content in input);
45        let mut items = Vec::new();
46        while !content.is_empty() {
47            let mut item: ImplItemFn = content.parse()?;
48            item.vis = correct_priv_vis(item.vis);
49            items.push(item);
50        }
51
52        Ok(OverrideItem {
53            _override_token: override_token,
54            override_class,
55            _brace_token: brace_token,
56            items,
57        })
58    }
59}
60
61#[derive(Debug, Clone)]
62enum ClassItem {
63    Field {
64        field: Field,
65        _semi_token: Token![;],
66    },
67    ImplItemFn(ImplItemFn),
68    OverrideItem(OverrideItem),
69}
70
71impl Parse for ClassItem {
72    fn parse(input: ParseStream) -> syn::Result<Self> {
73        let lookahead = input.lookahead1();
74        if lookahead.peek(Token![override]) {
75            return Ok(ClassItem::OverrideItem(OverrideItem::parse(input)?));
76        }
77
78        let begin = input.fork();
79        let _attrs = input.call(Attribute::parse_outer)?;
80        let _vis: Visibility = begin.parse()?;
81        let lookahead = begin.lookahead1();
82        if lookahead.peek(Token![fn]) || lookahead.peek(Token![unsafe]) {
83            return Ok(ClassItem::ImplItemFn(ImplItemFn::parse(input)?));
84        }
85
86        let mut field = Field::parse_named(input)?;
87        field.vis = correct_priv_vis(field.vis);
88        let semi_token = input.parse()?;
89        Ok(ClassItem::Field {
90            field,
91            _semi_token: semi_token,
92        })
93    }
94}
95
96#[derive(Debug, Clone)]
97struct SuperclassInput {
98    _colon_token: Token![:],
99    ty: Type,
100}
101
102impl Parse for SuperclassInput {
103    fn parse(input: ParseStream) -> syn::Result<Self> {
104        Ok(SuperclassInput {
105            _colon_token: input.parse()?,
106            ty: input.parse()?,
107        })
108    }
109}
110
111#[derive(Debug, Clone)]
112struct ClassInput {
113    vis: Visibility,
114    _class_token: kw::class,
115    ident: Ident,
116    superclass: Option<SuperclassInput>,
117    _brace_token: Brace,
118    items: Vec<ClassItem>,
119}
120
121impl Parse for ClassInput {
122    fn parse(input: ParseStream) -> syn::Result<Self> {
123        let content;
124        let vis = input.parse()?;
125        let class_token = input.parse()?;
126        let ident = input.parse()?;
127
128        let lookahead = input.lookahead1();
129        let superclass = if lookahead.peek(Token![:]) {
130            Some(input.parse()?)
131        } else {
132            None
133        };
134
135        let brace_token = braced!(content in input);
136        let mut items = Vec::new();
137        while !content.is_empty() {
138            items.push(content.parse()?);
139        }
140        Ok(ClassInput {
141            vis,
142            _class_token: class_token,
143            ident,
144            superclass,
145            _brace_token: brace_token,
146            items,
147        })
148    }
149}
150
151#[derive(Debug, Clone)]
152struct CrateAlias {
153    _crate_token: Token![crate],
154    _as_token: Token![as],
155    ident: Ident,
156    _semi_token: Token![;],
157}
158
159impl Parse for CrateAlias {
160    fn parse(input: ParseStream) -> syn::Result<Self> {
161        Ok(CrateAlias {
162            _crate_token: input.parse()?,
163            _as_token: input.parse()?,
164            ident: input.parse()?,
165            _semi_token: input.parse()?,
166        })
167    }
168}
169
170struct ClassInputs {
171    crate_alias: Option<CrateAlias>,
172    inputs: Vec<ClassInput>,
173}
174
175impl Parse for ClassInputs {
176    fn parse(input: ParseStream) -> syn::Result<Self> {
177        let lookahead = input.lookahead1();
178        let crate_alias = if lookahead.peek(Token![crate]) {
179            Some(input.parse()?)
180        } else {
181            None
182        };
183
184        let mut inputs = Vec::new();
185        while !input.is_empty() {
186            inputs.push(input.parse()?);
187        }
188
189        Ok(ClassInputs {
190            crate_alias,
191            inputs,
192        })
193    }
194}
195
196fn plusplus() -> proc_macro2::TokenStream {
197    let found_crate = crate_name("plusplus").expect("plusplus is present in `Cargo.toml`");
198    match found_crate {
199        FoundCrate::Itself => quote!(crate),
200        FoundCrate::Name(name) => {
201            let ident = Ident::new(&name, Span::call_site());
202            quote!( #ident )
203        }
204    }
205}
206
207fn cast_class_ptr(
208    plusplus: &proc_macro2::TokenStream,
209    from: &Type,
210    to: &Type,
211    expr: impl Into<proc_macro2::TokenStream>,
212) -> proc_macro2::TokenStream {
213    let expr = expr.into();
214    quote! {{
215        let t: &#from = #expr;
216        let self_size = std::mem::size_of_val(t);
217        let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
218        assert!(self_size >= target_size);
219        let array_size = self_size - target_size;
220        let target_ptr = std::ptr::slice_from_raw_parts(t as *const #from as *const u8, array_size);
221        let target_ref = &*(target_ptr as *const #to);
222        assert_eq!(self_size, std::mem::size_of_val(target_ref));
223        target_ref
224    }}
225}
226
227fn cast_class_ptr_mut(
228    plusplus: &TokenStream,
229    from: &Type,
230    to: &Type,
231    expr: impl Into<TokenStream>,
232) -> TokenStream {
233    let expr = expr.into();
234    quote! {{
235        let t: &mut #from = #expr;
236        let self_size = std::mem::size_of_val(t);
237        let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
238        assert!(self_size >= target_size);
239        let array_size = self_size - target_size;
240        let target_ptr = std::ptr::slice_from_raw_parts_mut(t as *mut #from as *mut u8, array_size);
241        let target_ref = &mut *(target_ptr as *mut #to);
242        assert_eq!(self_size, std::mem::size_of_val(target_ref));
243        target_ref
244    }}
245}
246
247#[derive(Debug, Clone)]
248struct FuncInfo {
249    func: ImplItemFn,
250    name: Ident,
251    vtbl_name: Ident,
252    sig: TokenStream,
253    args: Vec<Box<Pat>>,
254    mut_self: bool,
255}
256
257fn get_func_sig(class_name: &Type, f: &ImplItemFn) -> FuncInfo {
258    let func_name = &f.sig.ident;
259
260    let mut inputs = f.sig.inputs.clone();
261    let mut mut_self = false;
262    if let Some(FnArg::Receiver(rx)) = &f.sig.inputs.get(0) {
263        let receiver = &mut inputs[0];
264        if rx.mutability.is_some() {
265            *receiver = FnArg::Typed(parse_quote!(this: &mut #class_name));
266        } else {
267            *receiver = FnArg::Typed(parse_quote!(this: &#class_name));
268        }
269        mut_self = rx.mutability.is_some();
270    };
271
272    let output = &f.sig.output;
273    let func_sig = quote! {
274        (#inputs) #output
275    };
276    let vtbl_name = format_ident!("fn_{func_name}");
277
278    let func_args = inputs
279        .into_iter()
280        .skip(1)
281        .map(|arg| match arg {
282            FnArg::Receiver(_) => unreachable!(),
283            FnArg::Typed(arg) => arg.pat,
284        })
285        .collect::<Vec<_>>();
286
287    FuncInfo {
288        func: f.clone(),
289        name: func_name.clone(),
290        vtbl_name,
291        sig: func_sig,
292        args: func_args,
293        mut_self,
294    }
295}
296
297struct ClassData {
298    plusplus: TokenStream,
299    class_name: Ident,
300    class_type: Type,
301    class_mod_name: Ident,
302    vtbl_ident: Ident,
303    class_vis: Visibility,
304    fields: Vec<Field>,
305    constructors: Vec<FuncInfo>,
306    member_funcs: Vec<FuncInfo>,
307    overrides: Vec<OverrideItem>,
308    override_funcs: Vec<FuncInfo>,
309    superclass_type: Option<Type>,
310    mod_superclass_type: Option<Type>,
311}
312
313impl ClassData {
314    fn from_input(input: ClassInput, crate_alias: Option<&CrateAlias>) -> ClassData {
315        let ClassInput {
316            vis: class_vis,
317            _class_token: _,
318            ident: class_name,
319            superclass,
320            _brace_token: _,
321            items: class_items,
322        } = input;
323
324        let mut fields = Vec::new();
325        let mut constructors = Vec::new();
326        let mut member_funcs = Vec::new();
327        let mut overrides = Vec::new();
328        let mut override_funcs = Vec::new();
329
330        let class_type: Type = parse_quote!(#class_name);
331
332        for item in class_items {
333            match item {
334                ClassItem::Field { field, .. } => fields.push(field),
335                ClassItem::ImplItemFn(func) => {
336                    if let Some(FnArg::Receiver(_)) = func.sig.inputs.get(0) {
337                        member_funcs.push(get_func_sig(&class_type, &func))
338                    } else {
339                        constructors.push(get_func_sig(&class_type, &func));
340                    }
341                }
342                ClassItem::OverrideItem(override_item) => {
343                    override_funcs.extend(override_item.items.iter().map(|f| get_func_sig(&class_type, &f)));
344                    overrides.push(override_item);
345                }
346            }
347        }
348
349        let class_mod_name = format_ident!("plusplus__class_{}", class_name.to_string().to_lowercase());
350
351        let plusplus = if let Some(alias) = crate_alias {
352            let alias = &alias.ident;
353            quote!(#alias)
354        } else {
355            plusplus()
356        };
357
358        let superclass_type = superclass.map(|sc| sc.ty);
359        let mod_superclass_type = match superclass_type.clone() {
360            Some(Type::Path(mut type_path)) => {
361                if type_path.path.segments.get(0) != Some(&parse_quote!(crate)) {
362                    type_path.path.segments.insert(0, parse_quote!(super));
363                }
364                Some(Type::Path(type_path))
365            }
366            ty => ty
367        };
368
369        ClassData {
370            plusplus,
371            vtbl_ident: format_ident!("{}Vtbl", class_name),
372            class_vis,
373            class_name,
374            class_type,
375            class_mod_name,
376            fields,
377            constructors,
378            member_funcs,
379            overrides,
380            override_funcs,
381            superclass_type,
382            mod_superclass_type,
383        }
384    }
385
386    fn has_superclass(&self) -> bool {
387        self.superclass_type.is_some()
388    }
389
390    fn gen_mod_vtbl_struct(&self) -> TokenStream {
391        // create vtbl
392        let vtbl_ident = &self.vtbl_ident;
393        let class_name = &self.class_name;
394
395        let mut vtbl_func_names = Vec::new();
396        let mut func_sigs = Vec::new();
397        let mut my_func_names = Vec::new();
398
399        for f in self.member_funcs.iter() {
400            let FuncInfo {
401                func: ImplItemFn{ .. },
402                name: func_name,
403                vtbl_name,
404                sig: func_sig,
405                args: _,
406                mut_self: _,
407            } = f;
408            vtbl_func_names.push(vtbl_name);
409            func_sigs.push(func_sig);
410            let my_func_name = format_ident!("my_{func_name}");
411            my_func_names.push(my_func_name);
412        }
413
414        let vtbl_drop_field: Option<_>;
415        let vtbl_drop_func: Option<_>;
416        let vtbl_drop_set: Option<_>;
417        if !self.has_superclass() {
418            vtbl_drop_field = Some(quote! {
419                pub manually_drop: unsafe fn(*mut #class_name),
420            });
421            vtbl_drop_func = Some(quote! {
422                unsafe fn manually_drop(this: *mut #class_name) {
423                    unsafe{ std::ptr::drop_in_place(this) }
424                }
425            });
426            vtbl_drop_set = Some(quote! {
427                manually_drop,
428            });
429        } else {
430            vtbl_drop_field = None;
431            vtbl_drop_func = None;
432            vtbl_drop_set = None;
433        };
434
435        quote! {
436            #[doc(hidden)]
437            pub struct #vtbl_ident {
438                #vtbl_drop_field
439                #(pub #vtbl_func_names: fn #func_sigs,)*
440            }
441
442            impl #vtbl_ident {
443                const BASE: Self = {
444                    #vtbl_drop_func
445
446                    Self {
447                        #vtbl_drop_set
448                        #(#vtbl_func_names: #class_name::#my_func_names,)*
449                    }
450                };
451            }
452        }
453    }
454
455    fn gen_fn_set_vtbls(&self) -> TokenStream {
456        let plusplus = &self.plusplus;
457        let class_name = &self.class_name;
458
459        let set_vtbls = self.overrides.iter().map(|ovr| {
460            let ovr_class = &ovr.override_class;
461            let ovr_class = match ovr_class.clone() {
462                Type::Path(mut type_path) => {
463                    type_path.path.segments.insert(0, parse_quote!(super));
464                    Type::Path(type_path)
465                }
466                ty => ty
467            };
468
469            let mut ol_func_names = Vec::new();
470            let mut ol_func_sigs = Vec::new();
471            let mut ol_func_self_call_impls = Vec::new();
472            for f in &ovr.items {
473                let FuncInfo {
474                    func: _,
475                    name: func_name,
476                    vtbl_name,
477                    sig: func_sig,
478                    args: func_args,
479                    mut_self,
480                } = get_func_sig(&ovr_class, f);
481                ol_func_names.push(vtbl_name);
482                ol_func_sigs.push(func_sig);
483
484                let func_name = format_ident!("my_{}", func_name);
485                let self_call = if mut_self {
486                    let cast_mut = cast_class_ptr_mut(
487                        &plusplus,
488                        &ovr_class,
489                        &self.class_type,
490                        quote! {this},
491                    );
492                    quote! {
493                        let this: &mut #class_name = unsafe{ #cast_mut };
494                        this.#func_name(#(#func_args,)*)
495                    }
496                } else {
497                    let cast = cast_class_ptr(&plusplus, &ovr_class, &self.class_type, quote! {this});
498                    quote! {
499                        let this: &#class_name = unsafe{ #cast };
500                        this.#func_name(#(#func_args,)*)
501                    }
502                };
503                ol_func_self_call_impls.push(self_call);
504            }
505
506            quote! {{
507                let this: &mut #ovr_class = &mut *(unsafe{ self.to_constructed() });
508                #(
509                    fn #ol_func_names #ol_func_sigs {
510                        #ol_func_self_call_impls
511                    }
512                    unsafe{ this.plusplus__vtbl_mut().#ol_func_names = #ol_func_names };
513                )*
514            }}
515        });
516
517        let root_type: Type = parse_quote!(<#class_name as #plusplus::Class>::RootClass);
518        let cast_root_to_self =
519            cast_class_ptr_mut(&plusplus, &root_type, &self.class_type, quote!(ref_mut));
520        let root_type = &root_type;
521
522        let set_subclass = self.has_superclass().then(|| quote!{
523            unsafe{ self.superclass.plusplus__set_subclass(<#class_name as #plusplus::Class>::TYPE_ID) };
524
525            {
526                unsafe fn manually_drop(this: *mut #root_type) {
527                    let ref_mut = unsafe{ &mut *this };
528                    let this = unsafe{ #cast_root_to_self };
529                    unsafe{ std::ptr::drop_in_place(this) };
530                }
531                let root_vtbl = unsafe{ <#class_name as #plusplus::Class>::root_class_mut(self.to_constructed()).plusplus__vtbl_mut() };
532                root_vtbl.manually_drop = manually_drop;
533            }
534        });
535
536        quote! {
537            fn plusplus__set_vtbls(&mut self) {
538                #set_subclass
539                #(#set_vtbls)*
540            }
541        }
542    }
543
544    fn gen_mod_class_struct(&self) -> TokenStream {
545        let plusplus = &self.plusplus;
546
547        let superclass_field = self.mod_superclass_type.as_ref().map(|sc_type| {
548            quote! {
549                superclass: #sc_type<#plusplus::InConstruction>,
550            }
551        });
552        let superclass_field = superclass_field.as_ref();
553        let superclass_bound = self.mod_superclass_type.as_ref().map(|sc_ident| quote!{
554            where #sc_ident: #plusplus::Class
555        });
556
557        let class_struct_vis = correct_priv_vis(self.class_vis.clone());
558        let vtbl_ident = &self.vtbl_ident;
559        let class_name = &self.class_name;
560        let fields = &self.fields;
561        let init_superclass_field = superclass_field.map(|f| quote!(pub #f));
562        let init_fields = self.fields.iter().cloned().map(|f| Field {
563            vis: Visibility::Public(parse_quote!(pub)),
564            ..f
565        });
566
567        quote! {
568            #[repr(C)]
569            #class_struct_vis struct #class_name<C: ?Sized + #plusplus::ClassMemory = #plusplus::Constructed>
570                #superclass_bound
571            {
572                #superclass_field
573                vtbl: #vtbl_ident,
574                subclass_id: Option<std::any::TypeId>,
575                #(#fields,)*
576                memory: C,
577            }
578
579            pub struct PlusPlus__InitClass {
580                #init_superclass_field
581                #(#init_fields,)*
582            }
583        }
584    }
585
586    fn gen_superclass_casters(&self) -> Option<TokenStream> {
587        let Some(sc_type) = self.superclass_type.as_ref() else {
588            return None;
589        };
590        let class_name = &self.class_name;
591
592        let deref_upcast = cast_class_ptr(&self.plusplus, &self.class_type, sc_type, quote! {self});
593        let deref_upcast_mut = cast_class_ptr_mut(
594            &self.plusplus,
595            &self.class_type,
596            sc_type,
597            quote! {self},
598        );
599        let ref_downcast = cast_class_ptr(&self.plusplus, sc_type, &self.class_type, quote! {self});
600        let ref_downcast_mut = cast_class_ptr_mut(
601            &self.plusplus,
602            sc_type,
603            &self.class_type,
604            quote! {self},
605        );
606
607        let plusplus = &self.plusplus;
608        Some(quote! {
609            impl std::ops::Deref for #class_name {
610                type Target = #sc_type;
611
612                fn deref(&self) -> &Self::Target {
613                    unsafe { #deref_upcast }
614                }
615            }
616
617            impl std::ops::DerefMut for #class_name {
618                fn deref_mut(&mut self) -> &mut Self::Target {
619                    unsafe { #deref_upcast_mut }
620                }
621            }
622
623            impl<'a> #plusplus::Downcast<#class_name> for &'a #sc_type {
624                type Wrapped = &'a #class_name;
625                fn downcast(self) -> Result<&'a #class_name, Self> {
626                    use #plusplus::Class;
627                    let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
628                    if self.subclass_id() == Some(subclass_type_id) {
629                        Ok(unsafe{ #ref_downcast })
630                    } else {
631                        Err(self)
632                    }
633                }
634            }
635
636            impl<'a> #plusplus::Downcast<#class_name> for &'a mut #sc_type {
637                type Wrapped = &'a mut #class_name;
638                fn downcast(self) -> Result<&'a mut #class_name, Self> {
639                    use #plusplus::Class;
640                    let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
641                    if self.subclass_id() == Some(subclass_type_id) {
642                        Ok(unsafe{ #ref_downcast_mut })
643                    } else {
644                        Err(self)
645                    }
646                }
647            }
648        })
649    }
650
651    fn gen_mod_impl_class_trait(&self) -> TokenStream {
652        let plusplus = &self.plusplus;
653        let class_name = &self.class_name;
654        let root_class = self.mod_superclass_type
655            .as_ref()
656            .map(|sc_ident| quote! { <#sc_ident as #plusplus::Class>::RootClass })
657            .unwrap_or_else(|| quote! { #class_name });
658
659        quote! {
660            unsafe impl #plusplus::Class for #class_name {
661                const TYPE_ID: std::any::TypeId = std::any::TypeId::of::<#class_name>();
662
663                type RootClass = #root_class;
664
665                fn subclass_id(&self) -> Option<std::any::TypeId> {
666                    self.subclass_id
667                }
668
669                fn root_class(&self) -> &Self::RootClass {
670                    self
671                }
672
673                fn root_class_mut(&mut self) -> &mut Self::RootClass {
674                    self
675                }
676
677                unsafe fn manually_drop(slot: &mut std::mem::ManuallyDrop<Self>) {
678                    let as_root_class = slot.root_class_mut();
679                    let manual_drop_fn = unsafe{ as_root_class.plusplus__vtbl_mut().manually_drop };
680                    unsafe{ manual_drop_fn(as_root_class); }
681                }
682            }
683        }
684    }
685
686    fn gen_mod_class_impl(&self) -> TokenStream {
687        let class_name = &self.class_name;
688        let vtbl_ident = &self.vtbl_ident;
689
690        let mut call_vtbl_impls = Vec::new();
691        for f in self.member_funcs.iter() {
692            let FuncInfo {
693                func: ImplItemFn{ vis, sig, ..},
694                name: _,
695                vtbl_name,
696                sig: _,
697                args: func_args,
698                mut_self: _,
699            } = f;
700
701            let vis = correct_priv_vis(vis.clone());
702            let call_vtbl = quote! {
703                #vis #sig {
704                    (self.vtbl.#vtbl_name)(self, #(#func_args,)*)
705                }
706            };
707            call_vtbl_impls.push(call_vtbl);
708        }
709
710        let mut my_func_impls = Vec::new();
711        let mut super_func_impls = Vec::new();
712
713        for (f, is_override) in self.member_funcs
714            .iter().cloned()
715            .map(|f| (f, false))
716            .chain(self.override_funcs.iter().cloned().map(|f| (f, true)))
717        {
718            let FuncInfo {
719                func: ImplItemFn {
720                    attrs: _,
721                    vis,
722                    defaultness: _,
723                    sig,
724                    block,
725                },
726                name: func_name,
727                vtbl_name: _,
728                sig: _,
729                args: func_args,
730                mut_self,
731            } = f;
732
733            let my_impl_name = format_ident!("my_{}", func_name);
734            let mut my_impl_sig = sig.clone();
735            my_impl_sig.ident = my_impl_name.clone();
736            my_func_impls.push(quote! {
737                #vis #my_impl_sig {
738                    #block
739                }
740            });
741
742            if is_override {
743                let super_impl_name = format_ident!("super_{}", func_name);
744                let mut super_impl_sig = sig.clone();
745                super_impl_sig.ident = super_impl_name.clone();
746                let super_impl_block = if mut_self {
747                    quote! {
748                        self.plusplus__super_mut().#my_impl_name(#(#func_args)*)
749                    }
750                } else {
751                    quote! {
752                        self.plusplus__super_ref().#my_impl_name(#(#func_args)*)
753                    }
754                };
755                super_func_impls.push(quote! {
756                    #vis #super_impl_sig {
757                        #super_impl_block
758                    }
759                });
760            }
761        }
762
763        let superclass_getters = self.mod_superclass_type.as_ref().map(|sc_ident| {
764            quote! {
765                fn plusplus__super_ref(&self) -> &#sc_ident {
766                    self
767                }
768
769                fn plusplus__super_mut(&mut self) -> &mut #sc_ident {
770                    self
771                }
772            }
773        });
774
775        quote!{
776            impl #class_name {
777                #(#call_vtbl_impls)*
778                #(#super_func_impls)*
779
780                #superclass_getters
781
782                #[doc(hidden)]
783                pub unsafe fn plusplus__vtbl_mut(&mut self) -> &mut #vtbl_ident {
784                    &mut self.vtbl
785                }
786            }
787        }
788    }
789
790    fn gen_mod_in_construction_class_impl(&self) -> TokenStream {
791        let plusplus = &self.plusplus;
792        let class_name = &self.class_name;
793        let vtbl_ident = &self.vtbl_ident;
794
795        let set_vtbl_func = self.gen_fn_set_vtbls();
796        let class_vis = correct_priv_vis(self.class_vis.clone());
797
798        let superclass_field = self.has_superclass().then(|| quote!{superclass: init.superclass,});
799        let fields = self.fields.iter().map(|f| &f.ident).collect::<Vec<_>>();
800
801        quote!{
802            impl #class_name<#plusplus::InConstruction> {
803                #set_vtbl_func
804
805                pub(super) fn plusplus__new_from_init(init: PlusPlus__InitClass) -> Self {
806                    let mut this = Self {
807                        vtbl: #vtbl_ident::BASE,
808                        memory: #plusplus::InConstruction::default(),
809                        subclass_id: None,
810                        #superclass_field
811                        #(#fields: init.#fields,)*
812                    };
813
814                    this.plusplus__set_vtbls();
815
816                    this
817                }
818
819                #[doc(hidden)]
820                pub unsafe fn plusplus__set_subclass(&mut self, subclass_id: std::any::TypeId) {
821                    self.subclass_id = Some(subclass_id);
822                }
823
824                /// Unsafe because caller must guarantee that vtbl doesn't contain any
825                /// subclass methods
826                pub unsafe fn to_constructed(&mut self) -> &mut #class_name {
827                    unsafe{ &mut *(std::ptr::slice_from_raw_parts_mut::<u8>(self as *mut _ as *mut u8, 0) as *mut #class_name) }
828                }
829
830                /// Finish constructing this by moving it to the heap placing it in a `ClassBox`.
831                ///
832                /// Downcasting, upcasting, and deref coersions will work properly after calling this!
833                #class_vis fn finish(self: #class_name<#plusplus::InConstruction>) -> #plusplus::ClassBox<#class_name> {
834                    let boxed = Box::new(self);
835                    let leaked = Box::leak(boxed);
836                    let constructed = unsafe{ leaked.to_constructed() };
837                    unsafe{ #plusplus::ClassBox::from_raw(constructed) }
838                }
839            }
840        }
841    }
842
843    fn gen_init_class_macro(&self) -> TokenStream {
844        let plusplus = &self.plusplus;
845        let class_name = &self.class_name;
846        let class_mod_name = &self.class_mod_name;
847
848        quote! {
849            macro_rules! init_class {
850                ($($tt:tt)*) => {{
851                    #class_name::<#plusplus::InConstruction>::plusplus__new_from_init(#class_mod_name::PlusPlus__InitClass {
852                        $($tt)*
853                    })
854                }}
855            }
856        }
857    }
858
859    fn gen_class_impl(&self) -> TokenStream {
860        let class_name = &self.class_name;
861        let mut my_func_impls = Vec::new();
862        for f in self.member_funcs
863            .iter().cloned()
864            .chain(self.override_funcs.iter().cloned())
865        {
866            let FuncInfo {
867                func: ImplItemFn {
868                    attrs: _,
869                    vis,
870                    defaultness: _,
871                    sig,
872                    block,
873                },
874                name: func_name,
875                vtbl_name: _,
876                sig: _,
877                args: _,
878                mut_self: _,
879            } = f;
880
881            let my_impl_name = format_ident!("my_{}", func_name);
882            let mut my_impl_sig = sig.clone();
883            my_impl_sig.ident = my_impl_name.clone();
884            my_func_impls.push(quote! {
885                #vis #my_impl_sig {
886                    #block
887                }
888            });
889        }
890
891        let init_class_macro = self.gen_init_class_macro();
892        let mut constructor_impls = Vec::new();
893        for c in self.constructors.iter() {
894            let ImplItemFn {
895                attrs,
896                vis,
897                defaultness,
898                sig,
899                block,
900            } = &c.func;
901
902            let vis = correct_priv_vis(vis.clone());
903            constructor_impls.push(quote! {
904                #(#attrs)* #vis #defaultness #sig {
905                    #init_class_macro
906                    #block
907                }
908            });
909        }
910
911        quote!{
912            impl #class_name {
913                #(#constructor_impls)*
914                #(#my_func_impls)*
915            }
916        }
917    }
918
919    fn gen_class(&self) -> TokenStream {
920        let class_vis = &self.class_vis;
921        let class_name = &self.class_name;
922        let class_mod_name = &self.class_mod_name;
923        let mod_vtbl_struct = self.gen_mod_vtbl_struct();
924        let mod_class_struct = self.gen_mod_class_struct();
925        let mod_impl_class_trait = self.gen_mod_impl_class_trait();
926        let superclass_cast = self.gen_superclass_casters();
927        let mod_class_impl = self.gen_mod_class_impl();
928        let mod_in_construction_class_impl = self.gen_mod_in_construction_class_impl();
929        let class_impl = self.gen_class_impl();
930
931        quote! {
932            #class_vis use #class_mod_name::#class_name;
933            mod #class_mod_name {
934                use super::*;
935                #mod_vtbl_struct
936                #mod_class_struct
937
938                #mod_class_impl
939
940                #mod_impl_class_trait
941
942                #mod_in_construction_class_impl
943            }
944
945            #class_impl
946
947            #superclass_cast
948        }
949    }
950}
951
952/// The whole point.
953#[proc_macro]
954pub fn class(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
955    let inputs = parse_macro_input!(tokens as ClassInputs);
956    let class_data = inputs.inputs.into_iter().map(|input| ClassData::from_input(input, inputs.crate_alias.as_ref()).gen_class());
957
958    let output = quote!{
959        #(#class_data)*
960    };
961    output.into()
962}