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 }