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