1 module d.semantic.type;
2 
3 import d.semantic.semantic;
4 
5 import d.ast.identifier;
6 import d.ast.type;
7 
8 import d.ir.type;
9 
10 struct TypeVisitor {
11 	private SemanticPass pass;
12 	alias pass this;
13 	
14 	private TypeQualifier qualifier;
15 	
16 	this(SemanticPass pass, TypeQualifier qualifier = TypeQualifier.Mutable) {
17 		this.pass = pass;
18 		this.qualifier = qualifier;
19 	}
20 	
21 	import d.ast.declaration;
22 	TypeVisitor withStorageClass(StorageClass stc) {
23 		return TypeVisitor(
24 			pass,
25 			stc.hasQualifier
26 				? qualifier.add(stc.qualifier)
27 				: qualifier,
28 		);
29 	}
30 	
31 	Type visit(AstType t) {
32 		return t.accept(this).qualify(t.qualifier);
33 	}
34 	
35 	ParamType visit(ParamAstType t) {
36 		return visit(t.getType()).getParamType(t.paramKind);
37 	}
38 	
39 	Type visit(BuiltinType t) {
40 		return Type.get(t, qualifier);
41 	}
42 	
43 	Type visit(Identifier i) {
44 		import d.semantic.identifier;
45 		return IdentifierResolver(pass)
46 			.build(i)
47 			.apply!(delegate Type(identified) {
48 				static if(is(typeof(identified) : Type)) {
49 					return identified.qualify(qualifier);
50 				} else {
51 					import d.ir.error;
52 					return getError(
53 						identified,
54 						i.location,
55 						i.toString(pass.context) ~ " ("
56 							~ typeid(identified).toString()
57 							~ ") isn't an type",
58 					).type;
59 				}
60 			})();
61 	}
62 	
63 	Type visitPointerOf(AstType t) {
64 		return visit(t).getPointer(qualifier);
65 	}
66 	
67 	Type visitSliceOf(AstType t) {
68 		return visit(t).getSlice(qualifier);
69 	}
70 	
71 	Type visitArrayOf(AstExpression size, AstType t) {
72 		auto type = visit(t);
73 		
74 		import d.semantic.expression;
75 		return buildArray(ExpressionVisitor(pass).visit(size), type);
76 	}
77 	
78 	import d.ir.expression;
79 	private Type buildArray(Expression size, Type t) {
80 		import d.semantic.caster, d.semantic.expression;
81 		auto s = evalIntegral(buildImplicitCast(
82 			pass,
83 			size.location,
84 			pass.object.getSizeT().type,
85 			size,
86 		));
87 		
88 		assert(s <= uint.max, "Array larger than uint.max are not supported");
89 		return t.getArray(cast(uint) s, qualifier);
90 	}
91 	
92 	Type visitMapOf(AstType key, AstType t) {
93 		visit(t);
94 		visit(key);
95 		assert(0, "Map are not implemented.");
96 	}
97 	
98 	Type visitBracketOf(Identifier ikey, AstType t) {
99 		auto type = visit(t);
100 		
101 		import d.semantic.identifier, d.ir.symbol;
102 		return IdentifierResolver(pass)
103 			.build(ikey)
104 			.apply!(delegate Type(identified) {
105 				alias T = typeof(identified);
106 				static if (is(T : Type)) {
107 					assert(0, "Not implemented.");
108 				} else static if (is(T: Expression)) {
109 					return buildArray(identified, type);
110 				} else if (auto v = cast(ValueTemplateParameter) identified) {
111 					return Pattern(type, v).getType();
112 				} else {
113 					import d.ir.error;
114 					return getError(
115 						identified,
116 						ikey.location,
117 						ikey.toString(pass.context)
118 							~ " isn't an type or an expression",
119 					).type;
120 				}
121 			})();
122 	}
123 	
124 	Type visit(FunctionAstType t) {
125 		auto ctxCount = t.contexts.length;
126 		auto f = t.getFunction();
127 		
128 		ParamType[] paramTypes;
129 		paramTypes.length = f.parameters.length;
130 		
131 		auto oldQualifier = qualifier;
132 		scope(exit) qualifier = oldQualifier;
133 		
134 		foreach(i; 0 .. ctxCount) {
135 			paramTypes[i] = visit(f.parameters[i]);
136 		}
137 		
138 		qualifier = TypeQualifier.Mutable;
139 		
140 		auto returnType = visit(t.returnType);
141 		foreach (i; ctxCount .. paramTypes.length) {
142 			paramTypes[i] = visit(f.parameters[i]);
143 		}
144 		
145 		return FunctionType(t.linkage, returnType, paramTypes, t.isVariadic)
146 			.getDelegate(ctxCount)
147 			.getType(oldQualifier);
148 	}
149 	
150 	import d.ast.expression;
151 	Type visit(AstExpression e) {
152 		import d.semantic.expression;
153 		return ExpressionVisitor(pass).visit(e).type.qualify(qualifier);
154 	}
155 	
156 	Type visitTypeOfReturn() {
157 		assert(0, "typeof(return) is not implemented.");
158 	}
159 }