diff --git a/crates/fayalite-proc-macros-impl/src/lib.rs b/crates/fayalite-proc-macros-impl/src/lib.rs index 7aafe66..3a4a326 100644 --- a/crates/fayalite-proc-macros-impl/src/lib.rs +++ b/crates/fayalite-proc-macros-impl/src/lib.rs @@ -7,7 +7,9 @@ use std::io::{ErrorKind, Write}; use syn::{ bracketed, parenthesized, parse::{Parse, ParseStream, Parser}, - parse_quote, AttrStyle, Attribute, Error, Item, Token, + parse_quote, + punctuated::Pair, + AttrStyle, Attribute, Error, Item, Token, }; mod fold; @@ -318,6 +320,108 @@ impl HdlAttr { } } +#[allow(dead_code)] +pub(crate) trait PairsIterExt: Sized + Iterator { + fn map_pair T2, PunctFn: FnMut(P1) -> P2>( + self, + mut value_fn: ValueFn, + mut punct_fn: PunctFn, + ) -> impl Iterator> + where + Self: Iterator>, + { + self.map(move |p| { + let (t, p) = p.into_tuple(); + let t = value_fn(t); + let p = p.map(&mut punct_fn); + Pair::new(t, p) + }) + } + fn filter_map_pair Option, PunctFn: FnMut(P1) -> P2>( + self, + mut value_fn: ValueFn, + mut punct_fn: PunctFn, + ) -> impl Iterator> + where + Self: Iterator>, + { + self.filter_map(move |p| { + let (t, p) = p.into_tuple(); + let t = value_fn(t)?; + let p = p.map(&mut punct_fn); + Some(Pair::new(t, p)) + }) + } + fn map_pair_value T2>( + self, + f: F, + ) -> impl Iterator> + where + Self: Iterator>, + { + self.map_pair(f, |v| v) + } + fn filter_map_pair_value Option>( + self, + f: F, + ) -> impl Iterator> + where + Self: Iterator>, + { + self.filter_map_pair(f, |v| v) + } + fn map_pair_value_mut<'a, T1: 'a, T2: 'a, P: Clone + 'a, F: FnMut(T1) -> T2 + 'a>( + self, + f: F, + ) -> impl Iterator> + 'a + where + Self: Iterator> + 'a, + { + self.map_pair(f, |v| v.clone()) + } + fn filter_map_pair_value_mut< + 'a, + T1: 'a, + T2: 'a, + P: Clone + 'a, + F: FnMut(T1) -> Option + 'a, + >( + self, + f: F, + ) -> impl Iterator> + 'a + where + Self: Iterator> + 'a, + { + self.filter_map_pair(f, |v| v.clone()) + } + fn map_pair_value_ref<'a, T1: 'a, T2: 'a, P: Clone + 'a, F: FnMut(T1) -> T2 + 'a>( + self, + f: F, + ) -> impl Iterator> + 'a + where + Self: Iterator> + 'a, + { + self.map_pair(f, |v| v.clone()) + } + fn filter_map_pair_value_ref< + 'a, + T1: 'a, + T2: 'a, + P: Clone + 'a, + F: FnMut(T1) -> Option + 'a, + >( + self, + f: F, + ) -> impl Iterator> + 'a + where + Self: Iterator> + 'a, + { + self.filter_map_pair(f, |v| v.clone()) + } +} + +impl>> PairsIterExt for Iter {} + pub(crate) struct Errors { error: Option, finished: bool, diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs index ccc7252..bfa4a51 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information -use crate::{module::transform_body::Visitor, options, Errors, HdlAttr}; +use crate::{module::transform_body::Visitor, options, Errors, HdlAttr, PairsIterExt}; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt}; use syn::{ @@ -207,7 +207,7 @@ impl StructOrEnumLiteral { } pub(crate) fn map_fields( self, - mut f: impl FnMut(StructOrEnumLiteralField) -> StructOrEnumLiteralField, + f: impl FnMut(StructOrEnumLiteralField) -> StructOrEnumLiteralField, ) -> Self { let Self { attrs, @@ -217,10 +217,7 @@ impl StructOrEnumLiteral { dot2_token, rest, } = self; - let fields = Punctuated::from_iter(fields.into_pairs().map(|p| { - let (field, comma) = p.into_tuple(); - Pair::new(f(field), comma) - })); + let fields = fields.into_pairs().map_pair_value(f).collect(); Self { attrs, path, @@ -247,26 +244,22 @@ impl From for StructOrEnumLiteral { attrs, path: TypePath { qself, path }, brace_or_paren: BraceOrParen::Brace(brace_token), - fields: Punctuated::from_iter(fields.into_pairs().map(|v| { - let ( - FieldValue { + fields: fields + .into_pairs() + .map_pair_value( + |FieldValue { + attrs, + member, + colon_token, + expr, + }| StructOrEnumLiteralField { attrs, member, colon_token, expr, }, - comma, - ) = v.into_tuple(); - Pair::new( - StructOrEnumLiteralField { - attrs, - member, - colon_token, - expr, - }, - comma, ) - })), + .collect(), dot2_token, rest, } @@ -514,20 +507,24 @@ impl Visitor { } }; }; - let fields = Punctuated::from_iter(args.into_pairs().enumerate().map(|(index, p)| { - let (expr, comma) = p.into_tuple(); - let mut index = Index::from(index); - index.span = hdl_attr.hdl.span; - Pair::new( - StructOrEnumLiteralField { - attrs: vec![], - member: Member::Unnamed(index), - colon_token: None, - expr, - }, - comma, - ) - })); + let fields = args + .into_pairs() + .enumerate() + .map(|(index, p)| { + let (expr, comma) = p.into_tuple(); + let mut index = Index::from(index); + index.span = hdl_attr.hdl.span; + Pair::new( + StructOrEnumLiteralField { + attrs: vec![], + member: Member::Unnamed(index), + colon_token: None, + expr, + }, + comma, + ) + }) + .collect(); self.process_struct_enum( hdl_attr, StructOrEnumLiteral { diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs index 58b0bbb..fe1a895 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs @@ -6,7 +6,7 @@ use crate::{ expand_aggregate_literals::{AggregateLiteralOptions, StructOrEnumPath}, with_debug_clone_and_fold, Visitor, }, - Errors, HdlAttr, + Errors, HdlAttr, PairsIterExt, }; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; @@ -238,11 +238,7 @@ trait ParseMatchPat: Sized { leading_vert, cases: cases .into_pairs() - .filter_map(|pair| { - let (pat, punct) = pair.into_tuple(); - let pat = Self::parse(state, pat).ok()?; - Some(Pair::new(pat, punct)) - }) + .filter_map_pair_value(|pat| Self::parse(state, pat).ok()) .collect(), })), Pat::Paren(PatParen { @@ -282,10 +278,8 @@ trait ParseMatchPat: Sized { }) => { let fields = fields .into_pairs() - .filter_map(|pair| { - let (field_pat, punct) = pair.into_tuple(); - let field_pat = MatchPatStructField::parse(state, field_pat).ok()?; - Some(Pair::new(field_pat, punct)) + .filter_map_pair_value(|field_pat| { + MatchPatStructField::parse(state, field_pat).ok() }) .collect(); let path = TypePath { qself, path };