feat: rec attrset

This commit is contained in:
2025-08-08 12:12:23 +08:00
parent 67cdcfea33
commit a9cfddbf5c
13 changed files with 147 additions and 180 deletions

View File

@@ -17,7 +17,9 @@ use convert_case::{Case, Casing};
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::{ToTokens, format_ident, quote};
use syn::{FnArg, Item, ItemFn, ItemMod, Pat, PatType, Type, Visibility, parse_macro_input};
use syn::{
FnArg, Item, ItemFn, ItemMod, Pat, PatIdent, PatType, Type, Visibility, parse_macro_input,
};
/// The implementation of the `#[builtins]` macro.
pub fn builtins_impl(input: TokenStream) -> TokenStream {
@@ -144,9 +146,15 @@ fn generate_primop_wrapper(
// Check if the first argument is a context `&mut Ctx`.
let has_ctx = if let Some(FnArg::Typed(first_arg)) = user_args.peek() {
if let Type::Reference(_) = *first_arg.ty {
user_args.next(); // Consume the context argument
true
if let (Type::Reference(_), Pat::Ident(PatIdent { ident, .. })) =
(&*first_arg.ty, &*first_arg.pat)
{
if ident == "ctx" {
user_args.next();
true
} else {
false
}
} else {
false
}
@@ -163,17 +171,7 @@ fn generate_primop_wrapper(
// Generate code to unpack and convert arguments from the `Vec<Value>`.
let arg_unpacks = arg_pats.iter().enumerate().map(|(i, arg)| {
let arg_name = match &arg {
FnArg::Typed(PatType { pat, .. }) => {
if let Pat::Ident(pat_ident) = &**pat {
pat_ident.ident.clone()
} else {
// Create a placeholder name if the pattern is not a simple ident.
format_ident!("arg{}", i, span = Span::call_site())
}
}
_ => format_ident!("arg{}", i, span = Span::call_site()),
};
let arg_name = format_ident!("_arg{}", i, span = Span::call_site());
let arg_ty = match &arg {
FnArg::Typed(PatType { ty, .. }) => ty,
_ => unreachable!(),
@@ -190,12 +188,8 @@ fn generate_primop_wrapper(
.iter()
.enumerate()
.map(|(i, arg)| match &arg {
FnArg::Typed(PatType { pat, .. }) => {
if let Pat::Ident(pat_ident) = &**pat {
pat_ident.ident.clone()
} else {
format_ident!("arg{}", i, span = Span::call_site())
}
FnArg::Typed(PatType { .. }) => {
format_ident!("_arg{}", i, span = Span::call_site())
}
_ => unreachable!(),
})