#[macro_export]
macro_rules! make_units {
($System:ident;
$one:ident: $Unitless:ident;
base {
$($base:ident: $Unit:ident, $print_as:expr $(, $base_dim:ident)*;)+
}
derived {
$($derived_const:ident: $Derived:ident = ($($derived_rhs:tt)+) $(, $derived_dim:ident)*;)*
}
constants {
$($constant:ident: $ConstantUnit:ident = $constant_value:expr;)*
}
fmt = $to_fmt:ident;
) => (
use $crate::dimcore::marker;
use $crate::{Dimensioned, Dimensionless};
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash)]
pub struct $System<V, U> {
pub value_unsafe: V,
pub _marker: marker::PhantomData<U>,
}
impl<V, U> $System<V, U> {
#[inline]
pub fn new(v: V) -> Self {
$System { value_unsafe: v, _marker: marker::PhantomData }
}
}
impl<V, U> Dimensioned for $System<V, U> {
type Value = V;
type Units = U;
#[inline]
fn new(val: V) -> Self {
$System::new(val)
}
#[inline]
fn value_unsafe(&self) -> &V {
&self.value_unsafe
}
}
use $crate::MapUnsafe;
impl<ValueIn, UnitsIn, ValueOut, UnitsOut> MapUnsafe<ValueOut, UnitsOut> for $System<ValueIn, UnitsIn> {
type Output = $System<ValueOut, UnitsOut>;
#[inline]
fn map_unsafe<F: FnOnce(ValueIn) -> ValueOut>(self, f: F) -> Self::Output {
$System::new(f(self.value_unsafe))
}
}
use $crate::Map;
impl<ValueIn, ValueOut> Map<ValueOut> for $Unitless<ValueIn>
{
type Output = $Unitless<ValueOut>;
#[inline]
fn map<F: FnOnce(ValueIn) -> ValueOut>(self, f: F) -> Self::Output {
$System::new(f(self.value_unsafe))
}
}
#[cfg(feature = "oibit")]
use $crate::NotDim;
#[cfg(feature = "oibit")]
impl<V, U> !NotDim for $System<V, U> {}
#[doc(hidden)]
pub mod inner {
#[allow(unused_imports)]
use $crate::traits::*;
#[allow(unused_imports)]
use $crate::typenum::consts::*;
__make_units_internal!(@base_arrays $Unitless $($Unit)*);
$(#[allow(missing_docs)] pub type $Derived = __derived_internal!(@mu commas $($derived_rhs)+);)*
}
#[allow(missing_docs)]
pub type $Unitless<V> = $System<V, inner::$Unitless>;
$(#[allow(missing_docs)]
pub type $Unit<V> = $System<V, inner::$Unit>;
$(impl<V> $crate::dimensions::$base_dim for $Unit<V> {})*
)*
impl<Value> $crate::Dimensionless for $Unitless<Value> {
#[inline]
fn value(&self) -> &Value {
&self.value_unsafe
}
}
$(#[allow(missing_docs)] pub type $Derived<V> = $System<V, inner::$Derived>;
$(impl<V> $crate::dimensions::$derived_dim for $Derived<V> {})*
)*
macro_rules! define_consts {
($module:ident, $prefixes:ident, $t:ident) => (
pub mod $module {
use super::*;
use $crate::dimcore::marker::PhantomData;
#[allow(unused_imports)] use $crate::dimcore::$t::consts;
#[allow(unused_imports)] use $crate::$prefixes::*;
#[allow(dead_code, missing_docs)]
pub const $one: $Unitless<$t> = $System { value_unsafe: 1.0, _marker: PhantomData };
$(#[allow(dead_code, missing_docs)]
pub const $base: $Unit<$t> = $System { value_unsafe: 1.0, _marker: PhantomData };)*
$(#[allow(dead_code, missing_docs)]
pub const $derived_const: $Derived<$t> = $System { value_unsafe: 1.0, _marker: PhantomData };)*
$(#[allow(dead_code, missing_docs)]
pub const $constant: $ConstantUnit<$t> = $System { value_unsafe: $constant_value, _marker: PhantomData };)*
}
);
}
define_consts!(f32consts, f32prefixes, f32);
define_consts!(f64consts, f64prefixes, f64);
use $crate::dimcore::fmt;
use $crate::typenum::{Len, Length, TypeArray};
use $crate::generic_array::{GenericArray, ArrayLength};
use $crate::array::ToGA;
__make_units_internal!(@fmt true S $System $(P $print_as;)* T Debug E "{:?}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T Display E "{}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T Octal E "{:o}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T LowerHex E "{:x}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T UpperHex E "{:X}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T Pointer E "{:p}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T Binary E "{:b}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T LowerExp E "{:e}");
__make_units_internal!(@fmt $to_fmt S $System $(P $print_as;)* T UpperExp E "{:E}");
impl<V, U> $crate::Recip for $System<V, U> where V: $crate::Recip, U: $crate::dimcore::ops::Neg, {
type Output = $System<<V as $crate::Recip>::Output, $crate::typenum::Negate<U>>;
#[inline]
fn recip(self) -> Self::Output { $System::new(self.value_unsafe.recip()) }
}
use $crate::typenum::Pow;
impl<Exp, V, U> Pow<Exp> for $System<V, U>
where V: Pow<Exp>,
U: $crate::dimcore::ops::Mul<Exp>,
{
type Output = $System< <V as Pow<Exp>>::Output, $crate::typenum::Prod<U, Exp>>;
#[inline]
fn powi(self, exp: Exp) -> Self::Output {
$System::new( self.value_unsafe.powi(exp) )
}
}
impl<Index, V, U> $crate::Root<Index> for $System<V, U>
where V: $crate::Root<Index>,
U: $crate::typenum::PartialDiv<Index>,
{
type Output = $System< <V as $crate::Root<Index>>::Output, $crate::typenum::PartialQuot<U, Index>>;
#[inline]
fn root(self, idx: Index) -> Self::Output {
$System::new( self.value_unsafe.root(idx) )
}
}
use $crate::typenum::P2;
impl<V, U> $crate::Sqrt for $System<V, U>
where V: $crate::Sqrt,
U: $crate::typenum::PartialDiv<P2>,
{
type Output = $System< <V as $crate::Sqrt>::Output, $crate::typenum::PartialQuot<U, P2>>;
#[inline]
fn sqrt(self) -> Self::Output {
$System::new( self.value_unsafe.sqrt() )
}
}
use $crate::typenum::P3;
impl<V, U> $crate::Cbrt for $System<V, U>
where V: $crate::Cbrt,
U: $crate::typenum::PartialDiv<P3>,
{
type Output = $System< <V as $crate::Cbrt>::Output, $crate::typenum::PartialQuot<U, P3>>;
#[inline]
fn cbrt(self) -> Self::Output {
$System::new( self.value_unsafe.cbrt() )
}
}
use $crate::dimcore::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign,
BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Sub,
SubAssign, Rem, RemAssign, Neg, Not, Shl, ShlAssign, Shr,
ShrAssign};
use $crate::typenum::{Prod, Quot};
__make_units_internal!(@ops $System, $Unitless);
use $crate::dimcore::ops::Deref;
impl<V, U> Deref for $System<V, U> where $System<V, U>: Dimensionless {
type Target = V;
#[inline]
fn deref(&self) -> &Self::Target {
&self.value_unsafe
}
}
use $crate::dimcore::ops::Index;
impl<V, U, Idx> Index<Idx> for $System<V, U>
where V: Index<Idx>,
<V as Index<Idx>>::Output: Sized,
{
type Output = $System<<V as Index<Idx>>::Output, U>;
#[inline]
fn index(&self, index: Idx) -> &Self::Output {
unsafe {
$crate::dimcore::mem::transmute(&self.value_unsafe[index])
}
}
}
use $crate::dimcore::ops::IndexMut;
impl<V, U, Idx> IndexMut<Idx> for $System<V, U>
where $System<V, U>: Index<Idx>,
V: Index<Idx> + IndexMut<Idx>,
<V as Index<Idx>>::Output: Sized,
<$System<V, U> as Index<Idx>>::Output: Sized
{
#[inline]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output{
unsafe {
$crate::dimcore::mem::transmute(self.value_unsafe.index_mut(index))
}
}
}
);
}
#[doc(hidden)]
#[macro_export]
macro_rules! __make_units_internal {
(@ops $System:ident, $Unitless:ident) => (
macro_rules! unary_op {
($Trait:ident, $fun:ident) => (
impl<V, U> $Trait for $System<V, U> where
V: $Trait,
{
type Output = $System<<V as $Trait>::Output, U>;
#[inline]
fn $fun(self) -> Self::Output {
$System::new($Trait::$fun(self.value_unsafe))
}
}
);
}
unary_op!(Not, not);
unary_op!(Neg, neg);
macro_rules! binary_unit_preserve {
($Trait:ident, $fun:ident, $TraitAssign:ident, $fun_assign:ident) => (
impl<Vl, U, Vr> $Trait<$System<Vr, U>> for $System<Vl, U> where
Vl: $Trait<Vr>,
{
type Output = $System<<Vl as $Trait<Vr>>::Output, U>;
#[inline]
fn $fun(self, rhs: $System<Vr, U>) -> Self::Output {
$System::new($Trait::$fun(self.value_unsafe, rhs.value_unsafe))
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> $Trait<Vr> for $System<Vl, U> where
Vl: $Trait<Vr>, Vr: NotDim, $System<Vl, U>: Dimensionless
{
type Output = $System<<Vl as $Trait<Vr>>::Output, U>;
#[inline]
fn $fun(self, rhs: Vr) -> Self::Output {
$System::new($Trait::$fun(self.value_unsafe, rhs))
}
}
impl<Vl, U, Vr> $TraitAssign<$System<Vr, U>> for $System<Vl, U> where
Vl: $TraitAssign<Vr>,
{
#[inline]
fn $fun_assign(&mut self, rhs: $System<Vr, U>) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs.value_unsafe)
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> $TraitAssign<Vr> for $System<Vl, U> where
Vl: $TraitAssign<Vr>, Vr: NotDim, $System<Vl, U>: Dimensionless
{
#[inline]
fn $fun_assign(&mut self, rhs: Vr) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs)
}
}
);
}
binary_unit_preserve!(Add, add, AddAssign, add_assign);
binary_unit_preserve!(Sub, sub, SubAssign, sub_assign);
binary_unit_preserve!(BitAnd, bitand, BitAndAssign, bitand_assign);
binary_unit_preserve!(BitOr, bitor, BitOrAssign, bitor_assign);
binary_unit_preserve!(BitXor, bitxor, BitXorAssign, bitxor_assign);
macro_rules! binary_unit_change {
($Trait:ident, $fun:ident, $op:ident, $TraitAssign:ident, $fun_assign:ident) => (
impl<Vl, Ul, Vr, Ur> $Trait<$System<Vr, Ur>> for $System<Vl, Ul> where
Vl: $Trait<Vr>, Ul: $op<Ur>,
{
type Output = $System<<Vl as $Trait<Vr>>::Output, <Ul as $op<Ur>>::Output>;
#[inline]
fn $fun(self, rhs: $System<Vr, Ur>) -> Self::Output {
$System::new( $Trait::$fun(self.value_unsafe, rhs.value_unsafe) )
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> $Trait<Vr> for $System<Vl, U> where
Vl: $Trait<Vr>, Vr: NotDim,
{
type Output = $System<<Vl as $Trait<Vr>>::Output, U>;
#[inline]
fn $fun(self, rhs: Vr) -> Self::Output {
$System::new( $Trait::$fun(self.value_unsafe, rhs) )
}
}
impl<Vl, Ul, Vr, Ur> $TraitAssign<$System<Vr, Ur>> for $System<Vl, Ul> where
Vl: $TraitAssign<Vr>,
$System<Vr, Ur>: Dimensionless,
{
#[inline]
fn $fun_assign(&mut self, rhs: $System<Vr, Ur>) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs.value_unsafe)
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> $TraitAssign<Vr> for $System<Vl, U> where
Vl: $TraitAssign<Vr>, Vr: NotDim,
{
#[inline]
fn $fun_assign(&mut self, rhs: Vr) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs)
}
}
);
}
binary_unit_change!(Mul, mul, Add, MulAssign, mul_assign);
binary_unit_change!(Div, div, Sub, DivAssign, div_assign);
impl<Vl, Ul, Vr, Ur> Rem<$System<Vr, Ur>> for $System<Vl, Ul> where
Vl: Rem<Vr>
{
type Output = $System<<Vl as Rem<Vr>>::Output, Ul>;
#[inline]
fn rem(self, rhs: $System<Vr, Ur>) -> Self::Output {
$System::new( self.value_unsafe % rhs.value_unsafe )
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> Rem<Vr> for $System<Vl, U> where
Vl: Rem<Vr>, Vr: NotDim,
{
type Output = $System<<Vl as Rem<Vr>>::Output, U>;
#[inline]
fn rem(self, rhs: Vr) -> Self::Output {
$System::new( self.value_unsafe % rhs )
}
}
impl<Vl, Ul, Vr, Ur> RemAssign<$System<Vr, Ur>> for $System<Vl, Ul> where
Vl: RemAssign<Vr>,
{
#[inline]
fn rem_assign(&mut self, rhs: $System<Vr, Ur>) {
self.value_unsafe %= rhs.value_unsafe
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> RemAssign<Vr> for $System<Vl, U> where
Vl: RemAssign<Vr>, Vr: NotDim,
{
#[inline]
fn rem_assign(&mut self, rhs: Vr) {
self.value_unsafe %= rhs
}
}
macro_rules! binary_shift {
($Trait:ident, $fun:ident, $TraitAssign:ident, $fun_assign:ident) => (
impl<Vl, Ul, Vr, Ur> $Trait<$System<Vr, Ur>> for $System<Vl, Ul> where
Vl: $Trait<Vr>, $System<Vr, Ur>: Dimensionless
{
type Output = $System<<Vl as $Trait<Vr>>::Output, Ul>;
#[inline]
fn $fun(self, rhs: $System<Vr, Ur>) -> Self::Output {
$System::new( $Trait::$fun(self.value_unsafe, rhs.value_unsafe) )
}
}
#[cfg(feature = "oibit")]
impl<Vl, Ul, Vr> $Trait<Vr> for $System<Vl, Ul> where
Vl: $Trait<Vr>, Vr: NotDim,
{
type Output = $System<<Vl as $Trait<Vr>>::Output, Ul>;
#[inline]
fn $fun(self, rhs: Vr) -> Self::Output {
$System::new( $Trait::$fun(self.value_unsafe, rhs) )
}
}
impl<Vl, Ul, Vr, Ur> $TraitAssign<$System<Vr, Ur>> for $System<Vl, Ul> where
Vl: $TraitAssign<Vr>,
$System<Vr, Ur>: Dimensionless,
{
#[inline]
fn $fun_assign(&mut self, rhs: $System<Vr, Ur>) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs.value_unsafe)
}
}
#[cfg(feature = "oibit")]
impl<Vl, U, Vr> $TraitAssign<Vr> for $System<Vl, U> where
Vl: $TraitAssign<Vr>, Vr: NotDim,
{
#[inline]
fn $fun_assign(&mut self, rhs: Vr) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs)
}
}
);
}
binary_shift!(Shl, shl, ShlAssign, shl_assign);
binary_shift!(Shr, shr, ShrAssign, shr_assign);
macro_rules! prim {
($t: ty) => (
macro_rules! same_units {
($Trait:ident, $fun:ident, $TraitAssign:ident, $fun_assign:ident) => (
#[cfg(not(feature = "oibit"))]
impl<V, U> $Trait<$t> for $System<V, U> where
V: $Trait<$t>, $System<V, U>: Dimensionless
{
type Output = $System<<V as $Trait<$t>>::Output, U>;
#[inline]
fn $fun(self, rhs: $t) -> Self::Output {
$System::new( $Trait::$fun(self.value_unsafe, rhs) )
}
}
impl<V, U> $Trait<$System<V, U>> for $t where
$t: $Trait<V>, $System<V, U>: Dimensionless
{
type Output = $System<<$t as $Trait<V>>::Output, U>;
#[inline]
fn $fun(self, rhs: $System<V, U>) -> Self::Output {
$System::new( $Trait::$fun(self, rhs.value_unsafe) )
}
}
#[cfg(not(feature = "oibit"))]
impl<V, U> $TraitAssign<$t> for $System<V, U> where
V: $TraitAssign<$t>, $System<V, U>: Dimensionless
{
#[inline]
fn $fun_assign(&mut self, rhs: $t) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs)
}
}
);
}
same_units!(Add, add, AddAssign, add_assign);
same_units!(Sub, sub, SubAssign, sub_assign);
same_units!(BitAnd, bitand, BitAndAssign, bitand_assign);
same_units!(BitOr, bitor, BitOrAssign, bitor_assign);
same_units!(BitXor, bitxor, BitXorAssign, bitxor_assign);
macro_rules! rhs_units_differ {
($Trait:ident, $fun:ident, $TraitAssign:ident, $fun_assign:ident) => (
#[cfg(not(feature = "oibit"))]
impl<V, U> $Trait<$t> for $System<V, U> where
V: $Trait<$t>
{
type Output = $System<<V as $Trait<$t>>::Output, U>;
#[inline]
fn $fun(self, rhs: $t) -> Self::Output {
$System::new( $Trait::$fun(self.value_unsafe, rhs) )
}
}
#[cfg(not(feature = "oibit"))]
impl<V, U> $TraitAssign<$t> for $System<V, U> where
V: $TraitAssign<$t>
{
#[inline]
fn $fun_assign(&mut self, rhs: $t) {
$TraitAssign::$fun_assign(&mut self.value_unsafe, rhs)
}
}
);
}
rhs_units_differ!(Mul, mul, MulAssign, mul_assign);
rhs_units_differ!(Div, div, DivAssign, div_assign);
rhs_units_differ!(Rem, rem, RemAssign, rem_assign);
rhs_units_differ!(Shl, shl, ShlAssign, shl_assign);
rhs_units_differ!(Shr, shr, ShrAssign, shr_assign);
impl<V, U> Mul<$System<V, U>> for $t where $t: Mul<V> {
type Output = $System<Prod<$t, V>, U>;
#[inline]
fn mul(self, rhs: $System<V, U>) -> Self::Output {
$System::new(self * rhs.value_unsafe)
}
}
impl<V, U> Div<$System<V, U>> for $t where $t: Div<V>, U: Neg {
type Output = $System<Quot<$t, V>, <U as Neg>::Output>;
#[inline]
fn div(self, rhs: $System<V, U>) -> Self::Output {
$System::new(self / rhs.value_unsafe)
}
}
impl<V, U> Rem<$System<V, U>> for $t where $t: Rem<V> {
type Output = $Unitless<<$t as Rem<V>>::Output>;
#[inline]
fn rem(self, rhs: $System<V, U>) -> Self::Output {
$System::new(self % rhs.value_unsafe)
}
}
);
}
prim!(f32);
prim!(f64);
prim!(i8);
prim!(i16);
prim!(i32);
prim!(i64);
prim!(isize);
prim!(u8);
prim!(u16);
prim!(u32);
prim!(u64);
prim!(usize);
prim!(bool);
prim!(char);
);
(@fmt true S $System:ident $(P $print_as:expr;)* T $Trait:ident E $token:expr) => (
impl<V, U> fmt::$Trait for $System<V, U> where
V: fmt::$Trait,
Length<U>: ArrayLength<isize>,
U: TypeArray + Len + ToGA<Output = GenericArray<isize, Length<U>>>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
{
let exponents = U::to_ga();
let print_tokens = [$($print_as),*];
let mut first = true;
self.value_unsafe.fmt(f)?;
for (exp, token) in
exponents.into_iter()
.zip(print_tokens.iter())
{
if first {
if exp != 0 {
first = false;
write!(f, " ")?;
}
} else if exp != 0 {
write!(f, "*")?;
}
match exp {
0 => (),
1 => write!(f, "{}", token)?,
_ => {
write!(f, "{}^{}", token, exp)?
},
}
}
Ok(())
}
}
);
(@fmt false S $System:ident $(P $print_as:expr;)* T $Trait:ident E $token:expr) => ();
(@base_arrays $Unitless:ident $Unit:ident $($Units:ident)*) => (
pub type $Unitless = tarr![Z0, $(__make_units_internal!(@convert_to_zero $Units)),*];
__make_units_internal!(@next_array U $Unit $(U $Units)* $(E $Units)*);
);
(@next_array U $Unit:ident $(U $Units:ident)*
$(F $FrontZeros:ident)* E $Zero:ident $(E $EndZeros:ident)*) => (
pub type $Unit = tarr![
$(__make_units_internal!(@convert_to_zero $FrontZeros),)*
P1,
Z0 $(, __make_units_internal!(@convert_to_zero $EndZeros))*
];
__make_units_internal!(@next_array $(U $Units)* $(F $FrontZeros)* F $Zero $(E $EndZeros)*);
);
(@next_array U $Unit:ident $(F $FrontZeros:ident)*) => (
pub type $Unit = tarr![
$(__make_units_internal!(@convert_to_zero $FrontZeros),)*
P1
];
);
(@convert_to_zero $Unit:ident) => ( Z0 );
(@convert_to_zero) => ();
}
#[macro_export]
macro_rules! derived {
($module:ident, $System:ident: $name:ident = $($tail:tt)*) => (
pub type $name<V> = $System<V, __derived_internal!(@commas $module, $($tail)*)>;
);
}
#[doc(hidden)]
#[macro_export]
macro_rules! __derived_internal {
(@eval $module:ident, $a:ty,) => ($a);
(@eval $module:ident, $a:ident, /, $b:ident, $($tail:tt)*) => (
__derived_internal!(@eval $module, $crate::typenum::Diff<$module::inner::$a, $module::inner::$b>, $($tail)* )
);
(@eval $module:ident, $a:ident, *, $b:ident, $($tail:tt)*) => (
__derived_internal!(@eval $module, $crate::typenum::Sum<$module::inner::$a, $module::inner::$b>, $($tail)* )
);
(@eval $module:ident, $a:ty, /, $b:ident, $($tail:tt)*) => (
__derived_internal!(@eval $module, $crate::typenum::Diff<$a, $module::inner::$b>, $($tail)* )
);
(@eval $module:ident, $a:ty, *, $b:ident, $($tail:tt)*) => (
__derived_internal!(@eval $module, $crate::typenum::Sum<$a, $module::inner::$b>, $($tail)* )
);
(@commas $module:ident, $t:ty) => ($t);
(@commas $module:ident, $($tail:tt)*) => (__derived_internal!(@eval $module, $($tail,)*));
(@mu eval $a:ty,) => ($a);
(@mu eval $a:ty, *, $b:ty, $($tail:tt)*) =>
(__derived_internal!(@mu eval $crate::typenum::Sum<$a, $b>, $($tail)* ));
(@mu eval $a:ty, /, $b:ty, $($tail:tt)*) =>
(__derived_internal!(@mu eval $crate::typenum::Diff<$a, $b>, $($tail)* ));
(@mu commas $t:ty) => ($t);
(@mu commas $($tail:tt)*) => (__derived_internal!(@mu eval $($tail,)*));
}