tamer: f: impl_mono_map! macro
This helps to remove some boilerplate. Testing this out in `asg::graph::object::tpl` before applying it to other things; really `Map` can just go away entirely then since it can be implemented in terms of `TryMap`, but maybe it should stick around for manual impls (implementing `TryMap` manually is more work). DEV-13163main
parent
3c9e1add20
commit
66512bf20d
|
@ -50,26 +50,9 @@ impl Tpl {
|
|||
}
|
||||
}
|
||||
|
||||
impl Map<Span> for Tpl {
|
||||
fn map(self, f: impl FnOnce(Span) -> Span) -> Self::Target {
|
||||
match self {
|
||||
Self(span, shape) => Self(f(span), shape),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryMap<TplShape> for Tpl {
|
||||
fn try_map<E>(
|
||||
self,
|
||||
f: impl FnOnce(TplShape) -> Self::FnResult<E>,
|
||||
) -> Self::Result<E> {
|
||||
match self {
|
||||
Self(span, x) => match f(x) {
|
||||
Ok(shape) => Ok(Self(span, shape)),
|
||||
Err((shape, e)) => Err((Self(span, shape), e)),
|
||||
},
|
||||
}
|
||||
}
|
||||
impl_mono_map! {
|
||||
Span => Tpl(@, shape),
|
||||
TplShape => Tpl(span, @),
|
||||
}
|
||||
|
||||
impl Display for Tpl {
|
||||
|
@ -239,7 +222,7 @@ object_rel! {
|
|||
let span = to_oi.resolve(asg).span();
|
||||
|
||||
from_oi.try_map_obj(asg, |tpl| {
|
||||
tpl.try_map(|shape| {
|
||||
tpl.try_map(|shape: TplShape| {
|
||||
shape.try_adapt_to(TplShape::Expr(span), tpl_name)
|
||||
})
|
||||
})?;
|
||||
|
@ -269,7 +252,7 @@ object_rel! {
|
|||
|
||||
// TODO: Refactor; very similar to Expr edge above.
|
||||
from_oi.try_map_obj(asg, |tpl| {
|
||||
tpl.try_map(|shape| {
|
||||
tpl.try_map(|shape: TplShape| {
|
||||
shape.try_adapt_to(apply_shape, tpl_name)
|
||||
})
|
||||
})?;
|
||||
|
|
|
@ -180,6 +180,80 @@ pub trait TryMap<T, U = T>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
/// Generate monomorphic [`TryMap`] and [`Map`] implementations for the
|
||||
/// provided type.
|
||||
///
|
||||
/// This macro is suitable for otherwise-boilerplate `impl`s for these
|
||||
/// traits.
|
||||
/// If you expect anything more than a generic `map` or `try_map` operation,
|
||||
/// then you should implement the traits manually.
|
||||
///
|
||||
/// Only tuple structs are supported at present.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate tamer;
|
||||
/// # use tamer::impl_mono_map;
|
||||
/// # use tamer::f::Map;
|
||||
/// # fn main() {
|
||||
/// #[derive(Debug, PartialEq)]
|
||||
/// struct Foo(u8, Bar);
|
||||
///
|
||||
/// #[derive(Debug, PartialEq)]
|
||||
/// enum Bar { A, B };
|
||||
///
|
||||
/// impl_mono_map! {
|
||||
/// u8 => Foo(@, bar),
|
||||
/// Bar => Foo(n, @),
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(Foo(5, Bar::A).overwrite(Bar::B), Foo(5, Bar::B));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Each line above generates a pair of `impl`s,
|
||||
/// each for `Foo`,
|
||||
/// where `@` represents the tuple item being mapped over.
|
||||
#[macro_export] // for doc test above
|
||||
macro_rules! impl_mono_map {
|
||||
($($t:ty => $tup:ident( $($pre:ident,)* @ $(, $post:ident),* ),)+) => {
|
||||
$(
|
||||
impl $crate::f::TryMap<$t> for $tup {
|
||||
fn try_map<E>(
|
||||
self,
|
||||
f: impl FnOnce($t) -> Self::FnResult<E>,
|
||||
) -> Self::Result<E> {
|
||||
match self {
|
||||
Self($($pre,)* x $(, $post),*) => match f(x) {
|
||||
Ok(y) => Ok(Self($($pre,)* y $(, $post),*)),
|
||||
Err((y, e)) => Err((
|
||||
Self($($pre,)* y $(, $post),*),
|
||||
e,
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::f::Map<$t> for $tup {
|
||||
fn map(self, f: impl FnOnce($t) -> $t) -> Self::Target {
|
||||
use std::convert::Infallible;
|
||||
use $crate::f::TryMap;
|
||||
|
||||
// `unwrap()` requires `E: Debug`,
|
||||
// so this avoids that bound.
|
||||
match self.try_map::<Infallible>(|x| Ok(f(x))) {
|
||||
Ok(y) => y,
|
||||
// Verbosely emphasize unreachability
|
||||
Err::<_, (_, Infallible)>(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// A nullary [`Fn`] delaying some computation.
|
||||
///
|
||||
/// For the history and usage of this term in computing,
|
||||
|
|
|
@ -253,6 +253,8 @@ pub mod global;
|
|||
#[macro_use]
|
||||
extern crate static_assertions;
|
||||
|
||||
#[macro_use]
|
||||
pub mod f;
|
||||
#[macro_use]
|
||||
pub mod diagnose;
|
||||
#[macro_use]
|
||||
|
@ -260,7 +262,6 @@ pub mod xir;
|
|||
|
||||
pub mod asg;
|
||||
pub mod convert;
|
||||
pub mod f;
|
||||
pub mod fmt;
|
||||
pub mod fs;
|
||||
pub mod iter;
|
||||
|
|
Loading…
Reference in New Issue