diff --git a/Cargo.toml b/Cargo.toml index ec9f865..ba65888 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/bools.rs b/examples/bools.rs new file mode 100644 index 0000000..82315c2 --- /dev/null +++ b/examples/bools.rs @@ -0,0 +1,40 @@ +use type_fn::*; + +#[derive(Debug)] +pub struct True; +#[derive(Debug)] +pub struct False; + +type_fn! { + pub fn Or; + pub fn And; + pub fn Xor; + pub fn Not; +} + +type_fn_impl! { + fn Or< => True, B> => True; + fn Or< => False, B> => B; + + fn And< => True, B> => B; + fn And< => False, B> => False; + + fn Not< => True> => False; + fn Not< => False> => True; + + fn Xor< => True, B> + where Not: + TypeFn, + => as TypeFn>::Ret; + fn Xor< => False, B> => B; +} + +fn main() { + println!( + "True AND False: {}", + core::any::type_name::< as TypeFn>::Ret>() + ); + println!( + "True OR False: {}", + core::any::type_name::< as TypeFn>::Ret>() + ); +} diff --git a/examples/list.rs b/examples/list.rs new file mode 100644 index 0000000..89b34b5 --- /dev/null +++ b/examples/list.rs @@ -0,0 +1,46 @@ +use std::{any, marker::PhantomData}; + +use type_fn::*; + +pub struct EmptyList; +pub struct ListExt(PhantomData, PhantomData); + +pub struct RemovalResult(PhantomData, PhantomData); + +type_fn! { + pub fn AddElement; + pub fn RemoveLastElement; + + pub fn GetRemoved; + pub fn GetChangedList; +} + +type_fn_impl! { + fn AddElement => ListExt; + fn RemoveLastElement ListExt | Element> => RemovalResult; + + fn GetRemoved RemovalResult | List> => Element; + fn GetChangedList RemovalResult | Element> => List; +} + +fn main() { + struct Hello; + struct World; + + type MyListA = EmptyList; + type MyListB = as TypeFn>::Ret; + type MyListC = as TypeFn>::Ret; + + type RemovalA = as TypeFn>::Ret; + println!( + "{}", + any::type_name::< as TypeFn>::Ret>() + ); + + type MyListD = as TypeFn>::Ret; + type RemovalB = as TypeFn>::Ret; + println!( + "{}", + any::type_name::< as TypeFn>::Ret>() + ); +} diff --git a/src/lib.rs b/src/lib.rs index 6ccda22..51c9b47 100644 --- a/src/lib.rs +++ b/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 = >, Succ> as TypeFn>::Ret; assert_types_eq!(TwoMinusOne, Succ); - assert_types_eq!(> as TypeFn>::Ret, Zero); + assert_types_eq!(call!(Sub>), Zero); assert_types_eq!( Succ>>>, >, Succ>> as TypeFn>::Ret