Browse Source

Migrate ff_derive to syn 0.14 and quote 0.6

master
Jack Grigg 6 years ago
parent
commit
428f463555
No known key found for this signature in database
GPG Key ID: 1B8D649257DB0829
  1. 5
      ff_derive/Cargo.toml
  2. 169
      ff_derive/src/lib.rs

5
ff_derive/Cargo.toml

@ -12,8 +12,9 @@ repository = "https://github.com/ebfull/ff"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
syn = "0.11"
quote = "0.3"
num-bigint = "0.1" num-bigint = "0.1"
num-traits = "0.1" num-traits = "0.1"
num-integer = "0.1" num-integer = "0.1"
proc-macro2 = "0.4"
quote = "0.6"
syn = "0.14"

169
ff_derive/src/lib.rs

@ -1,6 +1,7 @@
#![recursion_limit = "1024"] #![recursion_limit = "1024"]
extern crate proc_macro; extern crate proc_macro;
extern crate proc_macro2;
extern crate syn; extern crate syn;
#[macro_use] #[macro_use]
extern crate quote; extern crate quote;
@ -12,18 +13,16 @@ extern crate num_traits;
use num_bigint::BigUint; use num_bigint::BigUint;
use num_integer::Integer; use num_integer::Integer;
use num_traits::{One, ToPrimitive, Zero}; use num_traits::{One, ToPrimitive, Zero};
use quote::TokenStreamExt;
use std::str::FromStr; use std::str::FromStr;
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))] #[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))]
pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// Construct a string representation of the type definition // Parse the type definition
let s = input.to_string(); let ast: syn::DeriveInput = syn::parse(input).unwrap();
// Parse the string representation
let ast = syn::parse_derive_input(&s).unwrap();
// The struct we're deriving for is a wrapper around a "Repr" type we must construct. // The struct we're deriving for is a wrapper around a "Repr" type we must construct.
let repr_ident = fetch_wrapped_ident(&ast.body) let repr_ident = fetch_wrapped_ident(&ast.data)
.expect("PrimeField derive only operates over tuple structs of a single item"); .expect("PrimeField derive only operates over tuple structs of a single item");
// We're given the modulus p of the prime field // We're given the modulus p of the prime field
@ -51,38 +50,40 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
} }
} }
let mut gen = quote::Tokens::new(); let mut gen = proc_macro2::TokenStream::new();
gen.append(prime_field_repr_impl(&repr_ident, limbs)); gen.extend(prime_field_repr_impl(&repr_ident, limbs));
gen.append(prime_field_constants_and_sqrt( gen.extend(prime_field_constants_and_sqrt(
&ast.ident, &ast.ident,
&repr_ident, &repr_ident,
modulus, modulus,
limbs, limbs,
generator, generator,
)); ));
gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs)); gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs));
// Return the generated impl // Return the generated impl
gen.parse().unwrap() gen.into()
} }
/// Fetches the ident being wrapped by the type we're deriving. /// Fetches the ident being wrapped by the type we're deriving.
fn fetch_wrapped_ident(body: &syn::Body) -> Option<syn::Ident> { fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> {
match body { match body {
&syn::Body::Struct(ref variant_data) => { &syn::Data::Struct(ref variant_data) => match variant_data.fields {
let fields = variant_data.fields(); syn::Fields::Unnamed(ref fields) => {
if fields.len() == 1 { if fields.unnamed.len() == 1 {
match fields[0].ty { match fields.unnamed[0].ty {
syn::Ty::Path(_, ref path) => { syn::Type::Path(ref path) => {
if path.segments.len() == 1 { if path.path.segments.len() == 1 {
return Some(path.segments[0].ident.clone()); return Some(path.path.segments[0].ident.clone());
}
} }
_ => {}
} }
_ => {}
} }
} }
} _ => {}
},
_ => {} _ => {}
}; };
@ -92,14 +93,18 @@ fn fetch_wrapped_ident(body: &syn::Body) -> Option<syn::Ident> {
/// Fetch an attribute string from the derived struct. /// Fetch an attribute string from the derived struct.
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> { fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
for attr in attrs { for attr in attrs {
if attr.name() == name { if let Some(meta) = attr.interpret_meta() {
match attr.value { match meta {
syn::MetaItem::NameValue(_, ref val) => match val { syn::Meta::NameValue(nv) => {
&syn::Lit::Str(ref s, _) => return Some(s.clone()), if nv.ident.to_string() == name {
_ => { match nv.lit {
panic!("attribute {} should be a string", name); syn::Lit::Str(ref s) => return Some(s.value()),
_ => {
panic!("attribute {} should be a string", name);
}
}
} }
}, }
_ => { _ => {
panic!("attribute {} should be a string", name); panic!("attribute {} should be a string", name);
} }
@ -111,7 +116,7 @@ fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
} }
// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs. // Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens { fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
quote! { quote! {
#[derive(Copy, Clone, PartialEq, Eq, Default)] #[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct #repr(pub [u64; #limbs]); pub struct #repr(pub [u64; #limbs]);
@ -253,7 +258,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens {
} }
/// Convert BigUint into a vector of 64-bit limbs. /// Convert BigUint into a vector of 64-bit limbs.
fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> { fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> {
let m = BigUint::one() << 64; let m = BigUint::one() << 64;
let mut ret = vec![]; let mut ret = vec![];
@ -271,6 +276,12 @@ fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> {
ret ret
} }
/// Convert BigUint into a tokenized vector of 64-bit limbs.
fn biguint_to_u64_vec(v: BigUint, limbs: usize) -> proc_macro2::TokenStream {
let ret = biguint_to_real_u64_vec(v, limbs);
quote!([#(#ret,)*])
}
fn biguint_num_bits(mut v: BigUint) -> u32 { fn biguint_num_bits(mut v: BigUint) -> u32 {
let mut bits = 0; let mut bits = 0;
@ -321,7 +332,7 @@ fn prime_field_constants_and_sqrt(
modulus: BigUint, modulus: BigUint,
limbs: usize, limbs: usize,
generator: BigUint, generator: BigUint,
) -> quote::Tokens { ) -> proc_macro2::TokenStream {
let modulus_num_bits = biguint_num_bits(modulus.clone()); let modulus_num_bits = biguint_num_bits(modulus.clone());
// The number of bits we should "shave" from a randomly sampled reputation, i.e., // The number of bits we should "shave" from a randomly sampled reputation, i.e.,
@ -437,7 +448,7 @@ fn prime_field_constants_and_sqrt(
let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs); let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs);
let r = biguint_to_u64_vec(r, limbs); let r = biguint_to_u64_vec(r, limbs);
let modulus = biguint_to_u64_vec(modulus, limbs); let modulus = biguint_to_real_u64_vec(modulus, limbs);
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1 // Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
let mut inv = 1u64; let mut inv = 1u64;
@ -449,7 +460,7 @@ fn prime_field_constants_and_sqrt(
quote! { quote! {
/// This is the modulus m of the prime field /// This is the modulus m of the prime field
const MODULUS: #repr = #repr(#modulus); const MODULUS: #repr = #repr([#(#modulus,)*]);
/// The number of bits needed to represent the modulus. /// The number of bits needed to represent the modulus.
const MODULUS_BITS: u32 = #modulus_num_bits; const MODULUS_BITS: u32 = #modulus_num_bits;
@ -482,15 +493,19 @@ fn prime_field_constants_and_sqrt(
} }
/// Implement PrimeField for the derived type. /// Implement PrimeField for the derived type.
fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote::Tokens { fn prime_field_impl(
name: &syn::Ident,
repr: &syn::Ident,
limbs: usize,
) -> proc_macro2::TokenStream {
// Returns r{n} as an ident. // Returns r{n} as an ident.
fn get_temp(n: usize) -> syn::Ident { fn get_temp(n: usize) -> syn::Ident {
syn::Ident::from(format!("r{}", n)) syn::Ident::new(&format!("r{}", n), proc_macro2::Span::call_site())
} }
// The parameter list for the mont_reduce() internal method. // The parameter list for the mont_reduce() internal method.
// r0: u64, mut r1: u64, mut r2: u64, ... // r0: u64, mut r1: u64, mut r2: u64, ...
let mut mont_paramlist = quote::Tokens::new(); let mut mont_paramlist = proc_macro2::TokenStream::new();
mont_paramlist.append_separated( mont_paramlist.append_separated(
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { (0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| {
if i != 0 { if i != 0 {
@ -499,17 +514,17 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
quote!{#x: u64} quote!{#x: u64}
} }
}), }),
",", proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
); );
// Implement montgomery reduction for some number of limbs // Implement montgomery reduction for some number of limbs
fn mont_impl(limbs: usize) -> quote::Tokens { fn mont_impl(limbs: usize) -> proc_macro2::TokenStream {
let mut gen = quote::Tokens::new(); let mut gen = proc_macro2::TokenStream::new();
for i in 0..limbs { for i in 0..limbs {
{ {
let temp = get_temp(i); let temp = get_temp(i);
gen.append(quote!{ gen.extend(quote!{
let k = #temp.wrapping_mul(INV); let k = #temp.wrapping_mul(INV);
let mut carry = 0; let mut carry = 0;
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); ::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry);
@ -518,7 +533,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
for j in 1..limbs { for j in 1..limbs {
let temp = get_temp(i + j); let temp = get_temp(i + j);
gen.append(quote!{ gen.extend(quote!{
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); #temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry);
}); });
} }
@ -526,17 +541,17 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let temp = get_temp(i + limbs); let temp = get_temp(i + limbs);
if i == 0 { if i == 0 {
gen.append(quote!{ gen.extend(quote!{
#temp = ::ff::adc(#temp, 0, &mut carry); #temp = ::ff::adc(#temp, 0, &mut carry);
}); });
} else { } else {
gen.append(quote!{ gen.extend(quote!{
#temp = ::ff::adc(#temp, carry2, &mut carry); #temp = ::ff::adc(#temp, carry2, &mut carry);
}); });
} }
if i != (limbs - 1) { if i != (limbs - 1) {
gen.append(quote!{ gen.extend(quote!{
let carry2 = carry; let carry2 = carry;
}); });
} }
@ -545,7 +560,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
for i in 0..limbs { for i in 0..limbs {
let temp = get_temp(limbs + i); let temp = get_temp(limbs + i);
gen.append(quote!{ gen.extend(quote!{
(self.0).0[#i] = #temp; (self.0).0[#i] = #temp;
}); });
} }
@ -553,22 +568,22 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
gen gen
} }
fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens { fn sqr_impl(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream {
let mut gen = quote::Tokens::new(); let mut gen = proc_macro2::TokenStream::new();
for i in 0..(limbs - 1) { for i in 0..(limbs - 1) {
gen.append(quote!{ gen.extend(quote!{
let mut carry = 0; let mut carry = 0;
}); });
for j in (i + 1)..limbs { for j in (i + 1)..limbs {
let temp = get_temp(i + j); let temp = get_temp(i + j);
if i == 0 { if i == 0 {
gen.append(quote!{ gen.extend(quote!{
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
}); });
} else { } else {
gen.append(quote!{ gen.extend(quote!{
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry); let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
}); });
} }
@ -576,7 +591,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let temp = get_temp(i + limbs); let temp = get_temp(i + limbs);
gen.append(quote!{ gen.extend(quote!{
let #temp = carry; let #temp = carry;
}); });
} }
@ -585,16 +600,16 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let k = get_temp(i); let k = get_temp(i);
if i == 1 { if i == 1 {
gen.append(quote!{ gen.extend(quote!{
let tmp0 = #k >> 63; let tmp0 = #k >> 63;
let #k = #k << 1; let #k = #k << 1;
}); });
} else if i == (limbs * 2 - 1) { } else if i == (limbs * 2 - 1) {
gen.append(quote!{ gen.extend(quote!{
let #k = tmp0; let #k = tmp0;
}); });
} else { } else {
gen.append(quote!{ gen.extend(quote!{
let tmp1 = #k >> 63; let tmp1 = #k >> 63;
let #k = #k << 1; let #k = #k << 1;
let #k = #k | tmp0; let #k = #k | tmp0;
@ -603,7 +618,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
} }
} }
gen.append(quote!{ gen.extend(quote!{
let mut carry = 0; let mut carry = 0;
}); });
@ -611,35 +626,42 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let temp0 = get_temp(i * 2); let temp0 = get_temp(i * 2);
let temp1 = get_temp(i * 2 + 1); let temp1 = get_temp(i * 2 + 1);
if i == 0 { if i == 0 {
gen.append(quote!{ gen.extend(quote!{
let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
}); });
} else { } else {
gen.append(quote!{ gen.extend(quote!{
let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
}); });
} }
gen.append(quote!{ gen.extend(quote!{
let #temp1 = ::ff::adc(#temp1, 0, &mut carry); let #temp1 = ::ff::adc(#temp1, 0, &mut carry);
}); });
} }
let mut mont_calling = quote::Tokens::new(); let mut mont_calling = proc_macro2::TokenStream::new();
mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); mont_calling.append_separated(
(0..(limbs * 2)).map(|i| get_temp(i)),
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
);
gen.append(quote!{ gen.extend(quote!{
self.mont_reduce(#mont_calling); self.mont_reduce(#mont_calling);
}); });
gen gen
} }
fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens { fn mul_impl(
let mut gen = quote::Tokens::new(); a: proc_macro2::TokenStream,
b: proc_macro2::TokenStream,
limbs: usize,
) -> proc_macro2::TokenStream {
let mut gen = proc_macro2::TokenStream::new();
for i in 0..limbs { for i in 0..limbs {
gen.append(quote!{ gen.extend(quote!{
let mut carry = 0; let mut carry = 0;
}); });
@ -647,11 +669,11 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let temp = get_temp(i + j); let temp = get_temp(i + j);
if i == 0 { if i == 0 {
gen.append(quote!{ gen.extend(quote!{
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
}); });
} else { } else {
gen.append(quote!{ gen.extend(quote!{
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry); let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
}); });
} }
@ -659,15 +681,18 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let temp = get_temp(i + limbs); let temp = get_temp(i + limbs);
gen.append(quote!{ gen.extend(quote!{
let #temp = carry; let #temp = carry;
}); });
} }
let mut mont_calling = quote::Tokens::new(); let mut mont_calling = proc_macro2::TokenStream::new();
mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); mont_calling.append_separated(
(0..(limbs * 2)).map(|i| get_temp(i)),
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
);
gen.append(quote!{ gen.extend(quote!{
self.mont_reduce(#mont_calling); self.mont_reduce(#mont_calling);
}); });
@ -679,12 +704,12 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote
let montgomery_impl = mont_impl(limbs); let montgomery_impl = mont_impl(limbs);
// (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ... // (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ...
let mut into_repr_params = quote::Tokens::new(); let mut into_repr_params = proc_macro2::TokenStream::new();
into_repr_params.append_separated( into_repr_params.append_separated(
(0..limbs) (0..limbs)
.map(|i| quote!{ (self.0).0[#i] }) .map(|i| quote!{ (self.0).0[#i] })
.chain((0..limbs).map(|_| quote!{0})), .chain((0..limbs).map(|_| quote!{0})),
",", proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
); );
quote!{ quote!{

Loading…
Cancel
Save