#![feature(unboxed_closures, tuple_trait, fn_traits)]
use std::{marker::Tuple, ops::Add};
pub trait Function<T> {
type Output;
fn apply(&mut self, value: T) -> Self::Output;
}
pub trait Map<T> {
type Output;
fn map(&mut self, value: T) -> Self::Output;
}
pub trait Fold<A, T> {
fn fold(&mut self, value: T, accumulator: A) -> A;
}
#[derive(Debug, PartialEq, Hash, Clone, Copy)]
pub struct Single<T>(pub T);
#[derive(Debug, PartialEq, Hash, Clone, Copy)]
pub struct Sequence<T, R>(pub T, pub R);
impl<F, A, T> Fold<A, Single<T>> for F
where
F: Function<(A, T), Output = A>,
{
fn fold(&mut self, value: Single<T>, accumulator: A) -> A {
self.apply((accumulator, value.0))
}
}
impl<F, A, T, R> Fold<A, Sequence<T, R>> for F
where
F: Function<(A, T), Output = A>,
F: Fold<A, R>,
{
fn fold(&mut self, value: Sequence<T, R>, accumulator: A) -> A {
let first = self.apply((accumulator, value.0));
self.fold(value.1, first)
}
}
impl<F, T> Map<Single<T>> for F
where
F: Function<(T,)>,
{
type Output = Single<F::Output>;
fn map(&mut self, value: Single<T>) -> Self::Output {
Single(self.apply((value.0,)))
}
}
impl<F, T, R> Map<Sequence<T, R>> for F
where
F: Function<(T,)>,
F: Map<R>,
{
type Output = Sequence<<F as Function<(T,)>>::Output, <F as Map<R>>::Output>;
fn map(&mut self, value: Sequence<T, R>) -> Self::Output {
Sequence(self.apply((value.0,)), self.map(value.1))
}
}
impl<F, T> Function<T> for F
where
F: FnMut<T>,
T: Tuple,
{
type Output = <F as FnOnce<T>>::Output;
fn apply(&mut self, value: T) -> Self::Output {
self.call_mut(value)
}
}
#[macro_export]
macro_rules! list {
($x:expr) => {
Single($x)
};
($x:expr, $y:expr $(,$($tt:tt)*)?) => {
Sequence($x, list!($y $(,$($tt)*)?))
};
}
#[macro_export]
macro_rules! List {
($x:ty) => {
Single<$x>
};
($x:ty, $y:ty $(,$($tt:tt)*)?) => {
Sequence<$x, List!($y $(,$($tt)*)?)>
};
}
#[macro_export]
macro_rules! function {
(
$name:ident
$([ $($capture:ident : $cty:ty $(,)?)* ])?
$(< $($parameter:ident $(,)?)* >)?
(&mut $self:ident, $($arg:ident: $aty:ty$(,)?)*)
-> $ret:ty
$(where ($($tt:tt)*) )?
$block:block
) => {
pub struct $name<'a> {
$(
$($capture: &'a mut $cty,)*
)?
__phantom: std::marker::PhantomData<fn(&'a ())>,
}
impl<'a, $($($parameter,)*)?> Function<($($aty,)*)> for $name<'a> $(where $($tt)*)? {
type Output = $ret;
fn apply(&mut $self, ($($arg,)*): ($($aty,)*)) -> Self::Output {
$block
}
}
#[allow(clippy::new_without_default)]
impl<'a> $name<'a> {
pub fn new($($($capture: &'a mut $cty,)*)?) -> Self {
Self {
$($($capture,)*)?
__phantom: std::marker::PhantomData,
}
}
}
};
(
$([ $($capture:ident : $cty:ty $(,)?)* ])?
$(< $($parameter:ident $(,)?)* >)?
(&mut $self:ident, $($arg:ident: $aty:ty$(,)?)*)
-> $ret:ty
$(where ($($tt:tt)*) )?
$block:block
) => {
{
pub struct Func<'a> {
$(
$($capture: &'a mut $cty,)*
)?
__phantom: std::marker::PhantomData<fn(&'a ())>,
}
impl<'a, $($($parameter,)*)?> Function<($($aty,)*)> for Func<'a> $(where $($tt)*)? {
type Output = $ret;
fn apply(&mut $self, ($($arg,)*): ($($aty,)*)) -> Self::Output {
$block
}
}
Func {
$($($capture: &mut $capture,)*)?
__phantom: std::marker::PhantomData,
}
}
};
}
pub trait Construct<T> {
fn construct(value: T) -> Self;
}
pub trait List: Sized {
fn map<F: Map<Self>>(self, f: &mut F) -> F::Output {
f.map(self)
}
fn fold<A, F: Fold<A, Self>>(self, accumulator: A, mut f: F) -> A {
f.fold(self, accumulator)
}
fn construct<T: Construct<Self>>(self) -> T {
T::construct(self)
}
}
impl<T> List for Single<T> {}
impl<T, R> List for Sequence<T, R> {}
pub trait Struct: Construct<Self::Fields> {
type Fields: List;
type FieldsAndNames: List;
type FieldsRef<'a>: List
where
Self: 'a;
type FieldsAndNamesRef<'a>: List
where
Self: 'a;
type FieldsMut<'a>: List
where
Self: 'a;
type FieldsAndNamesMut<'a>: List
where
Self: 'a;
fn fields(self) -> Self::Fields;
fn fields_and_names(self) -> Self::FieldsAndNames;
fn fields_ref(&self) -> Self::FieldsRef<'_>;
fn fields_and_names_ref(&self) -> Self::FieldsAndNamesRef<'_>;
fn fields_mut(&mut self) -> Self::FieldsMut<'_>;
fn fields_and_names_mut(&mut self) -> Self::FieldsAndNamesMut<'_>;
}
#[derive(Debug, Clone, PartialEq)]
pub struct Point {
x: i32,
y: i32,
}
impl Struct for Point {
type Fields = List![i32, i32];
type FieldsAndNames = List![(&'static str, i32), (&'static str, i32)];
type FieldsRef<'a> = List![&'a i32, &'a i32];
type FieldsAndNamesRef<'a> = List![(&'static str, &'a i32), (&'static str, &'a i32)];
type FieldsMut<'a> = List![&'a mut i32, &'a mut i32];
type FieldsAndNamesMut<'a> = List![(&'static str, &'a mut i32), (&'static str, &'a mut i32)];
fn fields(self) -> Self::Fields {
list![self.x, self.y]
}
fn fields_and_names(self) -> Self::FieldsAndNames {
list![("x", self.x), ("y", self.y)]
}
fn fields_ref(&self) -> Self::FieldsRef<'_> {
list![&self.x, &self.y]
}
fn fields_and_names_ref(&self) -> Self::FieldsAndNamesRef<'_> {
list![("x", &self.x), ("y", &self.y)]
}
fn fields_mut(&mut self) -> Self::FieldsMut<'_> {
list![&mut self.x, &mut self.y]
}
fn fields_and_names_mut(&mut self) -> Self::FieldsAndNamesMut<'_> {
list![("x", &mut self.x), ("y", &mut self.y)]
}
}
impl Construct<List![i32, i32]> for Point {
fn construct(value: List![i32, i32]) -> Self {
let Sequence(x, Single(y)) = value;
Self { x, y }
}
}
function!(
Dup<T>(&mut self, v: T) -> T where (T: Add<Output = T> + Copy) {
v + v
}
);