use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{Token, parse_macro_input, visit_mut::VisitMut};
use utils::*;
mod partial_application;
mod replace;
mod struct_fields;
#[proc_macro_attribute]
pub fn setup_error_handling_struct(_attr: TokenStream, item: TokenStream) -> TokenStream {
struct_fields::setup_error_handling_struct(_attr, item)
}
#[proc_macro_attribute]
pub fn setup_printer_struct(_attr: TokenStream, item: TokenStream) -> TokenStream {
struct_fields::setup_printer_struct(_attr, item)
}
mod utils {
use super::*;
pub(crate) fn crate_name() -> Ident {
let krate = module_path!().split("::").next().unwrap();
Ident::new(krate, Span::call_site())
}
pub(crate) fn prepend(item: TokenStream, prefix: proc_macro2::TokenStream) -> TokenStream {
let item: proc_macro2::TokenStream = item.into();
quote! {
#prefix
#item
}
.into()
}
pub(crate) fn add_derive(item: TokenStream, payload: proc_macro2::TokenStream) -> TokenStream {
prepend(item, quote! {#[derive(#payload)]})
}
pub(crate) fn rust_engine_krate_name() -> proc_macro2::TokenStream {
use proc_macro_crate::{FoundCrate, crate_name};
match crate_name("hax-rust-engine").unwrap() {
FoundCrate::Itself => quote!(crate),
FoundCrate::Name(name) => {
let ident = Ident::new(&name, Span::call_site());
quote!( #ident )
}
}
}
}
#[proc_macro_attribute]
pub fn derive_group_for_ast(_attr: TokenStream, item: TokenStream) -> TokenStream {
let krate = crate_name();
prepend(
item,
quote! {
#[#krate::derive_group_for_ast_base]
#[#krate::derive_group_for_ast_serialization]
},
)
}
#[proc_macro_attribute]
pub fn derive_group_for_ast_serialization(_attr: TokenStream, item: TokenStream) -> TokenStream {
add_derive(
item,
quote! {::serde::Deserialize, ::serde::Serialize, ::schemars::JsonSchema},
)
}
#[proc_macro_attribute]
pub fn derive_group_for_ast_base(_attr: TokenStream, item: TokenStream) -> TokenStream {
add_derive(
item,
quote! {Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, derive_generic_visitor::Drive, derive_generic_visitor::DriveMut},
)
}
#[proc_macro_attribute]
pub fn replace(attr: TokenStream, item: TokenStream) -> TokenStream {
replace::replace(attr, item)
}
#[proc_macro_attribute]
pub fn partial_apply(attr: TokenStream, item: TokenStream) -> TokenStream {
partial_application::partial_apply(attr, item)
}
#[proc_macro_attribute]
pub fn prepend_associated_functions_with(attr: TokenStream, item: TokenStream) -> TokenStream {
struct Visitor {
prefix: syn::Expr,
}
impl VisitMut for Visitor {
fn visit_item_impl_mut(&mut self, impl_block: &mut syn::ItemImpl) {
for item in &mut impl_block.items {
let syn::ImplItem::Fn(impl_item_fn) = item else {
continue;
};
impl_item_fn.block.stmts.insert(
0,
syn::Stmt::Expr(self.prefix.clone(), Some(Token))),
);
}
}
}
let mut item: syn::Item = parse_macro_input!(item);
let prefix = parse_macro_input!(attr);
Visitor { prefix }.visit_item_mut(&mut item);
quote! {#item}.into()
}