1 module d.common.builtintype;
2 
3 // Byte, Ubyte instead of Ubyte, Byte
4 enum BuiltinType : ubyte {
5 	None,
6 	Void,
7 	Bool,
8 	Char,
9 	Wchar,
10 	Dchar,
11 	Byte,
12 	Ubyte,
13 	Short,
14 	Ushort,
15 	Int,
16 	Uint,
17 	Long,
18 	Ulong,
19 	Cent,
20 	Ucent,
21 	Float,
22 	Double,
23 	Real,
24 	Null,
25 }
26 
27 string toString(BuiltinType t) {
28 	final switch (t) with (BuiltinType) {
29 		case None:
30 			return "__none__";
31 
32 		case Void:
33 			return "void";
34 
35 		case Bool:
36 			return "bool";
37 
38 		case Char:
39 			return "char";
40 
41 		case Wchar:
42 			return "wchar";
43 
44 		case Dchar:
45 			return "dchar";
46 
47 		case Byte:
48 			return "byte";
49 
50 		case Ubyte:
51 			return "ubyte";
52 
53 		case Short:
54 			return "short";
55 
56 		case Ushort:
57 			return "ushort";
58 
59 		case Int:
60 			return "int";
61 
62 		case Uint:
63 			return "uint";
64 
65 		case Long:
66 			return "long";
67 
68 		case Ulong:
69 			return "ulong";
70 
71 		case Cent:
72 			return "cent";
73 
74 		case Ucent:
75 			return "ucent";
76 
77 		case Float:
78 			return "float";
79 
80 		case Double:
81 			return "double";
82 
83 		case Real:
84 			return "real";
85 
86 		case Null:
87 			return "typeof(null)";
88 	}
89 }
90 
91 bool isChar(BuiltinType t) {
92 	return (t >= BuiltinType.Char) && (t <= BuiltinType.Dchar);
93 }
94 
95 BuiltinType integralOfChar(BuiltinType t) in {
96 	assert(isChar(t), "integralOfChar only applys to character types");
97 } do {
98 	return cast(BuiltinType) ((t * 2) | 0x01);
99 }
100 
101 unittest {
102 	assert(integralOfChar(BuiltinType.Char) == BuiltinType.Ubyte);
103 	assert(integralOfChar(BuiltinType.Wchar) == BuiltinType.Ushort);
104 	assert(integralOfChar(BuiltinType.Dchar) == BuiltinType.Uint);
105 }
106 
107 bool isIntegral(BuiltinType t) {
108 	return (t >= BuiltinType.Byte) && (t <= BuiltinType.Ucent);
109 }
110 
111 bool canConvertToIntegral(BuiltinType t) {
112 	return (t >= BuiltinType.Bool) && (t <= BuiltinType.Ucent);
113 }
114 
115 bool isSigned(BuiltinType t) in {
116 	assert(isIntegral(t), "isSigned only applys to integral types");
117 } do {
118 	return (t & 0x01) == 0;
119 }
120 
121 unittest {
122 	assert(isSigned(BuiltinType.Byte));
123 	assert(isSigned(BuiltinType.Short));
124 	assert(isSigned(BuiltinType.Int));
125 	assert(isSigned(BuiltinType.Long));
126 	assert(isSigned(BuiltinType.Cent));
127 
128 	assert(!isSigned(BuiltinType.Ubyte));
129 	assert(!isSigned(BuiltinType.Ushort));
130 	assert(!isSigned(BuiltinType.Uint));
131 	assert(!isSigned(BuiltinType.Ulong));
132 	assert(!isSigned(BuiltinType.Ucent));
133 }
134 
135 BuiltinType unsigned(BuiltinType t) in {
136 	assert(isIntegral(t), "unsigned only applys to integral types");
137 } do {
138 	return cast(BuiltinType) (t | 0x01);
139 }
140 
141 unittest {
142 	assert(unsigned(BuiltinType.Byte) == BuiltinType.Ubyte);
143 	assert(unsigned(BuiltinType.Ubyte) == BuiltinType.Ubyte);
144 
145 	assert(unsigned(BuiltinType.Short) == BuiltinType.Ushort);
146 	assert(unsigned(BuiltinType.Ushort) == BuiltinType.Ushort);
147 
148 	assert(unsigned(BuiltinType.Int) == BuiltinType.Uint);
149 	assert(unsigned(BuiltinType.Uint) == BuiltinType.Uint);
150 
151 	assert(unsigned(BuiltinType.Long) == BuiltinType.Ulong);
152 	assert(unsigned(BuiltinType.Ulong) == BuiltinType.Ulong);
153 
154 	assert(unsigned(BuiltinType.Cent) == BuiltinType.Ucent);
155 	assert(unsigned(BuiltinType.Ucent) == BuiltinType.Ucent);
156 }
157 
158 BuiltinType signed(BuiltinType t) in {
159 	assert(isIntegral(t), "signed only applys to integral types");
160 } do {
161 	return cast(BuiltinType) (t & ~0x01);
162 }
163 
164 unittest {
165 	assert(signed(BuiltinType.Byte) == BuiltinType.Byte);
166 	assert(signed(BuiltinType.Ubyte) == BuiltinType.Byte);
167 
168 	assert(signed(BuiltinType.Short) == BuiltinType.Short);
169 	assert(signed(BuiltinType.Ushort) == BuiltinType.Short);
170 
171 	assert(signed(BuiltinType.Int) == BuiltinType.Int);
172 	assert(signed(BuiltinType.Uint) == BuiltinType.Int);
173 
174 	assert(signed(BuiltinType.Long) == BuiltinType.Long);
175 	assert(signed(BuiltinType.Ulong) == BuiltinType.Long);
176 
177 	assert(signed(BuiltinType.Cent) == BuiltinType.Cent);
178 	assert(signed(BuiltinType.Ucent) == BuiltinType.Cent);
179 }
180 
181 bool isFloat(BuiltinType t) {
182 	return (t >= BuiltinType.Float) && (t <= BuiltinType.Real);
183 }
184 
185 uint getIntegralSize(BuiltinType t) in {
186 	assert(isIntegral(t), "getIntegralSize only apply to integral types");
187 } do {
188 	return 1 << ((t / 2) - 3);
189 }
190 
191 uint getSize(BuiltinType t) {
192 	final switch (t) with (BuiltinType) {
193 		case Bool:
194 			return 1;
195 
196 		case Char, Wchar, Dchar:
197 			return 1 << (t - Char);
198 
199 		case Byte, Ubyte, Short, Ushort, Int, Uint, Long, Ulong, Cent, Ucent:
200 			return getIntegralSize(t);
201 
202 		case Float, Double:
203 			return 1 << (t - Float + 2);
204 
205 		case None, Void, Real, Null:
206 			import std.conv;
207 			assert(0, "Use SizeofVisitor for " ~ t.to!string());
208 	}
209 }
210 
211 unittest {
212 	assert(getSize(BuiltinType.Bool) == 1);
213 	assert(getSize(BuiltinType.Byte) == 1);
214 	assert(getSize(BuiltinType.Ubyte) == 1);
215 	assert(getSize(BuiltinType.Char) == 1);
216 
217 	assert(getSize(BuiltinType.Short) == 2);
218 	assert(getSize(BuiltinType.Ushort) == 2);
219 	assert(getSize(BuiltinType.Wchar) == 2);
220 
221 	assert(getSize(BuiltinType.Int) == 4);
222 	assert(getSize(BuiltinType.Uint) == 4);
223 	assert(getSize(BuiltinType.Dchar) == 4);
224 	assert(getSize(BuiltinType.Float) == 4);
225 
226 	assert(getSize(BuiltinType.Long) == 8);
227 	assert(getSize(BuiltinType.Ulong) == 8);
228 	assert(getSize(BuiltinType.Double) == 8);
229 
230 	assert(getSize(BuiltinType.Cent) == 16);
231 	assert(getSize(BuiltinType.Ucent) == 16);
232 }
233 
234 uint getBits(BuiltinType t) {
235 	if (t == BuiltinType.Bool) {
236 		return 1;
237 	}
238 
239 	return getSize(t) * 8;
240 }
241 
242 unittest {
243 	assert(getBits(BuiltinType.Bool) == 1);
244 
245 	assert(getBits(BuiltinType.Byte) == 8);
246 	assert(getBits(BuiltinType.Ubyte) == 8);
247 	assert(getBits(BuiltinType.Char) == 8);
248 
249 	assert(getBits(BuiltinType.Short) == 16);
250 	assert(getBits(BuiltinType.Ushort) == 16);
251 	assert(getBits(BuiltinType.Wchar) == 16);
252 
253 	assert(getBits(BuiltinType.Int) == 32);
254 	assert(getBits(BuiltinType.Uint) == 32);
255 	assert(getBits(BuiltinType.Dchar) == 32);
256 	assert(getBits(BuiltinType.Float) == 32);
257 
258 	assert(getBits(BuiltinType.Long) == 64);
259 	assert(getBits(BuiltinType.Ulong) == 64);
260 	assert(getBits(BuiltinType.Double) == 64);
261 
262 	assert(getBits(BuiltinType.Cent) == 128);
263 	assert(getBits(BuiltinType.Ucent) == 128);
264 }
265 
266 ulong getMax(BuiltinType t) in {
267 	assert(isIntegral(t), "getMax only applys to integral types");
268 } do {
269 	auto base = 1UL << (8 - isSigned(t));
270 	return (base << (getIntegralSize(t) - 1) * 8) - 1;
271 }
272 
273 unittest {
274 	assert(getMax(BuiltinType.Byte) == 127);
275 	assert(getMax(BuiltinType.Ubyte) == 255);
276 
277 	assert(getMax(BuiltinType.Short) == 32767);
278 	assert(getMax(BuiltinType.Ushort) == 65535);
279 
280 	assert(getMax(BuiltinType.Int) == 2147483647);
281 	assert(getMax(BuiltinType.Uint) == 4294967295);
282 
283 	assert(getMax(BuiltinType.Long) == 9223372036854775807);
284 	assert(getMax(BuiltinType.Ulong) == 18446744073709551615UL);
285 }
286 
287 ulong getMin(BuiltinType t) in {
288 	assert(isIntegral(t), "getMin only applys to integral types");
289 } do {
290 	return isSigned(t) ? -(1UL << getIntegralSize(t) * 8 - 1) : 0;
291 }
292 
293 unittest {
294 	assert(getMin(BuiltinType.Ubyte) == 0);
295 	assert(getMin(BuiltinType.Ushort) == 0);
296 	assert(getMin(BuiltinType.Uint) == 0);
297 	assert(getMin(BuiltinType.Ulong) == 0);
298 	assert(getMin(BuiltinType.Ucent) == 0);
299 
300 	assert(getMin(BuiltinType.Byte) == -128);
301 	assert(getMin(BuiltinType.Short) == -32768);
302 	assert(getMin(BuiltinType.Int) == -2147483648);
303 	assert(getMin(BuiltinType.Long) == -9223372036854775808UL);
304 }
305 
306 dchar getCharInit(BuiltinType t) in {
307 	assert(isChar(t), "getCharInit only applys to character types");
308 } do {
309 	switch (t) with (BuiltinType) {
310 		case Char:
311 			return '\xff';
312 
313 		case Wchar, Dchar:
314 			return cast(dchar) 0xffff;
315 
316 		default:
317 			assert(0, "getCharInit only applys to character types");
318 	}
319 }
320 
321 unittest {
322 	assert(getCharInit(BuiltinType.Char) == '\xff');
323 	assert(getCharInit(BuiltinType.Wchar) == 0xffff);
324 	assert(getCharInit(BuiltinType.Dchar) == 0xffff);
325 }
326 
327 dchar getCharMax(BuiltinType t) in {
328 	assert(isChar(t), "getCharMax only applys to character types");
329 } do {
330 	switch (t) with (BuiltinType) {
331 		case Char:
332 			return '\xff';
333 
334 		case Wchar:
335 			return cast(dchar) 0xffff;
336 
337 		case Dchar:
338 			return cast(dchar) 0x10ffff;
339 
340 		default:
341 			assert(0, "getCharMax only applys to character types");
342 	}
343 }
344 
345 unittest {
346 	assert(getCharMax(BuiltinType.Char) == '\xff');
347 	assert(getCharMax(BuiltinType.Wchar) == 0xffff);
348 	assert(getCharMax(BuiltinType.Dchar) == 0x10ffff);
349 }