mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 01:35: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",
|
||||
"spin",
|
||||
"static_assertions",
|
||||
"tracer",
|
||||
"uapi",
|
||||
"uart_16550",
|
||||
"utils",
|
||||
@ -246,6 +247,14 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uapi"
|
||||
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