constant macro arrays
-rw-r--r--Cargo.toml2
-rw-r--r--src/lib.rs67
2 files changed, 41 insertions, 28 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 45aee1b..95c380e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "car"
-version = "0.1.2"
+version = "0.1.3"
authors = ["bend-n <[email protected]>"]
description = "std::array::{map, from_fn, try_from_fn} in const"
edition = "2021"
diff --git a/src/lib.rs b/src/lib.rs
index 20e4025..da6dc37 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -57,13 +57,15 @@ pub fn from_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
/// [Map](array::map) in const.
/// ```
/// assert_eq!(car::map!([1, 2, 3], |x| x * 2), [2, 4, 6]);
+/// assert_eq!(car::map!([1, 2, 3], std::convert::identity), [1, 2, 3]);
/// ```
#[proc_macro]
pub fn map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
struct Args {
array: Expr,
- f: ExprClosure,
+ f: Expr,
}
+
impl Parse for Args {
fn parse(input: parse::ParseStream) -> Result<Self> {
let mut args = Punctuated::<Expr, Token![,]>::parse_terminated(input)?;
@@ -73,30 +75,49 @@ pub fn map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
args.len()
)));
}
- let f = match args.pop().unwrap().into_value() {
- Expr::Closure(x) => x,
- x => return Err(Error::new_spanned(x, "mismatched types: expected closure")),
- };
+ let f = args.pop().unwrap().into_value();
let array = args.pop().unwrap().into_value();
Ok(Self { array, f })
}
}
- let Args {
- array,
- f: ExprClosure { body, inputs, .. },
- } = parse_macro_input!(input as Args);
- let n = inputs.len();
- let ns = inputs.span();
- let mut inputs = inputs.into_iter();
- let Some(binding) = inputs.next() else {
- return Error::new(ns, format!("expected one (or 2) inputs, found {n} inputs"))
- .into_compile_error()
- .into();
- };
- let index = inputs.next().into_iter();
+ let Args { array, f } = parse_macro_input!(input as Args);
let lib = lib();
+ let b = match f {
+ Expr::Closure(ExprClosure { body, inputs, .. }) => {
+ let n = inputs.len();
+ let ns = inputs.span();
+ let mut inputs = inputs.into_iter();
+ let Some(binding) = inputs.next() else {
+ return Error::new(ns, format!("expected one (or 2) inputs, found {n} inputs"))
+ .into_compile_error()
+ .into();
+ };
+
+ let index = inputs.next().into_iter();
+ quote! {
+ let i = i;
+ let #binding = unsafe { __ap.add(i).read() };
+ let __out = ();
+ let __arr = ();
+ #(let #index = i;)*
+
+ #body
+ }
+ }
+ Expr::Path(e) => quote! {
+ let i = i;
+ let __out = ();
+ let __arr = ();
+ #e(unsafe { __ap.add(i).read() })
+ },
+ e => {
+ return Error::new(e.span(), format!("mismatched types: expected function"))
+ .into_compile_error()
+ .into()
+ }
+ };
quote! { {
#lib
@@ -107,15 +128,7 @@ pub fn map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let __arr = ::core::mem::ManuallyDrop::new(__arr);
let mut i = 0usize;
while i < size {
- __out[i] = ::core::mem::MaybeUninit::new({
- let i = i;
- let #binding = unsafe { __ap.add(i).read() };
- let __out = ();
- let __arr = ();
- #(let #index = i;)*
-
- #body
- });
+ __out[i] = ::core::mem::MaybeUninit::new({ #b });
i += 1;
}
unsafe { aai(__out) }