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 }