Add some examples, add call!() macro
This commit is contained in:
parent
ef8f15a2e0
commit
42f2118834
4 changed files with 101 additions and 7 deletions
|
@ -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
40
examples/bools.rs
Normal 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
46
examples/list.rs
Normal 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>()
|
||||
);
|
||||
}
|
20
src/lib.rs
20
src/lib.rs
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue