ferris_gc_proc_macro/
lib.rs1use proc_macro::TokenStream;
2use std::borrow::{Borrow, BorrowMut};
3use quote::quote;
4use syn::{ReturnType, Type, Data, Fields};
5
6#[proc_macro_derive(Trace, attributes(unsafe_ignore_trace))]
7pub fn derive_trace(item: TokenStream) -> TokenStream {
8 let derive_input = syn::parse_macro_input!(item as syn::DeriveInput);
9
10 let ident = &derive_input.ident;
11 let data_type = &derive_input.data;
12 let trace_impl = match data_type {
13 Data::Struct(data_struct) => {
14 match &data_struct.fields {
15 Fields::Named(named_fields) => {
16 let mut fields = Vec::new();
17 for field in &named_fields.named {
18 let attrs = &field.attrs;
19 if !attrs.into_iter().any(|attr| attr.path.get_ident().unwrap() == "unsafe_ignore_trace") {
20 let ident = &field.ident;
21 fields.push(ident);
22 }
23 }
24 quote! {
25 impl Trace for #ident {
26 fn is_root(&self) -> bool {
27 unreachable!("is_root should never be called on user-defined type !!");
28 }
29
30 fn reset_root(&self) {
31 #(self.#fields.reset_root();)*
32 }
33
34 fn trace(&self) {
35 #(self.#fields.trace();)*
36 }
37
38 fn reset(&self) {
39 #(self.#fields.reset();)*
40 }
41
42 fn is_traceable(&self) -> bool {
43 unreachable!("is_traceable should never be called on user-defined type !!");
44 }
45 }
46 }
47 },
48 Fields::Unnamed(unnamed_fields) => {
49 let mut fields = Vec::new();
50 let mut idx = 0;
51 for field in &unnamed_fields.unnamed {
52 let attrs = &field.attrs;
53 if !attrs.into_iter().any(|attr| attr.path.get_ident().unwrap() == "unsafe_ignore_trace") {
54 fields.push(idx);
55 }
56 idx += 1;
57 }
58 quote! {
59 impl Trace for #ident {
60 fn is_root(&self) -> bool {
61 unreachable!("is_root should never be called on user-defined type !!");
62 }
63
64 fn reset_root(&self) {
65 #(self.#fields.reset_root();)*
66 }
67
68 fn trace(&self) {
69 #(self.#fields.trace();)*
70 }
71
72 fn reset(&self) {
73 #(self.#fields.reset();)*
74 }
75
76 fn is_traceable(&self) -> bool {
77 unreachable!("is_traceable should never be called on user-defined type !!");
78 }
79 }
80 }
81 },
82 Fields::Unit => {
83 panic!("Unit type is not supported !!");
84 },
85 }
86 },
87 Data::Enum(data_enum) => {
88 panic!("Enum type is not supported !!");
89 },
90 Data::Union(data_union) => {
91 panic!("Union type is not supported !!");
92 },
93 };
94
95 let print_tokens = Into::<TokenStream>::into(trace_impl.clone());
96 println!("Result Trace Impl is {}", print_tokens.to_string());
97 trace_impl.into()
98}
99
100#[proc_macro_derive(Finalize)]
101pub fn derive_finalize(item: TokenStream) -> TokenStream {
102 let derive_input = syn::parse_macro_input!(item as syn::DeriveInput);
103
104 let ident = &derive_input.ident;
105 let finalizer_impl = quote! {
106 impl Finalize for #ident {
107 fn finalize(&self) {
108 }
109 }
110 };
111
112 let print_tokens = Into::<TokenStream>::into(finalizer_impl.clone());
113 println!("Result Finalizer Impl is {}", print_tokens.to_string());
114 finalizer_impl.into()
115}
116
117#[proc_macro_attribute]
118pub fn ferris_gc_main(attrs: TokenStream, item: TokenStream) -> TokenStream {
119 let input = syn::parse_macro_input!(item as syn::ItemFn);
120 let attr_args = syn::parse_macro_input!(attrs as syn::AttributeArgs);
121
122 let sig = &input.sig;
123 let vis = input.vis;
124 let name = &input.sig.ident;
125 if name != "main" {
126 panic!("#[ferris_gc_main] is applied only for main function")
127 }
128 let mut args = Vec::new();
129 for arg in &input.sig.inputs {
130 args.push(arg);
131 }
132 let ret = match &input.sig.output {
133 ReturnType::Default => {
134 quote! {
135 }
136 },
137 ReturnType::Type(arrow, box_type) => {
138 quote! {
139 -> #box_type
140 }
141 }
142 };
143 let body = &input.block;
144 let attrs = &input.attrs;
145
146 let res_fun = quote! {
147 #(#attrs)*
148 #vis fn #name (#(#args),*) #ret {
149 let cleanup = ApplicationCleanup;
151 {
152 #body
153 }
154 }
155 };
156
157 let print_tokens = Into::<TokenStream>::into(res_fun.clone());
158 println!("Result Function is {}", print_tokens.to_string());
159 res_fun.into()
160}