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