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.slice;
5 
6 import vox.all;
7 
8 @(AstType.type_slice)
9 struct SliceTypeNode {
10 	mixin AstNodeData!(AstType.type_slice, 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 	IrIndex defaultVal;
16 
17 	enum sizealign = SizeAndAlignment(POINTER_SIZE * 2, POINTER_ALIGN_POW);
18 }
19 
20 void print_slice(SliceTypeNode* node, ref AstPrintState state)
21 {
22 	state.print("TYPE ", node.typeNode.printer(state.context));
23 }
24 
25 void post_clone_slice(SliceTypeNode* node, ref CloneState state)
26 {
27 	state.fixAstIndex(node.base);
28 }
29 
30 void name_register_nested_slice(SliceTypeNode* node, ref NameRegisterState state) {
31 	node.state = AstNodeState.name_register_nested;
32 	require_name_register(node.base, state);
33 	node.state = AstNodeState.name_register_nested_done;
34 }
35 
36 void name_resolve_slice(SliceTypeNode* node, ref NameResolveState state) {
37 	node.state = AstNodeState.name_resolve;
38 	require_name_resolve(node.base, state);
39 	node.state = AstNodeState.name_resolve_done;
40 }
41 
42 void type_check_slice(SliceTypeNode* node, ref TypeCheckState state)
43 {
44 	CompilationContext* c = state.context;
45 	node.state = AstNodeState.type_check;
46 	require_type_check(node.base, state);
47 	if (!node.base.isType(c))
48 		c.error(node.loc, "Slice base type is not a type, it is %s", node.base.astType(c));
49 
50 	node.state = AstNodeState.type_check_done;
51 }
52 
53 bool same_type_slice(SliceTypeNode* t1, SliceTypeNode* t2, CompilationContext* context)
54 {
55 	return same_type(t1.base, t2.base, context);
56 }
57 
58 IrIndex gen_init_value_slice(SliceTypeNode* node, CompilationContext* c)
59 {
60 	if (node.defaultVal.isDefined) return node.defaultVal;
61 	node.defaultVal = c.constants.addZeroConstant(gen_ir_type_slice(node, c));
62 	return node.defaultVal;
63 }
64 
65 // slice is lowered into struct with two members
66 IrIndex gen_ir_type_slice(SliceTypeNode* t, CompilationContext* context)
67 	out(res; res.isTypeStruct, "Not a struct type")
68 {
69 	if (t.irType.isDefined) return t.irType;
70 
71 	t.irType = context.types.appendStruct(2);
72 	IrTypeStruct* structType = &context.types.get!IrTypeStruct(t.irType);
73 	IrIndex baseType = t.base.gen_ir_type(context, AllowHeaderOnly.yes);
74 	// length
75 	structType.members[0] = IrTypeStructMember(makeIrType(IrBasicType.i64), 0);
76 	// ptr
77 	structType.members[1] = IrTypeStructMember(context.types.appendPtr(baseType), POINTER_SIZE);
78 	structType.sizealign = t.sizealign;
79 	return t.irType;
80 }
81 
82 TypeConvResKind type_conv_slice(SliceTypeNode* node, AstIndex typeBIndex, ref AstIndex expr, CompilationContext* c)
83 {
84 	TypeNode* typeB = typeBIndex.get_type(c);
85 
86 	switch(typeB.astType) with(AstType) {
87 		case type_ptr:
88 			if (expr.astType(c) == AstType.literal_string) {
89 				if (typeB.astType == AstType.type_ptr) {
90 					TypeNode* ptrBaseType = typeB.as_ptr.base.get_type(c);
91 					if (ptrBaseType.astType == AstType.type_basic &&
92 						ptrBaseType.as_basic.basicType == BasicType.t_u8)
93 					{
94 						return TypeConvResKind.string_literal_to_u8_ptr;
95 					}
96 				}
97 			}
98 			return TypeConvResKind.fail;
99 		default: return TypeConvResKind.fail;
100 	}
101 }