1 /// 2 module rxd.meta2.closure; 3 4 import rxd.meta2.traits : isEnumValue; 5 6 struct Closure(Args...) 7 { 8 pragma (msg, "In Closure template: ", Args.stringof); 9 10 enum gennedCode = genArgsAliases!Args("Args"); 11 pragma (msg, gennedCode); 12 mixin (gennedCode); 13 14 alias use = typeof(this); 15 private alias __my__args__ = Args; 16 } 17 18 /// 19 unittest 20 { 21 struct Point { float x, y; } 22 23 int a = 34; 24 Point b = { 3, 4 }; 25 int c = 32; 26 enum d = 42; 27 28 auto inner = Closure!(c, d)(); 29 auto outer = Closure!(inner, a, b)(); 30 31 static assert (inner.sizeof >= (void*).sizeof); 32 static assert (outer.sizeof >= (void*).sizeof); 33 34 assert (inner.c == 32); 35 assert (outer.a == 34); 36 assert (outer.b == Point(3, 4)); 37 assert (outer.c == 32); 38 39 outer.a++; 40 assert (a == 35); 41 assert (outer.a == 35); 42 43 outer.c++; 44 assert (c == 33); 45 assert (inner.c == 33); 46 assert (outer.c == 33); 47 48 void someFunc(C)(C closure) 49 { 50 assert (closure.a == 35); 51 52 with (closure) 53 assert (a == 35); 54 55 int local = 85; 56 auto ctx = Closure!(closure, local)(); 57 58 assert (ctx.local == 85); 59 assert (ctx.a == 35); 60 } 61 62 someFunc(outer); 63 } 64 65 private string genArgsAliases(Args...)(string prefix = "Args") 66 { 67 //enum string prefix = "Args"; 68 69 import std.conv : to; 70 import std.format : format; 71 import std.typecons : staticIota; 72 string res; 73 74 pragma (msg, "In genArgsAliases -> ", Args.stringof); 75 76 string genAliasFunc(string name, string start, size_t idx) 77 { 78 //pragma (msg, "In genAliasFunc -> name: ", name, " start: ", start, 79 // " idx: ", idx); 80 81 return (" auto ref __get__%1$s() { return %2$s[%3$s]; }\n" ~ 82 " alias %1$s = __get__%1$s;\n") 83 .format(name, start, idx); 84 } 85 86 foreach (idx; staticIota!(0, Args.length)) 87 static if (isEnumValue!(Args[idx])) 88 res ~= " enum %s = %s[%s];\n" 89 .format(__traits(identifier, Args[idx]), prefix, idx); 90 91 else static if (is(typeof(Args[idx]) : Closure!U, U...)) 92 res ~= genArgsAliases!(Args[idx].__my__args__)( 93 "%s[%s].__my__args__".format(prefix, idx)); 94 95 else 96 res ~= genAliasFunc(Args[idx].stringof, prefix, idx); 97 98 return res; 99 }