1 module yyd.y;
2 
3 private import std.meta : AliasSeq;
4 
5 // Functional combinators
6 
7 /** 
8  * Identity
9  * Params:
10  *   identity = 
11  */
12 mixin template _identity(alias T) 
13 {
14     alias _ = T;
15 }
16 
17 mixin template _identity(alias T,U...) 
18 {
19     alias _ = T!U;
20 }
21 
22 template identity(alias T) 
23 {
24     alias identity = T;
25 }
26 
27 auto ref identity(T)(inout ref T t) 
28 {
29     return t;
30 }
31 
32 mixin template _evaluate(alias T=identity) 
33 {
34     enum _ = T;
35 }
36 
37 template evaluate(alias T=identity) 
38 {
39     enum evaluate = T;
40 }
41 
42 
43 /**
44  * Decombinators.
45  * These restore the original value where _ has been used as a replacement for eponymosity.
46  */
47 
48 /*mixin template __y()
49 {
50     static if(is(typeof(_))) {
51         alias _ = _;
52     } else {
53     }
54 }*/
55 /*
56 template _y(alias T, V ...)
57 {
58     static if(is(typeof(T._))) {
59         static if(
60                 is(typeof(T._.length))
61         ) { // check if it's AliasSeq
62             alias _y = T._;
63         } else static if(
64                 __traits(isTemplate,T._)
65         ) {
66             //mixin T!() _;
67             //alias _y = _y!(_);
68             //alias _y = _y!(T._!(V),V);
69             //static if (V.length == len) {
70                 alias _y = _y!(T._!(V));
71             //} else {
72             //    alias _y = _y!(T._!(V[0..len]),V[len..$]);
73             //}
74         } else {
75             alias _y = _y!(T._,V);
76         }
77     } else {
78         alias _y = T;
79     }
80 }
81 */
82 
83 template _y(alias T)
84 {
85     static if(is(typeof(T._))) {
86         alias _y = T._;
87     } else {
88         // TODO check for eponymous template. The symbol would have a member with the same name as it's identifier.
89         alias _y = T;
90     }
91 }
92 
93 /**
94  * Decombinator and instatiate T as template with given parameters V.
95  */
96 template _yy(alias T,V...) 
97 {
98     static if(is(typeof(T._))) {
99         alias _yy = _y!(T._!(V));
100     } else {
101         alias _yy = _y!(T!(V));
102     }
103 }
104 /**
105  * Same as _yy but instiate as mixin.
106  */
107 mixin template _yyy(alias T,V...) 
108 {
109     static if(is(typeof(T._))) {
110         mixin T._!(V);
111     } else {
112         mixin T!(V);
113     }
114 }
115 
116 /*mixin template _yy_(alias T)
117 {
118     static if(is(typeof(T._))) {
119         alias _ ( V ... ) = () {
120             mixin T._!V;
121         };
122     } else {
123         alias _ (V ... ) = () {
124             mixin T!V;
125         };
126     }
127 }*/
128 
129 /**
130  * Create an alias to the instantiation of template T with parameters U
131  */
132 mixin template _apply(alias T=identity,U...) 
133 {
134     template _ () 
135     {
136         alias _ = T!U;
137     }
138 }
139 
140 /**
141  * Create an alias template that instantiates template T with a passed in argument.
142  */
143 mixin template _call(alias T=identity) 
144 {
145     alias _ (U...) = (U u) => T!u;
146 }
147 
148 /**
149  * Create a template _ to form a "partial" version of a mixin template T with the first part of the 
150  * supplied argument list, and the remainder as parameters to the created template.
151  */
152 mixin template _partialm(alias T=_identity,U...) 
153 {
154     template _ (V...) 
155     {
156         mixin T!(U,V) _;
157     }
158 }
159 
160 /**
161  * Create a template _ to form a "partial" version of template T with the last part of the 
162  * supplied argument list, and the preceding parts as parameters to the created template.
163  */
164 mixin template _rpartialm(alias T=_identity,U ...) 
165 {
166     template _ (V ...) 
167     {
168         mixin T!(V,U) _;
169     }
170 }
171 
172 /**
173  * Same as _partial but creates a mixin template.
174  */
175 mixin template _mpartial(alias T=identity, U ...) 
176 {
177     mixin template _ (V ...) 
178     {
179         alias _ = T!(U,V);
180     }
181 }
182 
183 /**
184  * Create an alias template that is a partial version of template T with the first 
185  * part of the argument list supplied as parameter U... and the remainder as 
186  * parameters to the created template _ .
187  */
188 mixin template _partial(alias T=identity, U ...) 
189 {
190     template _ (V ...) 
191     {
192         alias _ = T!(U,V);
193     }
194 }
195 
196 mixin template _rpartial(alias T=_identity,U...) 
197 {
198     template _ (V ...) 
199     {
200         alias _ = T!(V,U);
201     }
202 }
203 
204 /*
205 mixin template _partialf(alias T,U...) 
206 {
207     alias _(V...) = (V v) => T(U,v);
208 }
209 
210 mixin template _rpartialf(alias T,U...) {
211     alias _(V ...) = (V v) => T(v.U);
212 }
213 */
214 
215 mixin template _partialf(alias T=identity,U...) 
216 {
217     auto _ (V ...) (V v) 
218     {
219        return T(U,v);
220     }
221     //alias _ (V ...) = (V v) => T(U,v);
222 }
223 
224 mixin template _rpartialf(alias T=identity,U...) 
225 {
226     auto _ (V ...) (V v) 
227     {
228         return T(v,U);
229     }
230     //alias _ (V ...) = (V v) => T(v,U);
231 }
232 
233 mixin template _partialmf(alias T=identity,U...) 
234 {
235     auto _ (V ...) (V v) 
236     {
237        mixin T!(U,v) _;
238        return _y!_;
239     }
240     //alias _ (V ...) = (V v) => T(U,v);
241 }
242 
243 mixin template _rpartialmf(alias T=identity,U...) 
244 {
245     auto _ (V ...) (V v) 
246     {
247         mixin T!(v,U) _;
248         return _y!_;
249     }
250     //alias _ (V ...) = (V v) => T(v,U);
251 }
252 
253 
254 unittest {
255     auto t1(string A,string B,string C)() {
256         return A ~ B ~ C;
257     }
258 
259     mixin _partial!(t1,"First ","second ") p;
260     //enum result = _y!(p,"third");
261     enum result = p._!"third";
262 
263     static assert (result == "First second third");
264 }
265 
266 unittest {
267     auto t1(string A,string B,string C)() {
268         return A ~ B ~ C;
269     }
270 
271     mixin _rpartial!(t1,"First ","second") p;
272     //enum result = _y!(p,"third ");
273     enum result = _yy!(p,"third ");
274 
275     static assert (result == "third First second");
276 }
277 
278 unittest {
279     template t1(string A,string B,string C) {
280         enum t1 = A ~ B ~ C;
281     }
282 
283     mixin _partial!(t1,"First ") p;
284     //mixin _partial!(_y!(p,"second ")) q;
285     mixin _partial!(p._,"second ") q;
286     //enum result = q._!("third");
287     enum result = _yy!(q,"third");
288 
289     static assert (result == "First second third");
290 }
291 
292 unittest {
293     template t1(string A,string B,string C) {
294         enum t1 = A ~ B ~ C;
295     }
296 
297     mixin _partial!(t1,"First ") p;
298     mixin _partial!(p._,"second ") _p;
299     mixin _apply!(_p._,"third") _q;
300     //enum result = _q._!();
301     enum result = _yy!(_q);
302 
303     static assert (result == "First second third");
304 }
305 
306 unittest {
307     auto t1(string A,string B,string C) {
308         return A ~ B ~ C;
309     }
310 
311     mixin _partialf!(t1,"First ") p;
312     //mixin _partialf!(p._,"second ") _p;
313     mixin _partialf!(_y!p,"second ") _p;
314     //enum result = _p._("third");
315     enum result = _y!(_p)("third");
316 
317     static assert (result == "First second third");
318 }
319 
320 /**
321  * Embed a template into a lambda.
322  */
323 template toFnc(alias op,V ...) 
324 {
325 	alias toFnc(T...) = (V v)=>op!T(v);
326 }
327 
328 /**
329  * Mxin template decombinator into lambda.
330  */
331 mixin template y__(alias op) 
332 {
333 	alias _ = () {
334 		mixin op!(T) _;
335         return y!(_);
336 	};
337 }
338 
339 template y_ (alias T) {
340     alias y_() = ()=>T!v;
341 }
342 
343 mixin template _toFnc(alias op)
344 {
345 	alias _ = toFnc!op;
346 }
347 
348 mixin template _toFnc_m(alias op, V ...)
349 {
350     mixin toFnc_m!(op,V) _;
351 	//alias _ = toFnc_m!(op,V);
352 }
353 
354