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