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 }