Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rust-version = "1.68.2"
proc-macro = true

[dependencies]
either = "1"
proc-macro2 = "1"
quote = "1"
syn = { version = "2.0.43", features = ["full", "extra-traits"] }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct MultipleHandlers<T> {
#[typle(Tuple for 0..=3)]
impl<T> HandleStuff for MultipleHandlers<T>
where
T: Tuple, // `T`` is a tuple with 0 to 12 components.
T: Tuple, // `T`` is a tuple with 0 to 3 components.
T<_>: HandleStuff, // All components implement `HandleStuff`.
{
type Output = (typle!(i in .. => T<{i}>::Output));
Expand Down
14 changes: 9 additions & 5 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use syn::{
use zip_clone::ZipClone as _;

use crate::constant::{evaluate_bool, evaluate_range, evaluate_usize};
use crate::context::shared::{abort, Replacement};
use crate::context::shared::{abort, Replacements};
use crate::syn_ext::GeneralFunction;
use crate::TypleMacro;

Expand Down Expand Up @@ -184,7 +184,7 @@ impl TypleContext {
let path = &trait_bound.path;
if path.leading_colon.is_none() && path.segments.len() == 1 {
if let Some(segment) = path.segments.first() {
if segment.ident == self.typle_macro.ident {
if segment.ident == self.typle_macro.trait_ident {
match &segment.arguments {
PathArguments::None => {
if result.is_some() {
Expand Down Expand Up @@ -491,7 +491,8 @@ impl TypleContext {
None,
) = (segments.get(0), segments.get(1), segments.get(2))
{
if *ident1 == self.typle_macro.ident && ident2 == "Bounds"
if *ident1 == self.typle_macro.trait_ident
&& ident2 == "Bounds"
{
let token_stream = std::mem::take(&mut mac.tokens);
let predicates =
Expand Down Expand Up @@ -554,7 +555,10 @@ impl TypleContext {
Ok(())
}

fn expand_predicates(&self, token_stream: TokenStream) -> Replacement<WherePredicate> {
fn expand_predicates(
&self,
token_stream: TokenStream,
) -> Replacements<impl Iterator<Item = syn::Result<WherePredicate>>> {
self.expand_typle_macro(token_stream, |context, token_stream| {
// Divide the token_stream at the first single :
let mut bounded = Vec::new();
Expand Down Expand Up @@ -808,7 +812,7 @@ impl TypleContext {
}),
ReturnType::Type(_, t) => *t,
};
let typle_trait_name = &self.typle_macro.ident;
let typle_trait_name = &self.typle_macro.trait_ident;

// A method body is moved to a trait implementation on a dfferent type.
// Any instances of `Self` in the method body are converted to the
Expand Down
71 changes: 38 additions & 33 deletions src/context/expr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::context::shared::Replacement;
use either::Either;

use crate::context::shared::Replacements;

use super::*;

Expand Down Expand Up @@ -466,7 +468,7 @@ impl TypleContext {
&mut paren.expr,
Expr::Verbatim(TokenStream::new()),
)) {
Replacement::Singleton(inner) => {
Replacements::Singleton(Ok(inner)) => {
paren.expr = Box::new(inner);
}
iter => {
Expand Down Expand Up @@ -565,19 +567,24 @@ impl TypleContext {
Ok(())
}

pub(super) fn replace_expr_in_list(&self, mut expr: Expr) -> Replacement<Expr> {
pub(super) fn replace_expr_in_list(
&self,
mut expr: Expr,
) -> Replacements<impl Iterator<Item = syn::Result<Expr>>> {
let mut state = BlockState::default();
match &mut expr {
Expr::Macro(syn::ExprMacro { mac, .. }) => {
if let Some(ident) = mac.path.get_ident() {
if ident == "typle" || ident == "typle_args" {
let token_stream = std::mem::take(&mut mac.tokens);
return self.expand_typle_macro(token_stream, |context, token_stream| {
let mut expr = syn::parse2::<Expr>(token_stream)?;
let mut state = BlockState::default();
context.replace_expr(&mut expr, &mut state)?;
Ok(expr)
});
return self
.expand_typle_macro(token_stream, |context, token_stream| {
let mut expr = syn::parse2::<Expr>(token_stream)?;
let mut state = BlockState::default();
context.replace_expr(&mut expr, &mut state)?;
Ok(expr)
})
.map_iterator(Either::Left);
}
}
}
Expand All @@ -587,64 +594,62 @@ impl TypleContext {
let mut iter = array.elems.iter_mut().fuse();
if let (Some(field), None) = (iter.next(), iter.next()) {
if let Err(e) = self.replace_expr(field, &mut state) {
return Replacement::Error(e);
return Replacements::Singleton(Err(e));
}
if let Some((start, end)) = evaluate_range(field) {
let start = match start {
Bound::Included(Err(span)) | Bound::Excluded(Err(span)) => {
return Replacement::Error(syn::Error::new(
return Replacements::Singleton(Err(syn::Error::new(
span,
"expected integer for start of range",
));
)));
}
Bound::Included(Ok(start)) => start,
Bound::Excluded(Ok(start)) => start.saturating_add(1),
Bound::Unbounded => 0,
};
let end = match end {
Bound::Included(Err(span)) | Bound::Excluded(Err(span)) => {
return Replacement::Error(syn::Error::new(
return Replacements::Singleton(Err(syn::Error::new(
span,
"expected integer for end of range",
));
)));
}
Bound::Included(Ok(end)) => end.saturating_add(1),
Bound::Excluded(Ok(end)) => end,
Bound::Unbounded => match self.typle_len {
Some(end) => end,
None => {
return Replacement::Error(syn::Error::new(
return Replacements::Singleton(Err(syn::Error::new(
expr.span(),
"need an explicit range end",
));
)));
}
},
};
return Replacement::Iterator({
return Replacements::Iterator(Either::Right({
let span = index.span();
Box::new((start..end).zip_clone(expr.clone()).map(
move |(i, base)| {
Ok(Expr::Field(syn::ExprField {
attrs: Vec::new(),
base,
dot_token: token::Dot::default(),
member: Member::Unnamed(syn::Index {
index: i as u32,
span,
}),
}))
},
))
});
(start..end).zip_clone(expr.clone()).map(move |(i, base)| {
Ok(Expr::Field(syn::ExprField {
attrs: Vec::new(),
base,
dot_token: token::Dot::default(),
member: Member::Unnamed(syn::Index {
index: i as u32,
span,
}),
}))
})
}));
}
}
}
}
_ => {}
}
match self.replace_expr(&mut expr, &mut state) {
Ok(()) => Replacement::Singleton(expr),
Err(e) => Replacement::Error(e),
Ok(()) => Replacements::Singleton(Ok(expr)),
Err(e) => Replacements::Singleton(Err(e)),
}
}

Expand Down
13 changes: 8 additions & 5 deletions src/context/pat.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::context::shared::Replacement;
use crate::context::shared::Replacements;

use super::*;

Expand All @@ -21,7 +21,7 @@ impl TypleContext {
&mut paren.pat,
Pat::Verbatim(TokenStream::new()),
)) {
Replacement::Singleton(inner) => {
Replacements::Singleton(Ok(inner)) => {
paren.pat = Box::new(inner);
}
iter => {
Expand Down Expand Up @@ -111,7 +111,10 @@ impl TypleContext {
Ok(())
}

pub(super) fn replace_pat_in_list(&self, mut pat: Pat) -> Replacement<Pat> {
pub(super) fn replace_pat_in_list(
&self,
mut pat: Pat,
) -> Replacements<impl Iterator<Item = syn::Result<Pat>>> {
let mut state = BlockState::default();
match &mut pat {
Pat::Macro(syn::PatMacro { mac, .. }) => {
Expand All @@ -130,8 +133,8 @@ impl TypleContext {
_ => {}
}
match self.replace_pat(&mut pat, &mut state) {
Ok(()) => Replacement::Singleton(pat),
Err(e) => Replacement::Error(e),
Ok(()) => Replacements::Singleton(Ok(pat)),
Err(e) => Replacements::Singleton(Err(e)),
}
}

Expand Down
Loading