1use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, parse::{Parse, ParseStream, Result}, parse_quote, ItemFn, LitStr, Stmt, Meta, MetaList, MetaNameValue, punctuated::Punctuated, Attribute,
6token::Comma, Expr, Lit, Token, PatIdent, Pat, Local, PathSegment, DeriveInput};
7use proc_macro2::{TokenStream as TokenStream2, Span};
8use Mademoiselle_Entropia::custom_traits::STRN;
9mod lex;
10struct AttrArgs {
11 metas: Punctuated<Meta, Token![,]>,
12}
13impl Default for AttrArgs {
14 fn default() -> Self {
15 Self {
16 metas: Punctuated::new(),
17 }
18 }
19}
20struct AttrArgsIter<'a> {
21 iter: syn::punctuated::Iter<'a, Meta>, }
23
24impl<'a> Iterator for AttrArgsIter<'a> {
25 type Item = &'a Meta; fn next(&mut self) -> Option<Self::Item> {
28 self.iter.next() }
30}
31
32impl AttrArgs {
34 fn iter(&self) -> AttrArgsIter {
35 AttrArgsIter {
36 iter: self.metas.iter(), }
38 }
39}
40impl Parse for AttrArgs {
41 fn parse(input: ParseStream) -> syn::Result<Self> {
42 let metas = Punctuated::<Meta, Token![,]>::parse_terminated_with(input, Meta::parse)?;
43 Ok(AttrArgs { metas })
44 }
45}
46 macro_rules! _prnt_func {
47 ($name:ident, $body:block) => {
48 pub fn $name() {
49 println!("{}", stringify!($body));
50 }
51 };
52}
53#[proc_macro_attribute]
54pub fn inject(_attr: TokenStream, item: TokenStream) -> TokenStream {
55 let mut input: ItemFn = parse_macro_input!(item as ItemFn);
56 let mut new_stmts = Vec::<Stmt>::new();
57 let strn_stmts = format! ("{:?}", input.block.stmts);
58 let add_to: Stmt = syn::parse_quote! {
59 println!("yst {}", #strn_stmts);
60 };
61 let stmts = &input.block.stmts;
62 let stmts_len = stmts.len();
63 for j in 0..stmts_len {
64 if j == stmts_len -1 {new_stmts.push ( add_to.clone() ); }
65 new_stmts.push(stmts [j].clone());
66 }
67 input.block.stmts = new_stmts;
68 return TokenStream::from(quote! { #input })
69}
70#[proc_macro_attribute]
71pub fn inject_after_hello(_attr: TokenStream, item: TokenStream) -> TokenStream {
72 let mut input: ItemFn = parse_macro_input!(item as ItemFn);
73 let mut new_stmts = Vec::<Stmt>::new();
74
75 for stmt in input.block.stmts {
76 new_stmts.push(stmt.clone());
78
79 if let Stmt::Expr(syn::Expr::Macro(expr_macro), _) = &stmt {
81 let macro_path = &expr_macro.mac.path.segments;
82 let macro_tokens = expr_macro.mac.tokens.to_string();
83 if macro_path.len() == 1
84 && macro_path[0].ident == "println"
85 && macro_tokens.contains("\"hello\"")
86 {
87 new_stmts.push(syn::parse_quote! {
89 println!("-- injected after Hello, world!");
90 });
91 }
92 }
93 }
94
95 input.block.stmts = new_stmts;
96
97 TokenStream::from(quote! { #input })
98}
99#[proc_macro_attribute]
102pub fn inject_tst(args: TokenStream, item: TokenStream) -> TokenStream {
103 let (sub_fn, sub_fn_id) = prnt_func ("sub_fn", item.clone());
104 let item_str = format! ("{}", item.clone() );
105 let mut ext_quote = quote!();
106 let item0 = item.clone();
107 let mut input: ItemFn = parse_macro_input!(item0 as ItemFn);
108 let lit: LitStr = LitStr::new("Alice", proc_macro2::Span::call_site());
109 let val = Expr::Lit(syn::ExprLit {
110 attrs: vec![],
111 lit: Lit::Str(lit),
112 });
113 let meta_name_value = MetaNameValue {
114 path: syn::parse_quote!(name), eq_token: Default::default(), value: val,
117 };
118 let args = parse_macro_input! (args as AttrArgs);
130 for arg in args.iter() {
132 match arg {
133 Meta::Path(path) => { ext_quote.extend (
134 quote! { println!("Simple attribute: {:?}", #path); }
135 );
136 }
137 Meta::List(list) => {
138 let list = list.tokens.clone();
139 ext_quote.extend (
140 quote! {println!("Attribute with args: {:?}", #list); }
141 );
142 }
143 Meta::NameValue(name_value) => {
144 let ident = name_value.path.get_ident().unwrap().to_string();
145 let value = name_value.value.clone();
146 ext_quote.extend (
147 quote! { println!("Name-value attribute: {} = {:?}",
148 #ident,
149 #value);
150 } );
151 }
152 };
153 }
154 let input_str = format! ("{:#?}", input);
197 let mut new_stmts = Vec::<Stmt>::new();
198 let strn_stmts = format! ("{:?}", input.block.stmts);
199 let add_to: Stmt = syn::parse_quote! {
200 println!("yst {}\n{}\n{}", #strn_stmts, #input_str, #item_str);
201 };
202 let stmts = &input.block.stmts;
203 let stmts_len = stmts.len();
204 for j in 0..stmts_len {
205 if j == stmts_len -1 {new_stmts.push ( add_to.clone() ); }
206 new_stmts.push(stmts [j].clone());
207 }
208 input.block.stmts = new_stmts;
209 let input_str = format! ("{:#?}", input);
210 let ext_quote_str = ext_quote.to_string();
211 return TokenStream::from(quote! {
213 #sub_fn
214 pub fn lets_prnt_func () {
215 println! ("input {} ext {}", #input_str, #ext_quote_str );
216 #ext_quote
217 #sub_fn_id();
218 }} )
219}
220#[proc_macro]
221pub fn my_macro(input: TokenStream) -> TokenStream {
222 let ident = syn::Ident::new("my_variable", Span::call_site());
224 let mut new_stmts = Vec::<Stmt>::new();
225 let mut input: ItemFn = parse_macro_input!(input as ItemFn);
226 let expanded = TokenStream::from (quote! {
228 let #ident = #input;
229 } );
230
231 expanded.into()
232}
233 #[proc_macro]
234 pub fn stmt_to_tokenstream(input: TokenStream) -> TokenStream {
235 let stmt: Stmt = parse_macro_input!(input as Stmt);
237
238 let output = quote! {
240 #stmt
241 };
242
243 output.into()
244 }
245 #[proc_macro_attribute]
246 pub fn just_prnt (args: TokenStream, input: TokenStream) -> TokenStream {
247 let func_body = input.to_string();
248 let out = quote! {
249 pub fn lets_prnt_func () {
250 println! ("{}", #func_body);
251 }
252 };
253 return out.into()
254 }
255 #[inline]
256 fn prnt_func (name_fn: &str, input: TokenStream) -> (TokenStream2, syn::Ident) {
257 let func_body = input.to_string();
258 let name_fn_str = name_fn.strn();
259 let name_fn = strn_to_Ident (&name_fn);
260 let out = quote! {
265 pub fn #name_fn () {
266 println! ("{}", #func_body);
268 }
269 };
270 let sub_fn: proc_macro2::TokenStream = out.into();
272 let sub_fn_id = syn::Ident::new( &name_fn_str, proc_macro2::Span::call_site());
273 return (sub_fn, sub_fn_id)
274 }
275fn strn_to_LitStr(s: &str) -> LitStr {
276 LitStr::new(s, Span::call_site())
277}
278fn strn_to_Ident(s: &str) -> syn::Ident {
279 syn::Ident::new(s, Span::call_site())
280}
281#[proc_macro_attribute]
282pub fn prnt_vars(_attr: TokenStream, item: TokenStream) -> TokenStream {
283use syn::spanned::Spanned;
284 let item_fn = item.clone();
285 let mut input_fn = parse_macro_input!( item_fn as ItemFn);
286 let span = input_fn.attrs.first().map(|attr| attr.span()).unwrap_or_else(proc_macro2::Span::call_site);
287 let fn_name = &input_fn.sig.ident;
288 let mut new_stmts = Vec::new();
289
290 for stmt in input_fn.block.stmts {
291 if let Stmt::Local(local) = &stmt {
292 let span = local.init.as_ref().unwrap().expr.clone(); let local_pat = format! ("{:?}\nspanЪЪ {:?}", &local, span );
300
301 let print_stmts = quote! {
304 println! ("Loc {:?}", #local_pat);
307 };
308 new_stmts.push(quote! {
311 #stmt
312 #print_stmts
313 });
314 }
316 new_stmts.push(quote! { #stmt });
317 }
318
319 let expanded = quote! {
320 fn #fn_name() {
321 println!("[FN] Entering {}", stringify!(#fn_name));
322 #(#new_stmts)*
323 }
324 };
325
326 expanded.into()
327}
328
329