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.ptr;
5 
6 import vox.all;
7 
8 @(AstType.type_ptr)
9 struct PtrTypeNode {
10 	mixin AstNodeData!(AstType.type_ptr, AstFlags.isType, AstNodeState.name_register_self_done);
11 	AstIndex type = CommonAstNodes.type_type;
12 	TypeNode* typeNode() return { return cast(TypeNode*)&this; }
13 	AstIndex base;
14 	IrIndex irType;
15 	enum sizealign = SizeAndAlignment(POINTER_SIZE, POINTER_ALIGN_POW);
16 	bool isVoidPtr(CompilationContext* context) {
17 		return context.getAstType(base).isVoid;
18 	}
19 
20 	IrIndex gen_init_value(CompilationContext* c)
21 	{
22 		return c.constants.addZeroConstant(gen_ir_type_ptr(&this, c));
23 	}
24 }
25 
26 void print_ptr(PtrTypeNode* node, ref AstPrintState state)
27 {
28 	state.print("TYPE ", node.typeNode.printer(state.context));
29 }
30 
31 void post_clone_ptr(PtrTypeNode* node, ref CloneState state)
32 {
33 	state.fixAstIndex(node.base);
34 }
35 
36 void name_register_nested_ptr(PtrTypeNode* node, ref NameRegisterState state) {
37 	node.state = AstNodeState.name_register_nested;
38 	require_name_register(node.base, state);
39 	node.state = AstNodeState.name_register_nested_done;
40 }
41 
42 void name_resolve_ptr(PtrTypeNode* node, ref NameResolveState state)
43 {
44 	node.state = AstNodeState.name_resolve;
45 	require_name_resolve(node.base, state);
46 	node.state = AstNodeState.name_resolve_done;
47 }
48 
49 void type_check_ptr(PtrTypeNode* node, ref TypeCheckState state)
50 {
51 	node.state = AstNodeState.type_check;
52 	require_type_check(node.base, state);
53 	node.state = AstNodeState.type_check_done;
54 }
55 
56 bool same_type_ptr(PtrTypeNode* t1, PtrTypeNode* t2, CompilationContext* context)
57 {
58 	return same_type(t1.base, t2.base, context);
59 }
60 
61 CommonTypeResult common_type_ptr(PtrTypeNode* node, AstIndex typeBIndex, CompilationContext* c)
62 {
63 	TypeNode* typeB = typeBIndex.get_type(c);
64 	switch(typeB.astType) with(AstType)
65 	{
66 		case type_basic:
67 			BasicType basicB = typeB.as_basic.basicType;
68 			if (basicB == BasicType.t_null) {
69 				return CommonTypeResult(c.getAstNodeIndex(node), TypeConvResKind.no_i, TypeConvResKind.override_expr_type_i);
70 			}
71 			goto default;
72 		case type_ptr:
73 			if (typeB.as_ptr.base == CommonAstNodes.type_void) {
74 				return CommonTypeResult(c.getAstNodeIndex(node), TypeConvResKind.ii_i, TypeConvResKind.no_i);
75 			}
76 			goto default;
77 		default: return CommonTypeResult(CommonAstNodes.type_error);
78 	}
79 }
80 
81 TypeConvResKind type_conv_ptr(PtrTypeNode* node, AstIndex typeBIndex, ref AstIndex expr, CompilationContext* c)
82 {
83 	TypeNode* typeB = typeBIndex.get_type(c);
84 	switch(typeB.astType) with(AstType) {
85 		case type_basic:
86 			auto toBasic = typeB.as_basic.basicType;
87 			if (toBasic.isInteger) return TypeConvResKind.ii_e;
88 			if (toBasic.isBoolean) return TypeConvResKind.ii_i;
89 			return TypeConvResKind.fail;
90 		case type_ptr:
91 			if (typeB.as_ptr.base == CommonAstNodes.type_void) return TypeConvResKind.ii_i;
92 			return TypeConvResKind.ii_e;
93 		default: return TypeConvResKind.fail;
94 	}
95 }
96 
97 IrIndex gen_ir_type_ptr(PtrTypeNode* t, CompilationContext* context)
98 	out(res; res.isTypePointer, "Not a pointer type")
99 {
100 	if (t.irType.isDefined) return t.irType;
101 	IrIndex baseType = t.base.gen_ir_type(context, AllowHeaderOnly.yes);
102 	t.irType = context.types.appendPtr(baseType);
103 	return t.irType;
104 }