1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 module vox.fe.ast.type.basic; 5 6 import vox.all; 7 8 @(AstType.type_basic) 9 struct BasicTypeNode { 10 mixin AstNodeData!(AstType.type_basic, AstFlags.isType, AstNodeState.type_check_done); 11 AstIndex type = CommonAstNodes.type_type; 12 SizeAndAlignment sizealign; 13 ulong minValue; 14 ulong maxValue; 15 BasicType basicType; 16 ubyte typeFlags; 17 TypeNode* typeNode() return { return cast(TypeNode*)&this; } 18 string strId() { return basicTypeNames[basicType]; } 19 20 bool isFloat() { return cast(bool)(typeFlags & BasicTypeFlag.isFloat); } 21 bool isInteger() { return cast(bool)(typeFlags & BasicTypeFlag.isInteger); } 22 IsSigned isSigned() { return cast(IsSigned)cast(bool)(typeFlags & BasicTypeFlag.isSigned); } 23 bool isBoolean() { return cast(bool)(typeFlags & BasicTypeFlag.isBoolean); } 24 bool isAlias() { return basicType == BasicType.t_alias; } 25 bool isType() { return basicType == BasicType.t_type; } 26 27 IrIndex gen_init_value(CompilationContext* c) 28 { 29 switch(basicType) 30 { 31 case BasicType.t_error: return c.constants.addZeroConstant(makeIrType(IrBasicType.i8)); 32 case BasicType.t_bool: return c.constants.addZeroConstant(makeIrType(IrBasicType.i8)); 33 case BasicType.t_u8: return c.constants.addZeroConstant(makeIrType(IrBasicType.i8)); 34 case BasicType.t_i8: return c.constants.addZeroConstant(makeIrType(IrBasicType.i8)); 35 case BasicType.t_i16: return c.constants.addZeroConstant(makeIrType(IrBasicType.i16)); 36 case BasicType.t_u16: return c.constants.addZeroConstant(makeIrType(IrBasicType.i16)); 37 case BasicType.t_i32: return c.constants.addZeroConstant(makeIrType(IrBasicType.i32)); 38 case BasicType.t_u32: return c.constants.addZeroConstant(makeIrType(IrBasicType.i32)); 39 case BasicType.t_i64: return c.constants.addZeroConstant(makeIrType(IrBasicType.i64)); 40 case BasicType.t_u64: return c.constants.addZeroConstant(makeIrType(IrBasicType.i64)); 41 case BasicType.t_f32: return c.constants.addZeroConstant(makeIrType(IrBasicType.f32)); 42 case BasicType.t_f64: return c.constants.addZeroConstant(makeIrType(IrBasicType.f64)); 43 case BasicType.t_alias: return c.constants.addZeroConstant(makeIrType(IrBasicType.i32)); 44 case BasicType.t_type: return c.constants.addZeroConstant(makeIrType(IrBasicType.i32)); 45 default: c.internal_error(loc, "Cannot convert %s to IrIndex", basicType); 46 } 47 } 48 } 49 50 enum NumBasicTypeNodeSlots = 12; 51 52 enum BasicTypeFlag : ubyte { 53 isFloat = 1 << 0, 54 isInteger = 1 << 1, 55 isSigned = 1 << 2, 56 isBoolean = 1 << 3, 57 } 58 59 void print_type_basic(BasicTypeNode* node, ref AstPrintState state) 60 { 61 state.print("TYPE ", node.typeNode.printer(state.context)); 62 } 63 64 IrIndex gen_ir_type_basic(BasicTypeNode* t, CompilationContext* context) 65 out(res; res.isTypeBasic, "Not a basic type") 66 { 67 switch(t.basicType) 68 { 69 case BasicType.t_noreturn: return makeIrType(IrBasicType.noreturn_t); 70 case BasicType.t_void: return makeIrType(IrBasicType.void_t); 71 case BasicType.t_bool: return makeIrType(IrBasicType.i8); 72 case BasicType.t_null: return makeIrType(IrBasicType.i64); 73 case BasicType.t_u8: return makeIrType(IrBasicType.i8); 74 case BasicType.t_i8: return makeIrType(IrBasicType.i8); 75 case BasicType.t_i16: return makeIrType(IrBasicType.i16); 76 case BasicType.t_u16: return makeIrType(IrBasicType.i16); 77 case BasicType.t_i32: return makeIrType(IrBasicType.i32); 78 case BasicType.t_u32: return makeIrType(IrBasicType.i32); 79 case BasicType.t_i64: return makeIrType(IrBasicType.i64); 80 case BasicType.t_u64: return makeIrType(IrBasicType.i64); 81 case BasicType.t_f32: return makeIrType(IrBasicType.f32); 82 case BasicType.t_f64: return makeIrType(IrBasicType.f64); 83 case BasicType.t_alias: return makeIrType(IrBasicType.i32); 84 case BasicType.t_type: return makeIrType(IrBasicType.i32); 85 default: 86 context.internal_error(t.loc, "Cannot convert %s to IrIndex", t.basicType); 87 } 88 } 89 90 // leftExpr, rightExpr can be null 91 CommonTypeResult common_type_basic(BasicTypeNode* node, AstIndex typeBIndex, AstIndex leftExpr, AstIndex rightExpr, CompilationContext* c) 92 { 93 BasicType basicA = node.basicType; 94 TypeNode* typeB = typeBIndex.get_type(c); 95 switch(typeB.astType) with(AstType) 96 { 97 case type_basic: 98 BasicType basicB = typeB.as_basic.basicType; 99 BasicType commonType = commonBasicType[basicA][basicB]; 100 TypeConvResKind kindA = basicConversionKind[basicA][commonType]; 101 TypeConvResKind kindB = basicConversionKind[basicB][commonType]; 102 auto res = CommonTypeResult(c.basicTypeNodes(commonType), kindA, kindB); 103 104 if (leftExpr.isDefined && rightExpr.isDefined) { 105 auto leftExprNode = leftExpr.get_node(c); 106 auto rightExprNode = rightExpr.get_node(c); 107 if (leftExprNode.astType == AstType.literal_int) 108 { 109 if (rightExprNode.astType == AstType.literal_int) return res; 110 111 if (typeB.isInteger) 112 { 113 ubyte toSize = integerSize(basicB); 114 auto lit = leftExprNode.as!IntLiteralExprNode(c); 115 if (lit.isSigned) { 116 if (numSignedBytesForInt(lit.value) <= toSize) 117 return CommonTypeResult(c.basicTypeNodes(basicB), TypeConvResKind.override_expr_type_i, TypeConvResKind.no_i); 118 } else { 119 if (numUnsignedBytesForInt(lit.value) <= toSize) 120 return CommonTypeResult(c.basicTypeNodes(basicB), TypeConvResKind.override_expr_type_i, TypeConvResKind.no_i); 121 } 122 } 123 } 124 if (rightExprNode.astType == AstType.literal_int) { 125 if (node.isInteger) 126 { 127 ubyte toSize = integerSize(basicA); 128 auto lit = rightExprNode.as!IntLiteralExprNode(c); 129 if (lit.isSigned) { 130 if (numSignedBytesForInt(lit.value) <= toSize) 131 return CommonTypeResult(c.basicTypeNodes(basicA), TypeConvResKind.no_i, TypeConvResKind.override_expr_type_i); 132 } else { 133 if (numUnsignedBytesForInt(lit.value) <= toSize) 134 return CommonTypeResult(c.basicTypeNodes(basicA), TypeConvResKind.no_i, TypeConvResKind.override_expr_type_i); 135 } 136 } 137 } 138 } 139 return res; 140 case type_ptr: 141 if (basicA == BasicType.t_null) { 142 return CommonTypeResult(typeBIndex, TypeConvResKind.override_expr_type_i, TypeConvResKind.no_i); 143 } 144 return CommonTypeResult(CommonAstNodes.type_error); 145 default: assert(false); 146 } 147 } 148 149 TypeConvResKind type_conv_basic(BasicTypeNode* node, AstIndex typeBIndex, ref AstIndex expr, CompilationContext* c) 150 { 151 BasicType fromTypeBasic = node.basicType; 152 TypeNode* typeTo = typeBIndex.get_type(c); 153 154 switch(typeTo.astType) with(AstType) 155 { 156 case type_basic: 157 auto res = basicConversionKind[fromTypeBasic][typeTo.as_basic.basicType]; 158 auto exprNode = expr.get_node(c); 159 switch(exprNode.astType) { 160 case AstType.literal_int: 161 if (typeTo.isInteger) 162 { 163 ubyte toSize = integerSize(typeTo.as_basic.basicType); 164 auto lit = exprNode.as!IntLiteralExprNode(c); 165 if (lit.isSigned) { 166 if (numSignedBytesForInt(lit.value) <= toSize) return TypeConvResKind.override_expr_type_i; 167 } else { 168 if (numUnsignedBytesForInt(lit.value) <= toSize) return TypeConvResKind.override_expr_type_i; 169 } 170 } 171 return res; 172 case AstType.literal_float: 173 if (typeTo.isFloat) return TypeConvResKind.ff_i; 174 return res; 175 default: return res; 176 } 177 case type_ptr: 178 if (fromTypeBasic == BasicType.t_null) return TypeConvResKind.override_expr_type_i; 179 if (fromTypeBasic.isInteger) return TypeConvResKind.ii_e; 180 return TypeConvResKind.fail; 181 case type_slice: 182 if (fromTypeBasic == BasicType.t_null) return TypeConvResKind.override_expr_type_i; 183 return TypeConvResKind.fail; 184 case decl_enum: 185 auto res1 = type_conv_basic(node, typeTo.as_enum.memberType, expr, c); 186 auto res2 = res1.allowExplicitOnly; 187 //writefln("type_conv_basic %s %s %s %s", fromTypeBasic, printer(typeTo.as_enum.memberType, c), res1, res2); 188 return res2; 189 default: return TypeConvResKind.fail; 190 } 191 } 192 193 // The order is the same as in TokenType enum, CommonAstNodes enum, basicTypesArray, basicTypeNames 194 enum BasicType : ubyte { 195 t_error, 196 t_auto, 197 t_noreturn, 198 t_void, 199 t_bool, 200 t_null, 201 202 t_i8, 203 t_i16, 204 t_i32, 205 t_i64, 206 207 t_u8, 208 t_u16, 209 t_u32, 210 t_u64, 211 212 t_f32, 213 t_f64, 214 215 // meta types 216 t_alias, 217 t_type, 218 //t_value, 219 } 220 221 bool isInteger(BasicType b) { 222 return b >= BasicType.t_i8 && b <= BasicType.t_u64; 223 } 224 ubyte integerSize(BasicType b) { 225 switch(b) with(BasicType) { 226 case t_i8, t_u8: return 1; 227 case t_i16, t_u16: return 2; 228 case t_i32, t_u32: return 4; 229 case t_i64, t_u64: return 8; 230 default: return 0; 231 } 232 } 233 bool isSignedInteger(BasicType b) { 234 return b >= BasicType.t_i8 && b <= BasicType.t_i64; 235 } 236 bool isUnsignedInteger(BasicType b) { 237 return b >= BasicType.t_u8 && b <= BasicType.t_u64; 238 } 239 bool isFloat(BasicType b) { 240 return b == BasicType.t_f32 || b == BasicType.t_f64; 241 } 242 bool isBoolean(BasicType b) { 243 return b == BasicType.t_bool; 244 } 245 246 // 0b_000_0 247 // ^ 248 // | 0 e 0 explicit conversion only 249 // ` 1 i 1 explicit and implicit conversion allowed 250 enum TypeConvResKind : ubyte { 251 fail = 0b_000_0, // cannot convert 252 no_e = 0b_001_0, // noop, explicit conversion only 253 no_i = 0b_001_1, // noop, explicit and implicit conversion allowed 254 255 ii_e = 0b_010_0, // i to i explicit conversion only 256 ii_i = 0b_010_1, // i to i explicit and implicit conversion allowed 257 if_e = 0b_011_0, // i to f explicit conversion only 258 if_i = 0b_011_1, // i to f explicit and implicit conversion allowed 259 ff_e = 0b_100_0, // f to f explicit conversion only 260 ff_i = 0b_100_1, // f to f explicit and implicit conversion allowed 261 fi_e = 0b_101_0, // f to i explicit conversion only 262 fi_i = 0b_101_1, // f to i explicit and implicit conversion allowed 263 264 override_expr_type_e = 0b_110_0, 265 override_expr_type_i = 0b_110_1, 266 267 string_literal_to_u8_ptr = 0b_111_0, 268 array_literal_to_slice = 0b_111_1, 269 } 270 271 bool isNoop(TypeConvResKind kind) { return (kind & 0b_111_0) == TypeConvResKind.no_e; } 272 bool successful(TypeConvResKind kind) { return kind != TypeConvResKind.fail; } 273 bool canConvertImplicitly(TypeConvResKind kind) { 274 return (kind & 1) == 1 || kind >= TypeConvResKind.string_literal_to_u8_ptr; } 275 TypeConvResKind allowExplicitOnly(TypeConvResKind kind) { 276 if (kind >= TypeConvResKind.string_literal_to_u8_ptr) return kind; 277 return cast(TypeConvResKind)(kind & 0b_111_0); 278 } 279 280 // usage basicConversionKind[from][to] 281 immutable TypeConvResKind[BasicType.max + 1][BasicType.max + 1] basicConversionKind = (){ with(TypeConvResKind){ return [ 282 //err auto nret void bool null i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 $alias $type // to 283 [no_i,fail,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i, no_i, no_i], // from error 284 [fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, fail, fail], // from auto 285 [no_i,fail,fail,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i, fail, fail], // from noreturn 286 [no_i,fail,fail,no_i,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, fail, fail], // from void 287 [no_i,fail,fail,fail,no_i,fail,ii_i,ii_i,ii_i,ii_i,ii_i,ii_i,ii_i,ii_i,if_i,if_i, fail, fail], // from bool 288 [no_i,fail,fail,fail,ii_i,no_i,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,fail,fail, fail, fail], // from null 289 [no_i,fail,fail,fail,ii_i,fail,no_i,ii_i,ii_i,ii_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i8 290 [no_i,fail,fail,fail,ii_i,fail,ii_e,no_i,ii_i,ii_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i16 291 [no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,no_i,ii_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i32 292 [no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_e,no_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i64 293 [no_i,fail,fail,fail,ii_i,fail,ii_e,ii_i,ii_i,ii_i,no_i,ii_i,ii_i,ii_i,if_i,if_i, fail, fail], // from u8 294 [no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_i,ii_i,ii_e,no_i,ii_i,ii_i,if_i,if_i, fail, fail], // from u16 295 [no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_e,ii_i,ii_e,ii_e,no_i,ii_i,if_i,if_i, fail, fail], // from u32 296 [no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,no_i,if_i,if_i, fail, fail], // from u64 297 [no_i,fail,fail,fail,ii_i,fail,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,no_i,ff_i, fail, fail], // from f32 298 [no_i,fail,fail,fail,ii_i,fail,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,ff_e,no_i, fail, fail], // from f64 299 [no_i,fail,fail,fail,ii_i,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, no_i, fail], // from $alias 300 [no_i,fail,fail,fail,ii_i,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, ii_i, no_i], // from $type 301 ]; } 302 }(); 303 304 immutable BasicType[BasicType.max + 1][BasicType.max + 1] commonBasicType = (){ with(BasicType){ return [ 305 // error auto noreturn void bool null i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 $alias $type 306 [t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error], // error 307 [t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error], // auto 308 [t_error, t_error,t_noreturn,t_error,t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error], // noreturn 309 [t_error, t_error, t_error, t_void, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_alias, t_type ], // void 310 [t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_alias, t_type ], // bool 311 [t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_alias, t_type ], // null 312 [t_error, t_error, t_error, t_error, t_error, t_error, t_i8, t_i16, t_i32, t_i64, t_i8, t_i16, t_i32, t_i64, t_f32, t_f64, t_alias, t_type ], // i8 313 [t_error, t_error, t_error, t_error, t_error, t_error, t_i16, t_i16, t_i32, t_i64, t_i16, t_i16, t_i32, t_i64, t_f32, t_f64, t_alias, t_type ], // i16 314 [t_error, t_error, t_error, t_error, t_error, t_error, t_i32, t_i32, t_i32, t_i64, t_i32, t_i32, t_i32, t_i64, t_f32, t_f64, t_alias, t_type ], // i32 315 [t_error, t_error, t_error, t_error, t_error, t_error, t_i64, t_i64, t_i64, t_i64, t_i64, t_i64, t_i64, t_i64, t_f32, t_f64, t_alias, t_type ], // i64 316 [t_error, t_error, t_error, t_error, t_error, t_error, t_i8, t_i16, t_i32, t_i64, t_u8, t_u16, t_u32, t_u64, t_f32, t_f64, t_alias, t_type ], // u8 317 [t_error, t_error, t_error, t_error, t_error, t_error, t_i16, t_i16, t_i32, t_i64, t_u16, t_u16, t_u32, t_u64, t_f32, t_f64, t_alias, t_type ], // u16 318 [t_error, t_error, t_error, t_error, t_error, t_error, t_i32, t_i32, t_i32, t_i64, t_u32, t_u32, t_u32, t_u64, t_f32, t_f64, t_alias, t_type ], // u32 319 [t_error, t_error, t_error, t_error, t_error, t_error, t_i64, t_i64, t_i64, t_i64, t_u64, t_u64, t_u64, t_u64, t_f32, t_f64, t_alias, t_type ], // u64 320 [t_error, t_error, t_error, t_error, t_error, t_error, t_f32, t_f32, t_f32, t_f32, t_f32, t_f32, t_f32, t_f32, t_f32, t_f64, t_alias, t_type ], // f32 321 [t_error, t_error, t_error, t_error, t_error, t_error, t_f64, t_f64, t_f64, t_f64, t_f64, t_f64, t_f64, t_f64, t_f64, t_f64, t_alias, t_type ], // f64 322 [t_error, t_error, t_error, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias], // $alias 323 [t_error, t_error, t_error, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_type, t_alias, t_type ], // $type 324 ]; } 325 }(); 326 327 string[BasicType.max + 1] basicTypeNames = ["error", "auto", "noreturn", "void", "bool", "typeof(null)", "i8", "i16", "i32", 328 "i64", "u8", "u16", "u32", "u64", "f32", "f64", "$alias", "$type"]; 329 330 bool isBasicTypeToken(TokenType tt) { 331 return tt >= TYPE_TOKEN_FIRST && tt <= TYPE_TOKEN_LAST; 332 } 333 334 BasicType tokenTypeToBasicType(TokenType tt) { 335 return cast(BasicType)(tt - TYPE_TOKEN_FIRST + BasicType.t_noreturn); 336 } 337 338 ubyte numSignedBytesForInt(long value) { 339 if (cast(byte)(value & 0xFF) == value) 340 return 1; 341 else if (cast(short)(value & 0xFFFF) == value) 342 return 2; 343 else if (cast(int)(value & 0xFFFF_FFFF) == value) 344 return 4; 345 else 346 return 8; 347 } 348 349 ubyte numUnsignedBytesForInt(ulong value) { 350 if (cast(ubyte)(value & 0xFF) == value) 351 return 1; 352 else if (cast(ushort)(value & 0xFFFF) == value) 353 return 2; 354 else if (cast(uint)(value & 0xFFFF_FFFF) == value) 355 return 4; 356 else 357 return 8; 358 } 359 360 IrArgSize argSizeIntSigned(long value) { 361 if (cast(byte)(value & 0xFF) == value) 362 return IrArgSize.size8; 363 else if (cast(short)(value & 0xFFFF) == value) 364 return IrArgSize.size16; 365 else if (cast(int)(value & 0xFFFF_FFFF) == value) 366 return IrArgSize.size32; 367 else 368 return IrArgSize.size64; 369 } 370 371 IrArgSize argSizeIntUnsigned(ulong value) { 372 if (cast(ubyte)(value & 0xFF) == value) 373 return IrArgSize.size8; 374 else if (cast(ushort)(value & 0xFFFF) == value) 375 return IrArgSize.size16; 376 else if (cast(uint)(value & 0xFFFF_FFFF) == value) 377 return IrArgSize.size32; 378 else 379 return IrArgSize.size64; 380 } 381 382 BasicType minUnsignedIntType(ulong value) { 383 if (cast(ubyte)(value & 0xFF) == value) 384 return BasicType.t_u8; 385 else if (cast(ushort)(value & 0xFFFF) == value) 386 return BasicType.t_u16; 387 else if (cast(uint)(value & 0xFFFF_FFFF) == value) 388 return BasicType.t_u32; 389 else 390 return BasicType.t_u64; 391 } 392 393 BasicType minSignedIntType(long value) { 394 if (cast(long)cast(byte)(value & 0xFF) == value) 395 return BasicType.t_i8; 396 else if (cast(long)cast(short)(value & 0xFFFF) == value) 397 return BasicType.t_i16; 398 else if (cast(int)(value & 0xFFFF_FFFF) == value) 399 return BasicType.t_i32; 400 else 401 return BasicType.t_i64; 402 }