1 // NOTE: comes from std.bitmanip
2 
3 // PERMUTE_ARGS:
4 
myToString(ulong n)5 private string myToString(ulong n)
6 {
7     return n < 10
8         ? "" ~ cast(char) (n + '0')
9         : myToString(n / 10) ~ myToString(n % 10);
10 }
11 
toStringSfx(ulong n)12 private string toStringSfx(ulong n)
13 {
14     return myToString(n) ~ (n > uint.max ? "UL" : "U");
15 }
16 
CreateAccessors(string store,T,string name,size_t len,size_t offset)17 private string CreateAccessors(
18     string store, T, string name, size_t len, size_t offset)()
19 {
20     static if (!name.length)
21     {
22         // No need to create any accessor
23         return "";
24     }
25     else
26     {
27         static const
28             maskAllElse = ((1uL << len) - 1u) << offset,
29             maskMyself = ~maskAllElse,
30             signBitCheck = 1uL << (len - 1),
31             extendSign = ~((1uL << len) - 1);
32 
33         string result;
34         static if (is(T == bool))
35         {
36             static assert(len == 1);
37             // getter
38             result ~= "bool " ~ name ~ "(){ return "
39                 "("~store~" & "~toStringSfx(maskAllElse)~") != 0;}";
40             // setter
41             result ~= "void " ~ name ~ "(bool v){"
42                 "if (v) "~store~" |= "~toStringSfx(maskAllElse)~";"
43                 "else "~store~" &= "~toStringSfx(maskMyself)~";}";
44         }
45         else
46         {
47             // getter
48             result ~= T.stringof ~ " " ~ name ~ "(){ auto result = "
49                 "("~store~" & "
50                 ~ toStringSfx(maskAllElse) ~ ") >>"
51                 ~ toStringSfx(offset) ~ ";";
52             static if (T.min < 0)
53             {
54                 result ~= "if (result >= " ~ toStringSfx(signBitCheck)
55                     ~ ") result |= " ~ toStringSfx(extendSign) ~ ";";
56             }
57             result ~= " return cast(" ~ T.stringof ~ ") result;}";
58             // setter
59             result ~= "void " ~ name ~ "(" ~ T.stringof
60                 ~ " v){ "~store~" = ("~store~" & "
61                 ~ toStringSfx(maskMyself) ~ ") | "
62                 ~ "((cast(typeof("~store~")) v << " ~ toStringSfx(offset)
63                 ~ ") & " ~ toStringSfx(maskAllElse)
64                 ~ ");}";
65         }
66         return result;
67     }
68 }
69 
createStoreName(Ts...)70 private string createStoreName(Ts...)()
71 {
72     static if (Ts.length == 0)
73         return "";
74     else
75         return Ts[1] ~ createStoreName!(Ts[3 .. $])();
76 }
77 
CreateFields(string store,size_t offset,Ts...)78 private string CreateFields(string store, size_t offset, Ts...)()
79 {
80     static if (!Ts.length)
81     {
82         static if (offset == ubyte.sizeof * 8)
83             return "private ubyte " ~ store ~ ";";
84         else static if (offset == ushort.sizeof * 8)
85             return "private ushort " ~ store ~ ";";
86         else static if (offset == uint.sizeof * 8)
87             return "private uint " ~ store ~ ";";
88         else static if (offset == ulong.sizeof * 8)
89             return "private ulong " ~ store ~ ";";
90         else
91             static assert(false, ToString!(offset));
92     }
93     else
94     {
95         return CreateAccessors!(store, Ts[0], Ts[1], Ts[2], offset)()
96             ~ CreateFields!(store, offset + Ts[2], Ts[3 .. $])();
97     }
98 }
99 
BitFields(T...)100 template BitFields(T...)
101 {
102     //pragma(msg, CreateFields!(createStoreName!(T)(), 0, T)());
103     mixin(CreateFields!(createStoreName!(T)(), 0, T)());
104 }
105 
106 struct FloatRep
107 {
108     mixin BitFields!(
109         uint, "fraction", 23,
110         uint, "exponent", 8,
111         bool, "sign", 1);
112 }
113 
114 struct DoubleRep
115 {
116     mixin BitFields!(
117         ulong, "fraction", 52,
118         uint, "exponent", 11,
119         bool, "sign", 1);
120 }
121 
Bug2355(string x)122 struct Bug2355(string x) {}
123 static assert(is(Bug2355!"a" U : Bug2355!V, string V));
124 
main()125 int main()
126 {
127     return 0;
128 }
129