add Iterator<Item = Pair<T, P>> helpers

This commit is contained in:
Jacob Lifshay 2024-07-25 22:07:23 -07:00
parent c94a437686
commit 7963f0a5cd
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
3 changed files with 140 additions and 45 deletions

View file

@ -7,7 +7,9 @@ use std::io::{ErrorKind, Write};
use syn::{ use syn::{
bracketed, parenthesized, bracketed, parenthesized,
parse::{Parse, ParseStream, Parser}, parse::{Parse, ParseStream, Parser},
parse_quote, AttrStyle, Attribute, Error, Item, Token, parse_quote,
punctuated::Pair,
AttrStyle, Attribute, Error, Item, Token,
}; };
mod fold; mod fold;
@ -318,6 +320,108 @@ impl<T: Parse> HdlAttr<T> {
} }
} }
#[allow(dead_code)]
pub(crate) trait PairsIterExt: Sized + Iterator {
fn map_pair<T1, T2, P1, P2, ValueFn: FnMut(T1) -> T2, PunctFn: FnMut(P1) -> P2>(
self,
mut value_fn: ValueFn,
mut punct_fn: PunctFn,
) -> impl Iterator<Item = Pair<T2, P2>>
where
Self: Iterator<Item = Pair<T1, P1>>,
{
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<T1, T2, P1, P2, ValueFn: FnMut(T1) -> Option<T2>, PunctFn: FnMut(P1) -> P2>(
self,
mut value_fn: ValueFn,
mut punct_fn: PunctFn,
) -> impl Iterator<Item = Pair<T2, P2>>
where
Self: Iterator<Item = Pair<T1, P1>>,
{
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<T1, T2, P, F: FnMut(T1) -> T2>(
self,
f: F,
) -> impl Iterator<Item = Pair<T2, P>>
where
Self: Iterator<Item = Pair<T1, P>>,
{
self.map_pair(f, |v| v)
}
fn filter_map_pair_value<T1, T2, P, F: FnMut(T1) -> Option<T2>>(
self,
f: F,
) -> impl Iterator<Item = Pair<T2, P>>
where
Self: Iterator<Item = Pair<T1, P>>,
{
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<Item = Pair<T2, P>> + 'a
where
Self: Iterator<Item = Pair<T1, &'a mut P>> + '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<T2> + 'a,
>(
self,
f: F,
) -> impl Iterator<Item = Pair<T2, P>> + 'a
where
Self: Iterator<Item = Pair<T1, &'a mut P>> + '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<Item = Pair<T2, P>> + 'a
where
Self: Iterator<Item = Pair<T1, &'a P>> + '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<T2> + 'a,
>(
self,
f: F,
) -> impl Iterator<Item = Pair<T2, P>> + 'a
where
Self: Iterator<Item = Pair<T1, &'a P>> + 'a,
{
self.filter_map_pair(f, |v| v.clone())
}
}
impl<T, P, Iter: Iterator<Item = Pair<T, P>>> PairsIterExt for Iter {}
pub(crate) struct Errors { pub(crate) struct Errors {
error: Option<Error>, error: Option<Error>,
finished: bool, finished: bool,

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information // 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 proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt}; use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt};
use syn::{ use syn::{
@ -207,7 +207,7 @@ impl StructOrEnumLiteral {
} }
pub(crate) fn map_fields( pub(crate) fn map_fields(
self, self,
mut f: impl FnMut(StructOrEnumLiteralField) -> StructOrEnumLiteralField, f: impl FnMut(StructOrEnumLiteralField) -> StructOrEnumLiteralField,
) -> Self { ) -> Self {
let Self { let Self {
attrs, attrs,
@ -217,10 +217,7 @@ impl StructOrEnumLiteral {
dot2_token, dot2_token,
rest, rest,
} = self; } = self;
let fields = Punctuated::from_iter(fields.into_pairs().map(|p| { let fields = fields.into_pairs().map_pair_value(f).collect();
let (field, comma) = p.into_tuple();
Pair::new(f(field), comma)
}));
Self { Self {
attrs, attrs,
path, path,
@ -247,26 +244,22 @@ impl From<ExprStruct> for StructOrEnumLiteral {
attrs, attrs,
path: TypePath { qself, path }, path: TypePath { qself, path },
brace_or_paren: BraceOrParen::Brace(brace_token), brace_or_paren: BraceOrParen::Brace(brace_token),
fields: Punctuated::from_iter(fields.into_pairs().map(|v| { fields: fields
let ( .into_pairs()
FieldValue { .map_pair_value(
|FieldValue {
attrs,
member,
colon_token,
expr,
}| StructOrEnumLiteralField {
attrs, attrs,
member, member,
colon_token, colon_token,
expr, expr,
}, },
comma,
) = v.into_tuple();
Pair::new(
StructOrEnumLiteralField {
attrs,
member,
colon_token,
expr,
},
comma,
) )
})), .collect(),
dot2_token, dot2_token,
rest, rest,
} }
@ -514,20 +507,24 @@ impl Visitor {
} }
}; };
}; };
let fields = Punctuated::from_iter(args.into_pairs().enumerate().map(|(index, p)| { let fields = args
let (expr, comma) = p.into_tuple(); .into_pairs()
let mut index = Index::from(index); .enumerate()
index.span = hdl_attr.hdl.span; .map(|(index, p)| {
Pair::new( let (expr, comma) = p.into_tuple();
StructOrEnumLiteralField { let mut index = Index::from(index);
attrs: vec![], index.span = hdl_attr.hdl.span;
member: Member::Unnamed(index), Pair::new(
colon_token: None, StructOrEnumLiteralField {
expr, attrs: vec![],
}, member: Member::Unnamed(index),
comma, colon_token: None,
) expr,
})); },
comma,
)
})
.collect();
self.process_struct_enum( self.process_struct_enum(
hdl_attr, hdl_attr,
StructOrEnumLiteral { StructOrEnumLiteral {

View file

@ -6,7 +6,7 @@ use crate::{
expand_aggregate_literals::{AggregateLiteralOptions, StructOrEnumPath}, expand_aggregate_literals::{AggregateLiteralOptions, StructOrEnumPath},
with_debug_clone_and_fold, Visitor, with_debug_clone_and_fold, Visitor,
}, },
Errors, HdlAttr, Errors, HdlAttr, PairsIterExt,
}; };
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, TokenStreamExt}; use quote::{ToTokens, TokenStreamExt};
@ -238,11 +238,7 @@ trait ParseMatchPat: Sized {
leading_vert, leading_vert,
cases: cases cases: cases
.into_pairs() .into_pairs()
.filter_map(|pair| { .filter_map_pair_value(|pat| Self::parse(state, pat).ok())
let (pat, punct) = pair.into_tuple();
let pat = Self::parse(state, pat).ok()?;
Some(Pair::new(pat, punct))
})
.collect(), .collect(),
})), })),
Pat::Paren(PatParen { Pat::Paren(PatParen {
@ -282,10 +278,8 @@ trait ParseMatchPat: Sized {
}) => { }) => {
let fields = fields let fields = fields
.into_pairs() .into_pairs()
.filter_map(|pair| { .filter_map_pair_value(|field_pat| {
let (field_pat, punct) = pair.into_tuple(); MatchPatStructField::parse(state, field_pat).ok()
let field_pat = MatchPatStructField::parse(state, field_pat).ok()?;
Some(Pair::new(field_pat, punct))
}) })
.collect(); .collect();
let path = TypePath { qself, path }; let path = TypePath { qself, path };