Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 8988118

Browse files
committed
Introduce an enum to represent different functions
Canonical names enum Finish macro adjustments Fix macro Clean up macro, no more types Sorted out the annoying lifetime errors Musl back online Update mpfloat module Cleanup, test module builds Cleanup Reset cargo.toml Update macro tests
1 parent 56a27b6 commit 8988118

File tree

12 files changed

+637
-325
lines changed

12 files changed

+637
-325
lines changed

crates/libm-macros/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ publish = false
88
proc-macro = true
99

1010
[dependencies]
11+
heck = "0.5.0"
1112
proc-macro2 = "1.0.88"
1213
quote = "1.0.37"
1314
syn = { version = "2.0.79", features = ["full", "extra-traits", "visit-mut"] }

crates/libm-macros/src/enums.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use heck::ToUpperCamelCase;
2+
use proc_macro2 as pm2;
3+
use proc_macro2::{Ident, Span};
4+
use quote::quote;
5+
use syn::spanned::Spanned;
6+
use syn::{Fields, ItemEnum, Variant};
7+
8+
use crate::{ALL_FUNCTIONS_FLAT, base_name};
9+
10+
pub fn function_enum(
11+
mut item: ItemEnum,
12+
attributes: pm2::TokenStream,
13+
) -> syn::Result<pm2::TokenStream> {
14+
expect_empty_enum(&item)?;
15+
let attr_span = attributes.span();
16+
let mut attr = attributes.into_iter();
17+
let Some(tt) = attr.next() else {
18+
return Err(syn::Error::new(attr_span, "expected one attribute"));
19+
};
20+
21+
let pm2::TokenTree::Ident(base_enum) = tt else {
22+
return Err(syn::Error::new(tt.span(), "expected one attribute"));
23+
};
24+
25+
let item_name = &item.ident;
26+
let mut as_str_arms = Vec::new();
27+
let mut base_arms = Vec::new();
28+
29+
for func in ALL_FUNCTIONS_FLAT.iter() {
30+
let fn_name = func.name;
31+
let ident = Ident::new(&fn_name.to_upper_camel_case(), Span::call_site());
32+
as_str_arms.push(quote! { Self::#ident => #fn_name });
33+
34+
let variant = Variant {
35+
attrs: Vec::new(),
36+
ident: ident.clone(),
37+
fields: Fields::Unit,
38+
discriminant: None,
39+
};
40+
41+
item.variants.push(variant);
42+
43+
let bname_ident = Ident::new(&base_name(&fn_name).to_upper_camel_case(), Span::call_site());
44+
base_arms.push(quote! { Self::#ident => #base_enum::#bname_ident })
45+
}
46+
47+
let res = quote! {
48+
#item
49+
50+
impl #item_name {
51+
const fn as_str(self) -> &'static str {
52+
match self {
53+
#( #as_str_arms ),*
54+
}
55+
}
56+
57+
const fn base_name(self) -> #base_enum {
58+
match self {
59+
#( #base_arms ),*
60+
}
61+
}
62+
}
63+
};
64+
65+
Ok(res)
66+
}
67+
68+
pub fn base_name_enum(
69+
mut item: ItemEnum,
70+
attributes: pm2::TokenStream,
71+
) -> syn::Result<pm2::TokenStream> {
72+
expect_empty_enum(&item)?;
73+
if !attributes.is_empty() {
74+
let sp = pm2::TokenStream::from(attributes).span();
75+
return Err(syn::Error::new(sp.span(), "no attributes expected"));
76+
}
77+
78+
let mut base_names: Vec<_> =
79+
ALL_FUNCTIONS_FLAT.iter().map(|func| base_name(&func.name)).collect();
80+
base_names.sort_unstable();
81+
base_names.dedup();
82+
83+
let item_name = &item.ident;
84+
let mut as_str_arms = Vec::new();
85+
86+
for base_name in base_names {
87+
let ident = Ident::new(&base_name.to_upper_camel_case(), Span::call_site());
88+
as_str_arms.push(quote! { Self::#ident => #base_name });
89+
90+
let variant =
91+
Variant { attrs: Vec::new(), ident, fields: Fields::Unit, discriminant: None };
92+
93+
item.variants.push(variant);
94+
}
95+
96+
let res = quote! {
97+
#item
98+
99+
impl #item_name {
100+
const fn as_str(self) -> &'static str {
101+
match self {
102+
#( #as_str_arms ),*
103+
}
104+
}
105+
}
106+
};
107+
108+
Ok(res)
109+
}
110+
111+
fn expect_empty_enum(item: &ItemEnum) -> syn::Result<()> {
112+
if !item.variants.is_empty() {
113+
Err(syn::Error::new(item.variants.span(), "expected an empty enum"))
114+
} else {
115+
Ok(())
116+
}
117+
}

0 commit comments

Comments
 (0)