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.static_array;
5 
6 import vox.all;
7 
8 @(AstType.type_static_array)
9 struct StaticArrayTypeNode {
10 	mixin AstNodeData!(AstType.type_static_array, 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 	AstIndex length_expr;
15 	uint length;
16 	IrIndex irType;
17 	IrIndex defaultVal;
18 	SizeAndAlignment sizealign(CompilationContext* c) {
19 		gen_ir_type_static_array(&this, c);
20 		return c.types.typeSizeAndAlignment(irType);
21 	}
22 }
23 
24 void print_static_array(StaticArrayTypeNode* node, ref AstPrintState state)
25 {
26 	state.print("TYPE ", node.typeNode.printer(state.context));
27 }
28 
29 void post_clone_static_array(StaticArrayTypeNode* node, ref CloneState state)
30 {
31 	state.fixAstIndex(node.base);
32 	state.fixAstIndex(node.length_expr);
33 }
34 
35 void name_register_nested_static_array(StaticArrayTypeNode* node, ref NameRegisterState state) {
36 	node.state = AstNodeState.name_register_nested;
37 	require_name_register(node.base, state);
38 	node.state = AstNodeState.name_register_nested_done;
39 }
40 
41 void name_resolve_static_array(StaticArrayTypeNode* node, ref NameResolveState state) {
42 	node.state = AstNodeState.name_resolve;
43 	require_name_resolve(node.base, state);
44 	require_name_resolve(node.length_expr, state);
45 	node.state = AstNodeState.name_resolve_done;
46 }
47 
48 void type_check_static_array(StaticArrayTypeNode* node, ref TypeCheckState state)
49 {
50 	CompilationContext* c = state.context;
51 
52 	node.state = AstNodeState.type_check;
53 	require_type_check(node.base, state);
54 	calc_length_static_array(node, c);
55 	node.state = AstNodeState.type_check_done;
56 }
57 
58 TypeConvResKind type_conv_static_array(StaticArrayTypeNode* node, AstIndex typeBIndex, ref AstIndex expr, CompilationContext* c)
59 {
60 	TypeNode* typeB = typeBIndex.get_type(c);
61 	switch(typeB.astType) with(AstType)
62 	{
63 		case type_slice:
64 			if (same_type(node.base, typeB.as_slice.base, c)) {
65 				return TypeConvResKind.array_literal_to_slice;
66 			}
67 			return TypeConvResKind.fail;
68 		default: return TypeConvResKind.fail;
69 	}
70 }
71 
72 bool same_type_static_array(StaticArrayTypeNode* t1, StaticArrayTypeNode* t2, CompilationContext* context)
73 {
74 	return (t1.length == t2.length) && same_type(t1.base, t2.base, context);
75 }
76 
77 IrIndex gen_init_value_static_array(StaticArrayTypeNode* node, CompilationContext* c)
78 {
79 	if (node.defaultVal.isDefined) return node.defaultVal;
80 
81 	IrIndex arrayType = node.gen_ir_type_static_array(c);
82 	uint numElements = c.types.get!IrTypeArray(arrayType).numElements;
83 
84 	IrIndex elemDefault = node.base.get_type(c).gen_init_value(c);
85 
86 	if (elemDefault.isConstantZero)
87 	{
88 		node.defaultVal = c.constants.addZeroConstant(arrayType);
89 	}
90 	else
91 	{
92 		node.defaultVal = c.constants.addAggrecateConstant(arrayType, numElements);
93 		IrAggregateConstant* agg = &c.constants.getAggregate(node.defaultVal);
94 		agg.members[] = elemDefault;
95 	}
96 
97 	return node.defaultVal;
98 }
99 
100 uint calc_length_static_array(StaticArrayTypeNode* node, CompilationContext* c)
101 {
102 	final switch(node.getPropertyState(NodeProperty.init_value)) {
103 		case PropertyState.not_calculated: break;
104 		case PropertyState.calculating: c.circular_dependency;
105 		case PropertyState.calculated: return node.length;
106 	}
107 
108 	c.begin_node_property_calculation(node, NodeProperty.init_value);
109 	scope(exit) c.end_node_property_calculation(node, NodeProperty.init_value);
110 
111 	IrIndex val = eval_static_expr(node.length_expr, c);
112 	node.length = c.constants.get(val).i64.to!uint;
113 
114 	return node.length;
115 }
116 
117 IrIndex gen_ir_type_static_array(StaticArrayTypeNode* node, CompilationContext* c)
118 	out(res; res.isTypeArray, "Not a array type")
119 {
120 	final switch(node.getPropertyState(NodeProperty.ir_body)) {
121 		case PropertyState.not_calculated: break;
122 		case PropertyState.calculating: c.circular_dependency;
123 		case PropertyState.calculated: return node.irType;
124 	}
125 
126 	// dependencies
127 	uint array_length = calc_length_static_array(node, c);
128 	IrIndex baseType = node.base.gen_ir_type(c);
129 
130 	c.begin_node_property_calculation(node, NodeProperty.ir_body);
131 	scope(exit) c.end_node_property_calculation(node, NodeProperty.ir_body);
132 
133 	node.irType = c.types.appendArray(baseType, array_length);
134 
135 	return node.irType;
136 }