I'm wondering if its possible to create a macro that generate code based on a constant value.
I have this code :
const NB64BLOC: usize =5 //
...
for i in 0..NB64BLOC {
let (v, carry) = BigInt::overflowing_add(self.bits[i], _rhs.bits[i], c);
r.bits[i] = v;
c = carry;
}
and I wanted to generate :
let (v, carry) = BigInt::overflowing_add(self.bits[0], _rhs.bits[0], c);
r.bits[0] = v;
c = carry;
let (v, carry) = BigInt::overflowing_add(self.bits[1], _rhs.bits[1], c);
r.bits[1] = v;
c = carry;
let (v, carry) = BigInt::overflowing_add(self.bits[2], _rhs.bits[2], c);
r.bits[2] = v;
c = carry;
let (v, carry) = BigInt::overflowing_add(self.bits[3], _rhs.bits[3], c);
r.bits[3] = v;
c = carry;
let (v, carry) = BigInt::overflowing_add(self.bits[4], _rhs.bits[4], c);
r.bits[4] = v;
c = carry;
I know that it's basically loop unrolling and that the compiler should detect such a case. Nevertheless, I wanted to know if it is possible, to use this on more complicated operation.
use ::proc_macro::TokenStream;
use ::proc_macro2::{TokenStream as TokenStream2};
use ::quote::quote;
use ::syn::*;
#[proc_macro] pub
fn helper (input: TokenStream) -> TokenStream
{
let n: usize =
match ::syn::parse::<LitInt>(input)
.and_then(|lit| lit.base10_parse())
{
| Ok(it) => it,
| Err(err) => return err.to_compile_error().into(),
}
;
let mut ret = TokenStream2::new();
let mut emit = |tokens: TokenStream2| ret.extend(tokens);
for i in 0 .. n {
emit(quote! {
let (v, carry) = BigInt::overflowing_add(self.bits[#i], _rhs.bits[#i], c);
r.bits[#i] = v;
c = carry;
});
}
ret.into()
}
so that helper!(5) Just Works (but again, if you want that to work with a factored out NB64BLOC, you'll need to use a macro callback, and expand to $emit! { 5 }, so that NB64BLOC!(=> helper) works.
Many thanks @Yandros, @2e71828 for your complementary answers. As mentioned, theses solutions involves a lot of additional complexity (I'm still a Rust beginner) and / or external crates. I'm gonna have a look on how conditional compilation work on Rust, and see if it's possible to define new attribute e.g. BIT256, BIT512 ... and provide the unrolled implementation for each. This leads to longer code, but rather simple solution
Thanks again for your time and suggestions, it's really appreciated.