mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: tracer: add simple callback decorator using proc-macro
This commit is contained in:
parent
d4b2f78505
commit
6b770c4aea
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -106,6 +106,7 @@ dependencies = [
|
|||||||
"sbi-rt",
|
"sbi-rt",
|
||||||
"spin",
|
"spin",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
|
"tracer",
|
||||||
"uapi",
|
"uapi",
|
||||||
"uart_16550",
|
"uart_16550",
|
||||||
"utils",
|
"utils",
|
||||||
@ -246,6 +247,14 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracer"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uapi"
|
name = "uapi"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
11
lib/tracer/Cargo.toml
Normal file
11
lib/tracer/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "tracer"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = { version = "2.0", features = ["full"] }
|
||||||
|
quote = "1.0"
|
60
lib/tracer/src/lib.rs
Normal file
60
lib/tracer/src/lib.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{
|
||||||
|
parse::Parser, parse_macro_input, punctuated::Punctuated, Expr, ExprLit, ExprPath, ItemFn, Lit, MetaNameValue, Token,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn call_count(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let args = Punctuated::<MetaNameValue, Token![,]>::parse_terminated.parse(attr).unwrap();
|
||||||
|
|
||||||
|
let mut debug_print = false;
|
||||||
|
let mut callback = vec![];
|
||||||
|
|
||||||
|
for arg in args {
|
||||||
|
if !arg.path.is_ident("log") && !arg.path.is_ident("callback") {
|
||||||
|
panic!("Unknown attribute: {:?}.", arg.path.get_ident());
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.path.is_ident("log") {
|
||||||
|
if let Expr::Lit(ExprLit { lit: Lit::Bool(b), .. }) = &arg.value {
|
||||||
|
debug_print = b.value;
|
||||||
|
} else {
|
||||||
|
panic!("Unsupported log option provided.");
|
||||||
|
}
|
||||||
|
} else if arg.path.is_ident("callback") {
|
||||||
|
if let Expr::Path(ExprPath { path, .. }) = arg.value {
|
||||||
|
let ident = path.get_ident().expect("Invalid callback function provided.");
|
||||||
|
callback.push(ident.clone());
|
||||||
|
} else {
|
||||||
|
panic!("Unsupported callback option provided.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = parse_macro_input!(item as ItemFn);
|
||||||
|
let fn_name = &input.sig.ident;
|
||||||
|
let fn_block = &input.block;
|
||||||
|
let fn_vis = &input.vis;
|
||||||
|
let fn_sig = &input.sig;
|
||||||
|
|
||||||
|
let call_callback = callback.iter().map(|ident| {
|
||||||
|
quote! {
|
||||||
|
if #debug_print { log::debug!("[tracer][callback] invoking {}", stringify!(#ident)) }
|
||||||
|
#ident();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#fn_vis #fn_sig {
|
||||||
|
if #debug_print { log::debug!("[tracer] tracing {}", stringify!(#fn_name)) }
|
||||||
|
{ #(#call_callback)* }
|
||||||
|
if #debug_print { log::debug!("[tracer][function] invoking {}", stringify!(#fn_name)) }
|
||||||
|
(|| #fn_block)()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(expanded)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user