diff --git a/library/compiler-builtins/libm/crates/libm-macros/src/enums.rs b/library/compiler-builtins/libm/crates/libm-macros/src/enums.rs index 82dedc66ecd9..864b625eab38 100644 --- a/library/compiler-builtins/libm/crates/libm-macros/src/enums.rs +++ b/library/compiler-builtins/libm/crates/libm-macros/src/enums.rs @@ -31,6 +31,7 @@ pub fn function_enum( let enum_name = &item.ident; let mut as_str_arms = Vec::new(); + let mut from_str_arms = Vec::new(); let mut base_arms = Vec::new(); for func in ALL_OPERATIONS.iter() { @@ -40,6 +41,7 @@ pub fn function_enum( // Match arm for `fn as_str(self)` matcher as_str_arms.push(quote! { Self::#ident => #fn_name }); + from_str_arms.push(quote! { #fn_name => Self::#ident }); // Match arm for `fn base_name(self)` matcher base_arms.push(quote! { Self::#ident => #base_enum::#bname_ident }); @@ -50,11 +52,18 @@ pub fn function_enum( item.variants.push(variant); } + let variants = item.variants.iter(); + let res = quote! { // Instantiate the enum #item impl #enum_name { + /// All variants of this enum. + pub const ALL: &[Self] = &[ + #( Self::#variants, )* + ]; + /// The stringified version of this function name. pub const fn as_str(self) -> &'static str { match self { @@ -62,12 +71,26 @@ pub fn function_enum( } } + /// If `s` is the name of a function, return it. + pub fn from_str(s: &str) -> Option { + let ret = match s { + #( #from_str_arms , )* + _ => return None, + }; + Some(ret) + } + /// The base name enum for this function. pub const fn base_name(self) -> #base_enum { match self { #( #base_arms, )* } } + + /// Return information about this operation. + pub fn math_op(self) -> &'static crate::op::MathOpInfo { + crate::op::ALL_OPERATIONS.iter().find(|op| op.name == self.as_str()).unwrap() + } } }; diff --git a/library/compiler-builtins/libm/crates/libm-macros/tests/enum.rs b/library/compiler-builtins/libm/crates/libm-macros/tests/enum.rs index 884b8d8d6518..93e209a0dcc9 100644 --- a/library/compiler-builtins/libm/crates/libm-macros/tests/enum.rs +++ b/library/compiler-builtins/libm/crates/libm-macros/tests/enum.rs @@ -1,6 +1,6 @@ #[libm_macros::function_enum(BaseName)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum Function {} +pub enum Identifier {} #[libm_macros::base_name_enum] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -8,12 +8,31 @@ pub enum BaseName {} #[test] fn as_str() { - assert_eq!(Function::Sin.as_str(), "sin"); - assert_eq!(Function::Sinf.as_str(), "sinf"); + assert_eq!(Identifier::Sin.as_str(), "sin"); + assert_eq!(Identifier::Sinf.as_str(), "sinf"); +} + +#[test] +fn from_str() { + assert_eq!(Identifier::from_str("sin").unwrap(), Identifier::Sin); + assert_eq!(Identifier::from_str("sinf").unwrap(), Identifier::Sinf); } #[test] fn basename() { - assert_eq!(Function::Sin.base_name(), BaseName::Sin); - assert_eq!(Function::Sinf.base_name(), BaseName::Sin); + assert_eq!(Identifier::Sin.base_name(), BaseName::Sin); + assert_eq!(Identifier::Sinf.base_name(), BaseName::Sin); } + +#[test] +fn math_op() { + assert_eq!(Identifier::Sin.math_op().float_ty, FloatTy::F64); + assert_eq!(Identifier::Sinf.math_op().float_ty, FloatTy::F32); +} + +// Replicate the structure that we have in `libm-test` +mod op { + include!("../../libm-macros/src/shared.rs"); +} + +use op::FloatTy;