Unraw idents

This commit is contained in:
lumi 2025-06-23 07:18:16 +10:00
parent 884acd71e1
commit c3fb3407c4
Signed by: luaneko
GPG Key ID: 406809B8763FF07A
2 changed files with 39 additions and 27 deletions

View File

@ -2,7 +2,7 @@ use crate::utils::{ffi_crate, syn_assert, syn_error};
use darling::FromMeta; use darling::FromMeta;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::*; use syn::{ext::IdentExt, *};
#[derive(Debug, FromMeta)] #[derive(Debug, FromMeta)]
pub struct Args {} pub struct Args {}
@ -42,8 +42,8 @@ pub fn transform(_args: Args, mut item: Item) -> Result<TokenStream> {
fn generate_type(ty: &Ident) -> Result<TokenStream> { fn generate_type(ty: &Ident) -> Result<TokenStream> {
let ffi = ffi_crate(); let ffi = ffi_crate();
let fmt = quote!(::std::format!); let fmt = quote!(::std::format!);
let name = LitStr::new(&format!("{ty}"), ty.span()); let name = LitStr::new(&format!("{}", ty.unraw()), ty.span());
let cdecl_fmt = LitStr::new(&format!("struct {ty} {{}}"), ty.span()); let cdecl_fmt = LitStr::new(&format!("struct {} {{}}", ty.unraw()), ty.span());
Ok(quote! { Ok(quote! {
unsafe impl #ffi::Type for #ty { unsafe impl #ffi::Type for #ty {
@ -79,8 +79,8 @@ fn generate_cdef_structure(str: &mut ItemStruct) -> Result<TokenStream> {
let build = generate_build_cdef(&to_cfields(&mut str.fields)?)?; let build = generate_build_cdef(&to_cfields(&mut str.fields)?)?;
Ok(quote! { Ok(quote! {
unsafe impl #ffi::CDef for #ty { unsafe impl #ffi::Cdef for #ty {
fn build(b: &mut #ffi::CDefBuilder) { #build } fn build(b: &mut #ffi::CdefBuilder) { #build }
} }
}) })
} }
@ -104,8 +104,8 @@ fn generate_cdef_enum(enu: &mut ItemEnum) -> Result<TokenStream> {
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
Ok(quote! { Ok(quote! {
unsafe impl #ffi::CDef for #ty { unsafe impl #ffi::Cdef for #ty {
fn build(b: &mut #ffi::CDefBuilder) { fn build(b: &mut #ffi::CdefBuilder) {
b.field::<::std::ffi::c_int>("__tag").inner_union(|b| { #(#build)* }); b.field::<::std::ffi::c_int>("__tag").inner_union(|b| { #(#build)* });
} }
} }
@ -133,7 +133,7 @@ fn to_cfields(fields: &mut Fields) -> Result<Vec<CField>> {
.map(|(i, field)| { .map(|(i, field)| {
Ok(CField { Ok(CField {
name: match field.ident { name: match field.ident {
Some(ref name) => format!("{name}"), Some(ref name) => format!("{}", name.unraw()),
None => format!("__{i}"), None => format!("__{i}"),
}, },
ty: field.ty.clone(), ty: field.ty.clone(),

View File

@ -1,7 +1,7 @@
use crate::utils::{ffi_crate, is_primitive, is_unit, pat_ident, syn_assert, ty_name}; use crate::utils::{ffi_crate, is_primitive, is_unit, pat_ident, syn_assert, ty_name};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::*; use syn::{ext::IdentExt, *};
pub fn transform(mut imp: ItemImpl) -> Result<TokenStream> { pub fn transform(mut imp: ItemImpl) -> Result<TokenStream> {
syn_assert!( syn_assert!(
@ -44,12 +44,13 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
.map(generate_ffi_register) .map(generate_ffi_register)
.collect::<Result<_>>()?; .collect::<Result<_>>()?;
let ffi_new_fallback = match ffi_funcs let ffi_register_new = match ffi_funcs
.iter() .iter()
.find(|f| f.attrs.metatable.as_deref() == Some("new")) .find(|f| f.attrs.metatable.as_deref() == Some("new"))
{ {
Some(_) => None, Some(_) => None,
None => Some({ None => Some({
// fallback error constructor to prevent creating uninitialised ctypes
let err = format!(r#"function() error("type '{ty_name}' has no constructor"); end"#); let err = format!(r#"function() error("type '{ty_name}' has no constructor"); end"#);
quote! { b.metatable_raw("new", #err); } quote! { b.metatable_raw("new", #err); }
}), }),
@ -57,6 +58,19 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
let ffi_drop_rname = format_ident!("__ffi_drop"); let ffi_drop_rname = format_ident!("__ffi_drop");
let ffi_drop_cname = format!("{ty_name}_drop"); let ffi_drop_cname = format!("{ty_name}_drop");
let ffi_wrapper_drop = quote! {
#[unsafe(export_name = #ffi_drop_cname)]
unsafe extern "C" fn #ffi_drop_rname(ptr: *mut Self) {
unsafe { ::std::ptr::drop_in_place(ptr) }
}
};
let ffi_register_drop = quote! {
if ::std::mem::needs_drop::<Self>() {
b.declare::<unsafe extern "C" fn(*mut Self)>(#ffi_drop_cname);
b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname));
}
};
// ffi function symbol export code // ffi function symbol export code
let ffi_exports = { let ffi_exports = {
@ -75,11 +89,7 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
Ok(quote! { Ok(quote! {
impl #ty { impl #ty {
#(#ffi_wrappers)* #(#ffi_wrappers)*
#ffi_wrapper_drop
#[unsafe(export_name = #ffi_drop_cname)]
unsafe extern "C" fn #ffi_drop_rname(ptr: *mut Self) {
unsafe { ::std::ptr::drop_in_place(ptr) }
}
} }
unsafe impl #ffi::Metatype for #ty { unsafe impl #ffi::Metatype for #ty {
@ -89,10 +99,8 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
#(#ffi_register)* #(#ffi_register)*
#(#lua_register)* #(#lua_register)*
#ffi_new_fallback #ffi_register_new
#ffi_register_drop
b.declare::<unsafe extern "C" fn(*mut Self)>(#ffi_drop_cname);
b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname));
} }
} }
@ -154,9 +162,9 @@ fn get_ffi_functions(imp: &mut ItemImpl) -> Result<Vec<FfiFunction>> {
funcs.push(FfiFunction { funcs.push(FfiFunction {
name: func.sig.ident.clone(), name: func.sig.ident.clone(),
rust_name: format_ident!("__ffi_{}", func.sig.ident), rust_name: format_ident!("__ffi_{}", func.sig.ident.unraw()),
lua_name: format!("{}", func.sig.ident), lua_name: format!("{}", func.sig.ident.unraw()),
c_name: format!("{}_{}", ty_name(&imp.self_ty)?, func.sig.ident), c_name: format!("{}_{}", ty_name(&imp.self_ty)?, func.sig.ident.unraw()),
params, params,
ret, ret,
ret_by_out, ret_by_out,
@ -311,7 +319,7 @@ fn generate_ffi_exports<'a>(
struct LuaFunction { struct LuaFunction {
name: String, name: String,
params: Vec<PatType>, params: Vec<Pat>,
body: Block, body: Block,
} }
@ -325,8 +333,8 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
&& let Some(ref abi) = abi.name && let Some(ref abi) = abi.name
&& abi.value() == "Lua" && abi.value() == "Lua"
{ {
// normalise inputs to PatType // normalise inputs to Pat
let params = func let mut params: Vec<_> = func
.sig .sig
.inputs .inputs
.iter() .iter()
@ -337,11 +345,15 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
syn_assert!(recv.mutability.is_none(), recv, "cannot be mut"); syn_assert!(recv.mutability.is_none(), recv, "cannot be mut");
parse_quote! { self: cdata } parse_quote! { self: cdata }
} }
FnArg::Typed(ty) => ty.clone(), FnArg::Typed(ty) => Pat::Type(ty.clone()),
}) })
}) })
.collect::<Result<_>>()?; .collect::<Result<_>>()?;
if let Some(_) = func.sig.variadic {
params.push(parse_quote!(variadic!()));
}
// shouldn't specify an output type // shouldn't specify an output type
syn_assert!( syn_assert!(
matches!(func.sig.output, ReturnType::Default), matches!(func.sig.output, ReturnType::Default),
@ -350,7 +362,7 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
); );
funcs.push(LuaFunction { funcs.push(LuaFunction {
name: format!("{}", func.sig.ident), name: format!("{}", func.sig.ident.unraw()),
body: func.block.clone(), body: func.block.clone(),
params, params,
}); });