1 /// Copyright: Copyright (c) 2021 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.type_node; 5 6 import vox.all; 7 8 9 enum POINTER_SIZE = 8; 10 enum POINTER_ALIGN_POW = 3; 11 12 struct TypeNode 13 { 14 AstNode base; 15 alias base this; 16 17 BasicTypeNode* as_basic() return { if (astType == AstType.type_basic) return cast(BasicTypeNode*)&this; return null; } 18 FunctionSignatureNode* as_func_sig() return { if (astType == AstType.type_func_sig) return cast(FunctionSignatureNode*)&this; return null; } 19 PtrTypeNode* as_ptr() return { if (astType == AstType.type_ptr) return cast(PtrTypeNode*)&this; return null; } 20 SliceTypeNode* as_slice() return { if (astType == AstType.type_slice) return cast(SliceTypeNode*)&this; return null; } 21 StaticArrayTypeNode* as_static_array() return { if (astType == AstType.type_static_array) return cast(StaticArrayTypeNode*)&this; return null; } 22 StructDeclNode* as_struct() return { if (astType == AstType.decl_struct) return cast(StructDeclNode*)&this; return null; } 23 AliasDeclNode* as_alias() return { if (astType == AstType.decl_alias) return cast(AliasDeclNode*)&this; return null; } 24 NameUseExprNode* as_name_use() return { if (astType == AstType.expr_name_use) return cast(NameUseExprNode*)&this; return null; } 25 EnumDeclaration* as_enum() return { if (astType == AstType.decl_enum) return cast(EnumDeclaration*)&this; return null; } 26 27 TypeNode* foldAliases(CompilationContext* c) return { 28 if (astType == AstType.expr_name_use) return as_name_use.entity.get_type(c); 29 return &this; 30 } 31 32 SizeAndAlignment sizealign(CompilationContext* c) { 33 return require_type_size(&this, c); 34 } 35 36 IrArgSize argSize(CompilationContext* c) 37 { 38 return sizealign(c).size.sizeToIrArgSize(c); 39 } 40 41 bool isOpaqueStruct(CompilationContext* c) { 42 TypeNode* t = foldAliases(c); 43 if (t.astType == AstType.expr_name_use) t = c.getAstNode(t.as_name_use.entity).as_type(c); 44 return t.astType == AstType.decl_struct && t.as_struct.isOpaque; 45 } 46 47 TypePrinter printer(CompilationContext* c) return { 48 return TypePrinter(&this, c); 49 } 50 51 bool isPassByPtr(CompilationContext* c) 52 { 53 if (astType == AstType.type_slice) return true; 54 if (astType == AstType.decl_struct) 55 { 56 switch(sizealign(c).size) { 57 case 1: return false; 58 case 2: return false; 59 case 4: return false; 60 case 8: return false; 61 default: return true; 62 } 63 } 64 return false; 65 } 66 67 bool isTypeofNull() { 68 return astType == AstType.type_basic && 69 as_basic.basicType == BasicType.t_null; 70 } 71 bool isTypeBasic() { 72 return astType == AstType.type_basic; 73 } 74 bool isAuto() { 75 return astType == AstType.type_basic && 76 as_basic.basicType == BasicType.t_auto; 77 } 78 bool isNoreturn() { 79 return astType == AstType.type_basic && 80 as_basic.basicType == BasicType.t_noreturn; 81 } 82 bool isVoid() { 83 return astType == AstType.type_basic && 84 as_basic.basicType == BasicType.t_void; 85 } 86 bool isNoreturnOrVoid() { 87 return astType == AstType.type_basic && 88 as_basic.basicType == BasicType.t_void; 89 } 90 bool isPointer() { return astType == AstType.type_ptr; } 91 bool isSlice() { return astType == AstType.type_slice; } 92 bool isStaticArray() { return astType == AstType.type_static_array; } 93 bool isInteger() { return astType == AstType.type_basic && as_basic.isInteger; } 94 bool isBool() { return astType == AstType.type_basic && 95 as_basic.basicType == BasicType.t_bool; } 96 bool isStruct() { return astType == AstType.decl_struct; } 97 bool isFuncSignature() { return astType == AstType.type_func_sig; } 98 bool isMetaType() { 99 return astType == AstType.type_basic && 100 (as_basic.isAlias || as_basic.isType); } 101 bool isAlias() { return astType == AstType.type_basic && as_basic.isAlias; } 102 bool isTypeType() { return astType == AstType.type_basic && as_basic.isType; } 103 bool isEnum() { return astType == AstType.decl_enum; } 104 105 IsSigned isSigned() { 106 if (astType == AstType.type_basic) return as_basic.isSigned; 107 return IsSigned.no; 108 } 109 110 bool isFloat() { 111 if (astType == AstType.type_basic) return as_basic.isFloat; 112 return false; 113 } 114 115 AstIndex getElementType(CompilationContext* c) { 116 switch(astType) 117 { 118 case AstType.type_ptr: return as_ptr.base; 119 case AstType.type_static_array: return as_static_array.base; 120 case AstType.type_slice: return as_slice.base; 121 default: c.internal_error(loc, "%s is not indexable", astType); 122 } 123 } 124 125 IrIndex gen_init_value(CompilationContext* c) 126 { 127 switch(astType) 128 { 129 case AstType.type_basic: return as_basic.gen_init_value(c); 130 case AstType.type_ptr: return as_ptr.gen_init_value(c); 131 case AstType.type_static_array: return as_static_array.gen_init_value_static_array(c); 132 case AstType.type_slice: return as_slice.gen_init_value_slice(c); 133 case AstType.decl_struct: return as_struct.gen_init_value_struct(c); 134 case AstType.decl_enum: return as_enum.gen_init_value_enum(c); 135 case AstType.expr_name_use: return as_name_use.entity.get_type(c).gen_init_value(c); 136 default: assert(false, format("got %s", astType)); 137 } 138 } 139 } 140 141 SizeAndAlignment require_type_size(AstIndex typeIndex, CompilationContext* c) 142 { 143 return typeIndex.get_type(c).require_type_size(c); 144 } 145 146 SizeAndAlignment require_type_size(TypeNode* type, CompilationContext* c) 147 { 148 //c.assertf(type.state >= AstNodeState.type_check_done, type.loc, "%s %s", type.typeName(c), type.state); 149 switch(type.astType) 150 { 151 case AstType.type_basic: return type.as_basic.sizealign; 152 case AstType.type_ptr: return type.as_ptr.sizealign; 153 case AstType.type_static_array: return type.as_static_array.sizealign(c); 154 case AstType.type_slice: return type.as_slice.sizealign; 155 case AstType.decl_struct: return type.as_struct.sizealign(c); 156 case AstType.decl_enum: return type.as_enum.sizealign(c); 157 case AstType.expr_name_use: return type.as_name_use.entity.require_type_size(c); 158 default: assert(false, format("got %s", type.astType)); 159 } 160 } 161 162 IrArgSize typeArgSize(AstIndex typeIndex, CompilationContext* c) 163 { 164 return typeIndex.require_type_size(c).size.sizeToIrArgSize(c); 165 } 166 167 string typeName(AstIndex typeIndex, CompilationContext* c) 168 { 169 return typeIndex.get_type(c).typeName(c); 170 } 171 172 string typeName(TypeNode* type, CompilationContext* c) 173 { 174 switch(type.astType) 175 { 176 case AstType.type_basic: 177 return type.as_basic.strId; 178 case AstType.type_ptr: 179 return "ptr"; 180 case AstType.type_static_array: return "[num]"; 181 case AstType.type_slice: return "[]"; 182 case AstType.decl_struct: return c.idString(type.as_struct.id); 183 case AstType.decl_enum: return c.idString(type.as_enum.id); 184 case AstType.expr_name_use: return c.idString(type.as_name_use.id(c)); 185 default: assert(false, format("got %s", type.astType)); 186 } 187 } 188 189 struct TypePrinter 190 { 191 TypeNode* node; 192 CompilationContext* ctx; 193 194 void toString(scope void delegate(const(char)[]) sink) { 195 if (node) node.printType(sink, ctx); else sink("<null>"); 196 } 197 } 198 199 void printType(AstIndex t, scope void delegate(const(char)[]) sink, CompilationContext* ctx) { 200 if (t.isUndefined) { 201 sink("?"); 202 return; 203 } 204 printType(t.get_type(ctx), sink, ctx); 205 } 206 207 void printType(TypeNode* t, scope void delegate(const(char)[]) sink, CompilationContext* ctx) { 208 if (t is null) { 209 sink("?"); 210 return; 211 } 212 213 switch(t.astType) 214 { 215 case AstType.type_basic: 216 sink(basicTypeNames[t.as_basic.basicType]); 217 break; 218 case AstType.type_func_sig: 219 FunctionSignatureNode* func_sig = t.as_func_sig; 220 func_sig.returnType.get_node_type(ctx).printType(sink, ctx); 221 sink(" function("); 222 foreach(i, param; func_sig.parameters) 223 { 224 if (i > 0) sink(", "); 225 param.get_node_type(ctx).printType(sink, ctx); 226 sink(" "); 227 sink(ctx.idString(get_node_id(param, ctx))); 228 } 229 sink(")"); 230 break; 231 case AstType.type_ptr: 232 t.as_ptr.base.get_node_type(ctx).printType(sink, ctx); 233 sink("*"); 234 break; 235 case AstType.type_static_array: 236 t.as_static_array.base.get_node_type(ctx).printType(sink, ctx); 237 formattedWrite(sink, "[%s]", t.as_static_array.length); 238 break; 239 case AstType.type_slice: 240 t.as_slice.base.get_node_type(ctx).printType(sink, ctx); 241 sink("[]"); 242 break; 243 case AstType.decl_struct: 244 sink(ctx.idString(t.as_struct.id)); 245 break; 246 case AstType.expr_name_use: 247 if (t.as_name_use.isSymResolved) 248 t.as_name_use.entity.printType(sink, ctx); 249 else 250 sink(ctx.idString(t.as_name_use.id(ctx))); 251 break; 252 case AstType.decl_enum: 253 sink(ctx.idString(t.as_enum.id)); 254 break; 255 default: assert(false, format("%s is not type", t.astType)); 256 } 257 } 258 259 bool same_type(AstIndex _t1, AstIndex _t2, CompilationContext* c) { 260 TypeNode* t1 = c.getAstType(_t1).foldAliases(c); 261 TypeNode* t2 = c.getAstType(_t2).foldAliases(c); 262 assert(t1.isType, format("t1 is %s, not type", t1.astType)); 263 assert(t2.isType, format("t2 is %s, not type", t2.astType)); 264 265 if (t1.astType != t2.astType) { 266 return false; 267 } 268 269 switch(t1.astType) with(AstType) 270 { 271 case type_basic: 272 return t1.as_basic.basicType == t2.as_basic.basicType; 273 case type_func_sig: return same_type_func_sig(t1.as_func_sig, t2.as_func_sig, c); 274 case type_ptr: return same_type_ptr(t1.as_ptr, t2.as_ptr, c); 275 case type_static_array: return same_type_static_array(t1.as_static_array, t2.as_static_array, c); 276 case type_slice: 277 return same_type_slice(t1.as_slice, t2.as_slice, c); 278 case decl_struct: 279 return t1 == t2; 280 case decl_enum: 281 return t1 == t2; 282 default: 283 c.internal_error("got %s %s", t1.astType, t2.astType); 284 } 285 } 286 287 /// If AllowHeaderOnly is true and `ir_body` is `calculating` then it will return just the ir_header. 288 /// Otherwise if ir_body is not_calculated, gen_ir_type will calculate it 289 enum AllowHeaderOnly : bool { 290 no = false, 291 yes = true, 292 } 293 294 IrIndex gen_ir_type(AstIndex nodeIndex, CompilationContext* c, AllowHeaderOnly allow_header_only = AllowHeaderOnly.no) 295 { 296 return gen_ir_type(c.getAst!TypeNode(nodeIndex), c, allow_header_only); 297 } 298 299 IrIndex gen_ir_type(TypeNode* typeNode, CompilationContext* c, AllowHeaderOnly allow_header_only = AllowHeaderOnly.no) 300 { 301 switch (typeNode.astType) 302 { 303 case AstType.type_basic: return gen_ir_type_basic(typeNode.as_basic, c); 304 case AstType.type_ptr: return gen_ir_type_ptr(typeNode.as_ptr, c); 305 case AstType.type_static_array: return gen_ir_type_static_array(typeNode.as_static_array, c); 306 case AstType.type_slice: return gen_ir_type_slice(typeNode.as_slice, c); 307 case AstType.decl_struct: return gen_ir_type_struct(typeNode.as_struct, c, allow_header_only); 308 case AstType.type_func_sig: return gen_ir_type_func_sig(typeNode.as_func_sig, c); 309 case AstType.expr_name_use: return gen_ir_type(typeNode.as_name_use.entity.get_node_type(c), c, allow_header_only); 310 case AstType.decl_enum: return gen_ir_type_enum(typeNode.as_enum, c); 311 default: 312 c.internal_error(typeNode.loc, "Cannot convert `%s` to ir type", typeNode.astType); 313 } 314 }