]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | // NOTE: comes from std.bitmanip |
2 | ||
3 | // PERMUTE_ARGS: | |
4 | ||
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 | ||
12 | private string toStringSfx(ulong n) | |
13 | { | |
14 | return myToString(n) ~ (n > uint.max ? "UL" : "U"); | |
15 | } | |
16 | ||
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 " | |
7da827c9 | 39 | ~ "("~store~" & "~toStringSfx(maskAllElse)~") != 0;}"; |
b4c522fa IB |
40 | // setter |
41 | result ~= "void " ~ name ~ "(bool v){" | |
7da827c9 IB |
42 | ~ "if (v) "~store~" |= "~toStringSfx(maskAllElse)~";" |
43 | ~ "else "~store~" &= "~toStringSfx(maskMyself)~";}"; | |
b4c522fa IB |
44 | } |
45 | else | |
46 | { | |
47 | // getter | |
48 | result ~= T.stringof ~ " " ~ name ~ "(){ auto result = " | |
7da827c9 | 49 | ~ "("~store~" & " |
b4c522fa IB |
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 | ||
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 | ||
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 | ||
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 | ||
122 | struct Bug2355(string x) {} | |
123 | static assert(is(Bug2355!"a" U : Bug2355!V, string V)); | |
124 | ||
125 | int main() | |
126 | { | |
127 | return 0; | |
128 | } |