1#![feature(proc_macro_diagnostic)]
2
3use proc_macro::TokenStream;
5use quote::{quote, ToTokens};
7use syn::parse::{Parse, ParseStream, Result};
9use syn::punctuated::Punctuated;
10use syn::token::{Comma, Pub};
11use syn::{parse_macro_input, Ident, Token, Path, Visibility, Attribute, Type, Expr, Generics, FnArg, Stmt, braced, WhereClause, parenthesized};
13
14struct ClassExtends {
15 type_sequence: Vec<Path>,
17 component_type: Path,
18 oop_inheritance_crate: Option<proc_macro2::TokenStream>,
19}
20
21fn parse_full_qualified_id(input: ParseStream) -> Result<Path> {
22 Ok(Path::parse_mod_style(input)?)
23}
24
25impl Parse for ClassExtends {
26 fn parse(input: ParseStream) -> Result<Self> {
27 let mut type_sequence: Vec<Path> = vec![];
28 type_sequence.push(parse_full_qualified_id(input)?);
29
30 input.parse::<Token![<]>()?;
32 type_sequence.push(parse_full_qualified_id(input)?);
33 while input.peek(Token![<]) {
34 input.parse::<Token![<]>()?;
35 type_sequence.push(parse_full_qualified_id(input)?);
36 }
37
38 input.parse::<Token![,]>()?;
40 input.parse::<Token![use]>()?;
41 let component_type = parse_full_qualified_id(input)?;
42
43 let mut oop_inheritance_crate = None;
44 if input.peek(Token![,]) {
45 input.parse::<Token![,]>()?;
46 oop_inheritance_crate = Some(parse_full_qualified_id(input)?.to_token_stream());
47 }
48
49 Ok(ClassExtends {
50 type_sequence,
51 component_type,
52 oop_inheritance_crate,
53 })
54 }
55}
56
57#[proc_macro]
79pub fn class_extends(input: TokenStream) -> TokenStream {
80 let ClassExtends { type_sequence, component_type, oop_inheritance_crate } = parse_macro_input!(input as ClassExtends);
81 let subtype = type_sequence[0].clone();
82 let super_type = type_sequence[1].clone();
83 let oop_inheritance_crate = oop_inheritance_crate.unwrap_or(quote! {::oop_inheritance});
84
85 let mut expanded = TokenStream::new();
86
87 expanded.extend::<TokenStream>(quote! {
88 impl ::std::ops::Deref for #subtype { type Target = #super_type; fn deref(&self) -> &Self::Target { &self.0 } }
89 impl Clone for #subtype { fn clone(&self) -> Self { Self(self.0.clone()) } }
90 impl PartialEq for #subtype { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } }
91 impl Eq for #subtype {}
92 impl ::std::hash::Hash for #subtype { fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) { self.0.hash(state); } }
93
94 impl AsRef<#super_type> for #subtype { fn as_ref(&self) -> &#super_type { &self.0 } }
96 impl AsRef<#subtype> for #subtype { fn as_ref(&self) -> &Self { self } }
97
98 impl From<#subtype> for #super_type { fn from(value: #subtype) -> Self { value.0.clone() } }
100
101 impl TryFrom<#super_type> for #subtype { type Error = #oop_inheritance_crate::ClassError; fn try_from(value: #super_type) -> Result<Self, Self::Error> { if value.has::<#component_type>() { Ok(#subtype(value.clone())) } else { Err(#oop_inheritance_crate::ClassError::new("Type conversion failed")) } } }
103 }.into());
104
105 for super_type in &type_sequence[2..] {
107 expanded.extend::<TokenStream>(quote! {
108 impl AsRef<#super_type> for #subtype { fn as_ref(&self) -> &#super_type { self.0.as_ref() } }
109 impl From<#subtype> for #super_type { fn from(value: #subtype) -> Self { #super_type::from(value.0) } }
110 impl TryFrom<#super_type> for #subtype { type Error = #oop_inheritance_crate::ClassError; fn try_from(value: #super_type) -> Result<Self, Self::Error> { if value.has::<#component_type>() { Ok(#subtype(value.try_into()?)) } else { Err(#oop_inheritance_crate::ClassError::new("Type conversion failed")) } } }
111 }.into());
112 }
113
114 expanded
115}
116
117struct Class {
118 oop_inheritance_crate: Option<proc_macro2::TokenStream>,
119 attributes: Vec<Attribute>,
120 visibility: Visibility,
121 name: Ident,
122 inherited: Vec<Path>,
123 fields: Vec<ClassField>,
124 constructor: ClassConstructor,
125}
126
127struct ClassField {
129 attributes: Vec<Attribute>,
130 visibility: Visibility,
131 is_reference: bool,
132 name: Ident,
133 type_annotation: Type,
134 default_value: Expr,
135}
136
137struct ClassConstructor {
138 attributes: Vec<Attribute>,
139 visibility: Visibility,
140 generics: Generics,
141 inputs: Punctuated<FnArg, Comma>,
142 super_arguments: Punctuated<Expr, Comma>,
143 statements: Vec<Stmt>,
144}
145
146impl Parse for Class {
147 fn parse(input: ParseStream) -> Result<Self> {
148 let mut oop_inheritance_crate = None;
149 if input.peek(Token![use]) {
150 oop_inheritance_crate = Some(parse_class_oop_inheritance_crate_ref(input)?.to_token_stream());
151 }
152
153 let attributes = Attribute::parse_outer(input)?;
154 let visibility = input.parse::<Visibility>()?;
155
156 input.parse::<Token![struct]>()?;
157
158 let name = input.parse::<Ident>()?;
159 input.parse::<Token![:]>()?;
160
161 let mut inherited = vec![];
163 inherited.push(Path::parse_mod_style(input)?);
164 if input.peek(Token![<]) {
165 input.parse::<Token![<]>()?;
166 inherited.push(Path::parse_mod_style(input)?);
167 }
168
169 let mut fields = vec![];
170 let braced_content;
171 let _ = braced!(braced_content in input);
172
173 while !braced_content.is_empty() {
174 fields.push(parse_class_field(&braced_content)?);
175 if braced_content.peek(Token![,]) {
176 braced_content.parse::<Token![,]>()?;
177 } else {
178 break;
179 }
180 }
181
182 let mut constructor = ClassConstructor {
183 attributes: vec![],
184 visibility: Visibility::Public(Pub::default()),
185 generics: Generics::default(),
186 inputs: Punctuated::new(),
187 super_arguments: Punctuated::new(),
188 statements: vec![],
189 };
190
191 if !input.is_empty() {
192 constructor = parse_class_constructor(input)?;
193 }
194
195 Ok(Class {
196 oop_inheritance_crate,
197 attributes,
198 visibility,
199 name,
200 inherited,
201 fields,
202 constructor,
203 })
204 }
205}
206
207fn parse_class_field(input: ParseStream) -> Result<ClassField> {
208 let attributes = Attribute::parse_outer(input)?;
209 let visibility = input.parse::<Visibility>()?;
210 let is_reference = if input.peek(Token![ref]) {
211 input.parse::<Token![ref]>()?;
212 true
213 } else {
214 false
215 };
216 let name = input.parse::<Ident>()?;
217 input.parse::<Token![:]>()?;
218 let type_annotation = input.parse::<Type>()?;
219 input.parse::<Token![=]>()?;
220 let default_value = input.parse::<Expr>()?;
221
222 Ok(ClassField {
223 attributes,
224 visibility,
225 is_reference,
226 name,
227 type_annotation,
228 default_value,
229 })
230}
231
232fn parse_class_constructor(input: ParseStream) -> Result<ClassConstructor> {
233 let attributes = Attribute::parse_outer(input)?;
234 let visibility = input.parse::<Visibility>()?;
235 input.parse::<Token![fn]>()?;
236 let id = input.parse::<Ident>()?;
237 if id.to_string() != "constructor" {
238 id.span().unwrap().error("Identifier must be equals \"constructor\"").emit();
239 }
240 let mut generics = input.parse::<Generics>()?;
241
242 let parens_content;
243 parenthesized!(parens_content in input);
244 let inputs = parens_content.parse_terminated(FnArg::parse, Comma)?;
245
246 generics.where_clause = if input.peek(Token![where]) { Some(input.parse::<WhereClause>()?) } else { None };
247
248 let braced_content;
249 let _ = braced!(braced_content in input);
250 braced_content.parse::<Token![super]>()?;
251
252 let paren_content;
253 let _ = parenthesized!(paren_content in braced_content);
254 let super_arguments = paren_content.parse_terminated(Expr::parse, Comma)?;
255 braced_content.parse::<Token![;]>()?;
256
257 let mut statements = vec![];
258 while !braced_content.is_empty() {
259 statements.push(braced_content.parse::<Stmt>()?);
260 }
261
262 Ok(ClassConstructor {
263 attributes,
264 visibility,
265 generics,
266 inputs,
267 super_arguments,
268 statements,
269 })
270}
271
272fn parse_class_oop_inheritance_crate_ref(input: ParseStream) -> Result<Path> {
273 input.parse::<Token![use]>()?;
274 let id = input.parse::<Ident>()?;
275 if id.to_string() != "oop_inheritance" {
276 id.span().unwrap().error("Identifier must be equals \"oop_inheritance\"").emit();
277 }
278 input.parse::<Token![=]>()?;
279 let path = Path::parse_mod_style(input)?;
280 input.parse::<Token![;]>()?;
281 Ok(path)
282}
283
284#[proc_macro]
324pub fn class(input: TokenStream) -> TokenStream {
325 let Class {
326 oop_inheritance_crate, attributes, visibility, name, inherited, fields,
327 constructor
328 } = parse_macro_input!(input as Class);
329
330 let super_type = inherited[0].clone();
331 let component_name = Ident::new(&(name.to_string() + "Component"), name.span().clone());
332 let oop_inheritance_crate = oop_inheritance_crate.unwrap_or(quote! {::oop_inheritance});
333
334 let mut expanded = TokenStream::new();
335
336 let mut constructor_tokens = proc_macro2::TokenStream::new();
337 {
338 let ClassConstructor {
339 attributes,
340 visibility,
341 generics,
342 inputs,
343 super_arguments,
344 statements,
345 } = constructor;
346
347 let mut generics_p = proc_macro2::TokenStream::new();
348 let mut generics_w = proc_macro2::TokenStream::new();
349 if !generics.params.is_empty() {
350 let param_seq = generics.params;
351 generics_p.extend::<proc_macro2::TokenStream>(quote! { <#param_seq> }.try_into().unwrap());
352 }
353 if let Some(w) = generics.where_clause {
354 generics_w.extend::<proc_macro2::TokenStream>(quote! { #w }.try_into().unwrap());
355 }
356
357 constructor_tokens.extend::<proc_macro2::TokenStream>(quote! {
358 #(#attributes)*
359 #visibility fn new #generics_p (#inputs) -> Self #generics_w {
360 let this = Self(#super_type::new(#super_arguments).set(#component_name::default()).try_into().unwrap());
361 #(#statements)*
362 this
363 }
364 }.try_into().unwrap());
365 }
366
367 let mut component_fields = proc_macro2::TokenStream::new();
368 let mut component_field_defaults = proc_macro2::TokenStream::new();
369 let mut field_methods = proc_macro2::TokenStream::new();
370
371 for field in fields {
372 let ClassField {
373 attributes,
374 visibility,
375 is_reference,
376 name,
377 type_annotation,
378 default_value,
379 } = field;
380 let setter_name = Ident::new(&("set_".to_owned() + &name.to_string()), name.span().clone());
381
382 if is_reference {
383 component_fields.extend::<proc_macro2::TokenStream>(quote! {
384 #name: ::std::sync::RwLock<::std::sync::Arc<#type_annotation>>,
385 }.try_into().unwrap());
386 component_field_defaults.extend::<proc_macro2::TokenStream>(quote! {
387 #name: ::std::sync::RwLock::new(::std::sync::Arc::new(#default_value)),
388 }.try_into().unwrap());
389 field_methods.extend::<proc_macro2::TokenStream>(quote! {
390 #(#attributes)*
391 #visibility fn #name(&self) -> ::std::sync::Arc<#type_annotation> {
392 ::std::sync::Arc::clone(&*self.get::<#component_name>().unwrap().#name.read().unwrap())
393 }
394 #(#attributes)*
395 #visibility fn #setter_name(&self, value: ::std::sync::Arc<#type_annotation>) -> Self {
396 *self.get::<#component_name>().unwrap().#name.write().unwrap() = value;
397 self.clone()
398 }
399 }.try_into().unwrap());
400 } else {
401 component_fields.extend::<proc_macro2::TokenStream>(quote! {
402 #name: ::std::sync::RwLock<#type_annotation>,
403 }.try_into().unwrap());
404 component_field_defaults.extend::<proc_macro2::TokenStream>(quote! {
405 #name: ::std::sync::RwLock::new(#default_value),
406 }.try_into().unwrap());
407 field_methods.extend::<proc_macro2::TokenStream>(quote! {
408 #(#attributes)*
409 #visibility fn #name(&self) -> #type_annotation {
410 self.get::<#component_name>().unwrap().#name.read().unwrap().clone()
411 }
412 #(#attributes)*
413 #visibility fn #setter_name(&self, value: #type_annotation) -> Self {
414 *self.get::<#component_name>().unwrap().#name.write().unwrap() = value;
415 self.clone()
416 }
417 }.try_into().unwrap());
418 }
419 }
420
421 expanded.extend::<TokenStream>(quote! {
422 #(#attributes)*
423 #visibility struct #name(#super_type);
424
425 #oop_inheritance_crate::class_extends!(#name < #(#inherited)<*, use #component_name, #oop_inheritance_crate);
426
427 impl #name {
428 #constructor_tokens
429 #field_methods
430 }
431
432 struct #component_name {
433 #component_fields
434 }
435
436 impl Default for #component_name {
437 fn default() -> Self {
438 Self {
439 #component_field_defaults
440 }
441 }
442 }
443 }.try_into().unwrap());
444
445 expanded
446}