1#![recursion_limit = "512"]
2
3mod macros;
4pub use macros::*;
5mod to_num;
6pub use to_num::*;
7
8use std::marker::PhantomData;
9
10pub trait Number {}
11
12pub struct Zero;
13pub struct Successor<N: Number>(PhantomData<N>);
14pub struct Negative<N: Number>(PhantomData<N>);
15
16impl Number for Zero {}
19impl<N: Number> Number for Successor<N> {}
20impl<N: Number> Number for Negative<N> {}
21
22pub type One = Successor<Zero>;
25
26pub type Z0 = Zero;
27pub type Z1 = Successor<Z0>;
28pub type Z2 = Successor<Z1>;
29pub type Z3 = Successor<Z2>;
30pub type Z4 = Successor<Z3>;
31pub type Z5 = Successor<Z4>;
32pub type Z6 = Successor<Z5>;
33pub type Z7 = Successor<Z6>;
34pub type Z8 = Successor<Z7>;
35pub type Z9 = Successor<Z8>;
36pub type Z10 = Successor<Z9>;
37pub type Z100 = type_expr!(<Z10> * <Z10>);
38pub type ZN0 = Negative<Z0>;
39pub type ZN1 = Negative<Z1>;
40pub type ZN2 = Negative<Z2>;
41pub type ZN3 = Negative<Z3>;
42pub type ZN4 = Negative<Z4>;
43pub type ZN5 = Negative<Z5>;
44pub type ZN6 = Negative<Z6>;
45pub type ZN7 = Negative<Z7>;
46pub type ZN8 = Negative<Z8>;
47pub type ZN9 = Negative<Z9>;
48pub type ZN10 = Negative<Z10>;
49pub type ZN100 = Negative<Z100>;
50
51pub struct Op<Lhs: Number, Rhs: Number>(PhantomData<Lhs>, PhantomData<Rhs>);
54
55mod add;
56mod mul;
57mod neg;
58mod sub;
59pub use add::*;
60pub use mul::*;
61pub use neg::*;
62pub use sub::*;
63
64#[cfg(test)]
67mod test {
68 use super::*;
69
70 #[test]
71 fn test_compile() {
72 type TAOne = <Op<Zero, One> as AddOp>::Output;
74 type TATwo = <Op<TAOne, TAOne> as AddOp>::Output;
75 type TAThree1 = <Op<TAOne, TATwo> as AddOp>::Output;
76 type TAThree2 = <Op<TATwo, TAOne> as AddOp>::Output;
77 assert_types_eq!(TAOne, Z1);
78 assert_types_eq!(TATwo, Z2);
79 assert_types_eq!(TAThree1, TAThree2);
80 assert_types_eq!(TAThree1, Z3);
81
82 type TSOne1 = <Op<TATwo, TAOne> as SubOp>::Output;
85 type TSOne2 = <Op<TAThree1, TATwo> as SubOp>::Output;
86 type TSTwo1 = <Op<TATwo, Zero> as SubOp>::Output;
87 type TSTwo2 = <Op<TAThree1, TAOne> as SubOp>::Output;
88 type TSNegOne = <Op<TAOne, TATwo> as SubOp>::Output;
89 type TSNegTwo = <Op<TAOne, TAThree1> as SubOp>::Output;
90 type TSNegThree = <Op<Zero, TAThree1> as SubOp>::Output;
91 assert_types_eq!(TSOne1, TSOne2);
92 assert_types_eq!(TSOne1, Z1);
93 assert_types_eq!(TSTwo1, TSTwo2);
94 assert_types_eq!(TSTwo1, Z2);
95 assert_types_eq!(TSNegOne, ZN1);
96 assert_types_eq!(TSNegTwo, ZN2);
97 assert_types_eq!(TSNegThree, ZN3);
98
99 assert_types_eq!(<Op<TSNegOne, TSTwo1> as AddOp>::Output, Z1);
102 assert_types_eq!(<Op<TSOne1, TSNegOne> as AddOp>::Output, Z0); assert_types_eq!(<Op<TSNegOne, TSTwo1> as SubOp>::Output, ZN3);
107 assert_types_eq!(<Op<TSOne1, TSNegOne> as SubOp>::Output, Z2);
108
109 assert_types_eq!(<Op<ZN1, ZN2> as SubOp>::Output, Z1);
110 assert_types_eq!(<Op<ZN2, ZN3> as SubOp>::Output, Z1);
111 assert_types_eq!(<Op<ZN2, ZN4> as SubOp>::Output, Z2);
112
113 assert_types_eq!(type_expr!(<Z5> + <Z5>), <Op<Z5, Z5> as AddOp>::Output);
114 }
115
116 #[test]
117 fn test_run() {
118 assert_eq!(
119 <type_expr!(<Z5> + <Z8> + <Z8>) as ToNum<usize>>::OUTPUT,
120 5 + 8 + 8
121 );
122 assert_eq!(<type_expr!(<Z100> * <Z5>) as ToNum<usize>>::OUTPUT, 500);
123 assert_eq!(<type_expr!(<Z100> * <ZN5>) as ToNum<isize>>::OUTPUT, -500);
124 }
125}