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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Backwards-incompatible changes
- `typle_bounds!` has been replaced by support for `typle!` macro in where clauses.
- `typle_args` as a synonym for `typle!` has been removed.

# 0.11

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ proc-macro = true
either = "1"
proc-macro2 = "1"
quote = "1"
syn = { version = "2.0.43", features = ["full", "extra-traits"] }
syn = { version = "2.0.43", features = ["full", "parsing"] }
zip_clone = "0.1.0"

[dev-dependencies]
Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ For example, to define a function to zip a pair of tuples into a tuple of pairs:
pub fn zip<A: Tuple, B: Tuple>(
a: A,
b: B,
) -> (typle![i in .. => (A<{i}>, B<{i}>)])
) -> (typle! {
i in .. => (A<{i}>, B<{i}>)
})
{
(typle!{i in .. => (a[[i]], b[[i]])})
(typle! {
i in .. => (a[[i]], b[[i]])
})
}
```

Expand Down Expand Up @@ -61,15 +65,17 @@ where
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));
type Output = (typle! {i in .. => T<{i}>::Output});

// Return a tuple of output from each handler applied to the same input.
fn handle_stuff(&self, input: Input) -> Self::Output {
if typle_const!(T::LEN == 0) {
()
} else {
(
typle!(i in ..T::LAST => self.handlers[[i]].handle_stuff(input.clone())),
typle! {
i in ..T::LAST => self.handlers[[i]].handle_stuff(input.clone())
},
// Avoid expensive clone for the last handler.
self.handlers[[T::LAST]].handle_stuff(input),
)
Expand All @@ -90,7 +96,7 @@ impl<T0> HandleStuff for MultipleHandlers<(T0,)>
where
T0: HandleStuff,
{
type Output = (<T0>::Output,);
type Output = (T0::Output,);
fn handle_stuff(&self, input: Input) -> Self::Output {
{ (self.handlers.0.handle_stuff(input),) }
}
Expand All @@ -100,7 +106,7 @@ where
T0: HandleStuff,
T1: HandleStuff,
{
type Output = (<T0>::Output, <T1>::Output);
type Output = (T0::Output, T1::Output);
fn handle_stuff(&self, input: Input) -> Self::Output {
{
(
Expand All @@ -116,7 +122,7 @@ where
T1: HandleStuff,
T2: HandleStuff,
{
type Output = (<T0>::Output, <T1>::Output, <T2>::Output);
type Output = (T0::Output, T1::Output, T2::Output);
fn handle_stuff(&self, input: Input) -> Self::Output {
{
(
Expand Down
24 changes: 16 additions & 8 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,14 +594,22 @@ impl TypleContext {
}
let mut bounded_ty = syn::parse2::<Type>(bounded.into_iter().collect())?;
context.replace_type(&mut bounded_ty)?;
let mut bound = syn::parse2::<TypeParamBound>(bound.into_iter().collect())?;
context.replace_bound(&mut bound)?;
Ok(WherePredicate::Type(syn::PredicateType {
lifetimes: None,
bounded_ty,
colon_token: token::Colon::default(),
bounds: std::iter::once(bound).collect(),
}))
let bounds = Punctuated::<TypeParamBound, token::Plus>::parse_terminated
.parse2(bound.into_iter().collect())?
.into_iter()
.map(|mut bound| {
context.replace_bound(&mut bound)?;
Ok(bound)
})
.collect::<syn::Result<_>>()?;
Ok(Replacements::<std::iter::Empty<_>>::Singleton(Ok(
WherePredicate::Type(syn::PredicateType {
lifetimes: None,
bounded_ty,
colon_token: token::Colon::default(),
bounds,
}),
)))
})
}

Expand Down
27 changes: 16 additions & 11 deletions src/context/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,11 @@ impl TypleContext {
// t[[0]]
let mut iter = array.elems.iter_mut().fuse();
let (Some(field), None) = (iter.next(), iter.next()) else {
abort!(index.index, "unsupported tuple index1");
abort!(index.index, "unsupported tuple index");
};
self.replace_expr(field, state)?;
let deb = field.clone();
let Some(i) = evaluate_usize(field) else {
abort!(
index.index,
format!("unsupported tuple index {:?} {:?}", self.constants, deb)
);
abort!(index.index, format!("unsupported tuple index"));
};
*expr = Expr::Field(syn::ExprField {
attrs: std::mem::take(&mut index.attrs),
Expand Down Expand Up @@ -575,14 +571,23 @@ impl TypleContext {
match &mut expr {
Expr::Macro(syn::ExprMacro { mac, .. }) => {
if let Some(ident) = mac.path.get_ident() {
if ident == "typle" || ident == "typle_args" {
if ident == "typle" {
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)
Ok(Replacements::Iterator(
Punctuated::<syn::Expr, token::Comma>::parse_terminated
.parse2(token_stream)?
.into_iter()
.map(|mut expr| {
let mut state = BlockState::default();
context.replace_expr(&mut expr, &mut state)?;
Ok(expr)
})
// collect and into_iter due to context lifetime
.collect::<Vec<_>>()
.into_iter(),
))
})
.map_iterator(Either::Left);
}
Expand Down
4 changes: 2 additions & 2 deletions src/context/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ impl TypleContext {
match &mut pat {
Pat::Macro(syn::PatMacro { mac, .. }) => {
if let Some(ident) = mac.path.get_ident() {
if ident == "typle" || ident == "typle_args" {
if ident == "typle" {
let token_stream = std::mem::take(&mut mac.tokens);
return self.expand_typle_macro(token_stream, |context, token_stream| {
let mut pat = Pat::parse_single.parse2(token_stream)?;
let mut state = BlockState::default();
context.replace_pat(&mut pat, &mut state)?;
Ok(pat)
Ok(Replacements::<std::iter::Empty<_>>::Singleton(Ok(pat)))
});
}
}
Expand Down
18 changes: 11 additions & 7 deletions src/context/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,14 +448,15 @@ impl TypleContext {
Ok(None)
}

pub(super) fn expand_typle_macro<T, F>(
pub(super) fn expand_typle_macro<T, F, I>(
&self,
token_stream: TokenStream,
f: F,
) -> Replacements<impl Iterator<Item = syn::Result<T>>>
where
T: 'static,
F: Fn(&TypleContext, TokenStream) -> syn::Result<T> + 'static,
F: Fn(&TypleContext, TokenStream) -> syn::Result<Replacements<I>>,
I: Iterator<Item = syn::Result<T>>,
{
let mut tokens = token_stream.into_iter();
let (pattern, range) = match self.parse_pattern_range(&mut tokens) {
Expand All @@ -472,17 +473,20 @@ impl TypleContext {
if let Some(ident) = pattern.clone() {
context.constants.insert(ident, 0);
}
return Replacements::Iterator(range.zip_clone(token_stream).flat_map(
Replacements::Iterator(range.zip_clone(token_stream).flat_map(
move |(index, token_stream)| {
if let Some(ident) = &pattern {
*context.constants.get_mut(ident).unwrap() = index;
}
match context.evaluate_if(token_stream) {
Ok(Some(token_stream)) => Some(f(&context, token_stream)),
Ok(None) => None,
Err(e) => Some(Err(e)),
Ok(Some(token_stream)) => match f(&context, token_stream) {
Ok(iter) => iter,
Err(err) => Replacements::Singleton(Err(err)),
},
Ok(None) => Replacements::Empty,
Err(err) => Replacements::Singleton(Err(err)),
}
},
));
))
}
}
17 changes: 13 additions & 4 deletions src/context/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,22 @@ impl TypleContext {
match &mut ty {
Type::Macro(syn::TypeMacro { mac }) => {
if let Some(ident) = mac.path.get_ident() {
if ident == "typle" || ident == "typle_args" {
if ident == "typle" {
let token_stream = std::mem::take(&mut mac.tokens);
return self
.expand_typle_macro(token_stream, |context, token_stream| {
let mut ty = syn::parse2::<Type>(token_stream)?;
context.replace_type(&mut ty)?;
Ok(ty)
Ok(Replacements::Iterator(
Punctuated::<syn::Type, token::Comma>::parse_terminated
.parse2(token_stream)?
.into_iter()
.map(|mut ty| {
context.replace_type(&mut ty)?;
Ok(ty)
})
// collect and into_iter due to context lifetime
.collect::<Vec<_>>()
.into_iter(),
))
})
.map_iterator(Either::Left);
}
Expand Down
Loading