1 module evx.meta.transform;
2 
3 private {//imports
4 	import std.traits;
5 	import std.typecons;
6 	import evx.meta.match;
7 }
8 
9 /**
10 	 identity template
11 */
12 alias Identity (T...) = T[0]; 
13 ///
14 unittest {
15     static assert (is (Identity!int == int));
16 }
17 
18 /**
19 	 identity function
20 */
21 auto ref identity (T)(T x)
22 {
23 	return x;
24 }
25 ///
26 unittest {
27     assert (1.identity == 1);
28 }
29 
30 /**
31 	 get the type of a single-symbol expression
32 */
33 template ExprType (alias symbol)
34 {
35 	 alias ExprType = typeof(symbol.identity);
36 }
37 ///
38 unittest {
39     auto a (){return 1;}
40     auto b = 1;
41 
42     static assert (!(is (typeof(a) == typeof(b))));
43     static assert (is (typeof(a()) == typeof(b)));
44     static assert (is (typeof(a()) == ExprType!a));
45     static assert (is (ExprType!a == ExprType!b));
46 }
47 
48 /**
49 	 remove qualifiers from a type
50 */
51 alias Unqual = std.traits.Unqual;
52 
53 /**
54 	 select one of two valid expressions based on a boolean expression
55 */
56 alias Select = std.typecons.Select;
57 
58 /**
59 	 extract the underlying type of a unary template type
60 */
61 template Unwrapped (T)
62 {
63 	static if (is (T == W!U, alias W, U))
64 		alias Unwrapped = U;
65 	else alias Unwrapped = T;
66 }
67 ///
68 unittest {
69 	static struct T {}
70 	static struct U (T) {}
71 
72 	alias V = U!T;
73 	alias W = U!(U!T);
74 
75 	static assert (is (Unwrapped!T == T));
76 	static assert (is (Unwrapped!V == T));
77 	static assert (is (Unwrapped!W == V));
78 	static assert (is (Unwrapped!(Unwrapped!W) == T));
79 }
80 
81 /**
82 	 extract the deepest underlying type of a nested series of unary templates
83 */
84 template InitialType (T)
85 {
86 	static if (is (T == W!U, alias W, U))
87 		alias InitialType = InitialType!U;
88 	else alias InitialType = T;
89 }
90 ///
91 unittest {
92 	static struct T {}
93 	static struct U (T) {}
94 
95 	alias V = U!T;
96 	alias W = U!(U!T);
97 
98 	static assert (is (InitialType!T == T));
99 	static assert (is (InitialType!V == T));
100 	static assert (is (InitialType!W == T));
101 }
102 
103 /**
104 	 compose a list of templates into a single template
105 */
106 template Compose (Templates...)
107 {
108 	static if (Templates.length > 1)
109 	{
110 		alias T = Templates[0];
111 		alias U = Compose!(Templates[1..$]);
112 
113 		alias Compose (Args...) = T!(U!(Args));
114 	}
115 	else alias Compose = Templates[0];
116 }
117 ///
118 unittest {
119 	import std.range: ElementType;
120 
121 	alias ArrayOf (T) = T[];
122 	alias Const (T) = const(T);
123 
124 	alias C0 = Compose!(ElementType, ArrayOf);
125 	alias C1 = Compose!(ArrayOf, ElementType);
126 	alias C2 = Compose!(ElementType, Const, C0);
127 	alias C3 = Compose!(ArrayOf, Unqual, C2);
128 
129 	alias T = int[5];
130 
131 	static assert (is (C0!T == int[5]));
132 	static assert (is (C1!T == int[]));
133 	static assert (is (C2!T == const(int)));
134 	static assert (is (C3!T == int[]));
135 }
136 
137 /**
138 	 mixin a zero-parameter template
139 	(useful for mixing in templates from a list)
140 */
141 template Mixin (alias mix)
142 {
143 	mixin mix;
144 }