Add some examples, add call!() macro

This commit is contained in:
Daniella 2023-11-14 22:13:53 +01:00
parent ef8f15a2e0
commit 42f2118834
Signed by: TudbuT
GPG key ID: B3CF345217F202D3
4 changed files with 101 additions and 7 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "type-fn"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
description = "Allows for simpler coding of type-level logic, e.g. for type-number systems."
license = "MIT"

40
examples/bools.rs Normal file
View file

@ -0,0 +1,40 @@
use type_fn::*;
#[derive(Debug)]
pub struct True;
#[derive(Debug)]
pub struct False;
type_fn! {
pub fn Or<A, B>;
pub fn And<A, B>;
pub fn Xor<A, B>;
pub fn Not<A>;
}
type_fn_impl! {
fn<TypeFn> Or< => True, B> => True;
fn<TypeFn> Or< => False, B> => B;
fn<TypeFn> And< => True, B> => B;
fn<TypeFn> And< => False, B> => False;
fn<TypeFn> Not< => True> => False;
fn<TypeFn> Not< => False> => True;
fn<TypeFn> Xor< => True, B>
where Not<B>: + TypeFn,
=> <Not<B> as TypeFn>::Ret;
fn<TypeFn> Xor< => False, B> => B;
}
fn main() {
println!(
"True AND False: {}",
core::any::type_name::<<And<True, False> as TypeFn>::Ret>()
);
println!(
"True OR False: {}",
core::any::type_name::<<Or<True, False> as TypeFn>::Ret>()
);
}

46
examples/list.rs Normal file
View file

@ -0,0 +1,46 @@
use std::{any, marker::PhantomData};
use type_fn::*;
pub struct EmptyList;
pub struct ListExt<T, Next>(PhantomData<T>, PhantomData<Next>);
pub struct RemovalResult<Element, List>(PhantomData<Element>, PhantomData<List>);
type_fn! {
pub fn AddElement<List, Element>;
pub fn RemoveLastElement<List>;
pub fn GetRemoved<R>;
pub fn GetChangedList<R>;
}
type_fn_impl! {
fn<TypeFn> AddElement<List, Element> => ListExt<Element, List>;
fn<TypeFn> RemoveLastElement<List => ListExt<Element, List> | Element> => RemovalResult<Element, List>;
fn<TypeFn> GetRemoved<Element => RemovalResult<Element, List> | List> => Element;
fn<TypeFn> GetChangedList<List => RemovalResult<Element, List> | Element> => List;
}
fn main() {
struct Hello;
struct World;
type MyListA = EmptyList;
type MyListB = <AddElement<MyListA, World> as TypeFn>::Ret;
type MyListC = <AddElement<MyListB, Hello> as TypeFn>::Ret;
type RemovalA = <RemoveLastElement<MyListC> as TypeFn>::Ret;
println!(
"{}",
any::type_name::<<GetRemoved<RemovalA> as TypeFn>::Ret>()
);
type MyListD = <GetChangedList<RemovalA> as TypeFn>::Ret;
type RemovalB = <RemoveLastElement<MyListD> as TypeFn>::Ret;
println!(
"{}",
any::type_name::<<GetRemoved<RemovalB> as TypeFn>::Ret>()
);
}

View file

@ -5,6 +5,14 @@ pub trait TypeFn {
type Ret;
}
/// Calls a type-fn
#[macro_export]
macro_rules! call {
($($fn:tt)+) => {
<$($fn)+ as TypeFn>::Ret
};
}
/// Verifies equality between two types at compile-time.
#[macro_export]
macro_rules! assert_types_eq {
@ -35,11 +43,11 @@ macro_rules! assert_types_eq {
/// You can define an arbitrary amount of functions in one macro invocation.
#[macro_export]
macro_rules! type_fn_impl {
(@a_or_else_b => ) => {compiler_error!()};
(@a_or_else_b => $($b:ident)+) => {$($b)*};
(@a_or_else_b $($a:ty)+ => $($b:ident)*) => { $($a)+ };
($(fn < $sup:ty > $name:ident <$($($arg:ident)? $(=> $($argv:ty)+)?),* $(| $($targ:ident),+)?>
$(where $($tv:ty : $( + $( ?$tcqm:ident )? $( $tc:ident )? )+ ,)+)? => $ret:ty;)+)
{@a_or_else_b => } => {compiler_error!()};
{@a_or_else_b => $($b:ident)+} => {$($b)*};
{@a_or_else_b $($a:ty)+ => $($b:ident)*} => { $($a)+ };
{$(fn < $sup:ty > $name:ident <$($($arg:ident)? $(=> $($argv:ty)+)?),* $(| $($targ:ident),+)?>
$(where $($tv:ty : $( + $( ?$tcqm:ident )? $( $tc:ident )? )+ ,)+)? => $ret:ty;)+}
=> {
$(
impl<$($($arg, )?)* $($($targ, )*)?>
@ -107,7 +115,7 @@ mod tests {
type TwoMinusOne = <Sub<Succ<Succ<Zero>>, Succ<Zero>> as TypeFn>::Ret;
assert_types_eq!(TwoMinusOne, Succ<Zero>);
assert_types_eq!(<Sub<TwoMinusOne, Succ<Zero>> as TypeFn>::Ret, Zero);
assert_types_eq!(call!(Sub<TwoMinusOne, Succ<Zero>>), Zero);
assert_types_eq!(
Succ<Succ<Succ<Succ<Zero>>>>,
<Mul<Succ<Succ<Zero>>, Succ<Succ<Zero>>> as TypeFn>::Ret