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