1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity average)
4 module dil.ast.Types;
5 
6 public import dil.ast.Type;
7 import dil.ast.Node,
8        dil.ast.Expression,
9        dil.ast.Parameters,
10        dil.ast.NodeCopier,
11        dil.ast.Meta;
12 import dil.lexer.Identifier;
13 import dil.semantic.Types;
14 import dil.Enums;
15 import common;
16 
17 /// Syntax error.
18 class IllegalType : TypeNode
19 {
20   mixin(memberInfo());
21   this()
22   {
23     mixin(set_kind);
24   }
25   mixin methods;
26 }
27 
28 /// $(BNF IntegralType := char | int | float | ...)
29 class IntegralType : TypeNode
30 {
31   TOK tok;
32   mixin(memberInfo("tok"));
33   this(TOK tok)
34   {
35     mixin(set_kind);
36     this.tok = tok;
37   }
38   mixin methods;
39 }
40 
41 /// $(BNF ModuleScopeType := ".")
42 class ModuleScopeType : TypeNode
43 {
44   mixin(memberInfo());
45   this()
46   {
47     mixin(set_kind);
48   }
49   mixin methods;
50 }
51 
52 /// $(BNF IdentifierType := Type? Identifier)
53 class IdentifierType : TypeNode
54 {
55   Token* name;
56   mixin(memberInfo("next?", "name"));
57   this(TypeNode next, Token* name)
58   {
59     super(next);
60     mixin(set_kind);
61     this.name = name;
62   }
63 
64   @property Identifier* id()
65   {
66     return name.ident;
67   }
68 
69   mixin methods;
70 }
71 
72 /// $(BNF TypeofType := typeof "(" (Expression | return) ")")
73 class TypeofType : TypeNode
74 {
75   Expression expr;
76 
77   mixin(memberInfo("expr?"));
78   this(Expression e)
79   {
80     mixin(set_kind);
81     addOptChild(e);
82     this.expr = e;
83   }
84 
85   /// Returns true for typeof "(" return ")".
86   bool isTypeofReturn()
87   {
88     return expr is null;
89   }
90 
91   mixin methods;
92 }
93 
94 /// $(BNF TemplateInstanceType :=
95 ////  Identifier "!" (TemplateArgumentList | TemplateArgumentSingle))
96 class TmplInstanceType : TypeNode
97 {
98   Token* name;
99   TemplateArguments targs;
100   mixin(memberInfo("next?", "name", "targs"));
101   this(TypeNode next, Token* name, TemplateArguments targs)
102   {
103     super(next);
104     mixin(set_kind);
105     addOptChild(targs);
106     this.name = name;
107     this.targs = targs;
108   }
109 
110   @property Identifier* id()
111   {
112     return name.ident;
113   }
114 
115   mixin methods;
116 }
117 
118 /// $(BNF PointerType:= Type "*")
119 class PointerType : TypeNode
120 {
121   mixin(memberInfo("next"));
122   this(TypeNode next)
123   {
124     super(next);
125     mixin(set_kind);
126   }
127   mixin methods;
128 }
129 
130 /// $(BNF
131 ////ArrayType := DynamicArray | StaticArray | SliceArray | AssociativeArray
132 ////DynamicArray     := T "[" "]"
133 ////StaticArray      := T "[" E "]"
134 ////SliceArray       := T "[" E ".." E "]" # for slicing tuples
135 ////AssociativeArray := T "[" T "]"
136 ////)
137 class ArrayType : TypeNode
138 {
139   Expression index1, index2;
140   TypeNode assocType;
141 
142   mixin(memberInfo("next", "index1?", "index2?", "assocType?"));
143   /// DynamicArray.
144   this(TypeNode next)
145   {
146     super(next);
147     mixin(set_kind);
148   }
149 
150   /// StaticArray or SliceArray.
151   this(TypeNode next, Expression e1, Expression e2 = null)
152   {
153     this(next);
154     addChild(e1);
155     addOptChild(e2);
156     this.index1 = e1;
157     this.index2 = e2;
158   }
159 
160   /// AssociativeArray.
161   this(TypeNode next, TypeNode assocType)
162   {
163     this(next);
164     addChild(assocType);
165     this.assocType = assocType;
166   }
167 
168   /// For ASTSerializer.
169   this(TypeNode next, Expression e1, Expression e2, TypeNode assocType)
170   {
171     if (e1)
172       this(next, e1, e2);
173     else if (assocType)
174       this(next, assocType);
175     else
176       this(next);
177   }
178 
179   bool isDynamic()
180   {
181     return assocType is null && index1 is null;
182   }
183 
184   bool isStatic()
185   {
186     return index1 !is null && index2 is null;
187   }
188 
189   bool isSlice()
190   {
191     return index1 !is null && index2 !is null;
192   }
193 
194   bool isAssociative()
195   {
196     return assocType !is null;
197   }
198 
199   mixin methods;
200 }
201 
202 /// $(BNF FunctionType := ReturnType function ParameterList)
203 class FunctionType : TypeNode
204 {
205   alias returnType = next;
206   Parameters params;
207   mixin(memberInfo("returnType", "params"));
208   this(TypeNode returnType, Parameters params)
209   {
210     super(returnType);
211     mixin(set_kind);
212     addChild(params);
213     this.params = params;
214   }
215   mixin methods;
216 }
217 
218 /// $(BNF DelegateType := ReturnType delegate ParameterList)
219 class DelegateType : TypeNode
220 {
221   alias returnType = next;
222   Parameters params;
223   mixin(memberInfo("returnType", "params"));
224   this(TypeNode returnType, Parameters params)
225   {
226     super(returnType);
227     mixin(set_kind);
228     addChild(params);
229     this.params = params;
230   }
231   mixin methods;
232 }
233 
234 /// $(BNF BaseClassType := Protection? BasicType)
235 class BaseClassType : TypeNode
236 {
237   Protection prot;
238   mixin(memberInfo("prot", "next"));
239   this(Protection prot, TypeNode type)
240   {
241     super(type);
242     mixin(set_kind);
243     this.prot = prot;
244   }
245   mixin methods;
246 }
247 
248 /// $(BNF ModifierType := ModAttrType | ModParenType
249 ////ModAttrType := Modifier Type
250 ////ModParenType := Modifier "(" Type ")"
251 ////Modifier := const | immutable | shared | inout)
252 class ModifierType : TypeNode
253 {
254   Token* mod;
255   bool hasParen; // True if, e.g.: const "(" Type ")"
256   mixin(memberInfo("next?", "mod", "hasParen"));
257 
258   this(TypeNode next, Token* mod, bool hasParen)
259   {
260     super(next);
261     mixin(set_kind);
262     this.mod = mod;
263     this.hasParen = hasParen;
264   }
265 
266   this(Token* mod)
267   {
268     this(null, mod, false);
269   }
270 
271   bool isImmutable() @property
272   {
273     return mod.kind == TOK.Immutable;
274   }
275 
276   bool isConst() @property
277   {
278     return mod.kind == TOK.Const;
279   }
280 
281   bool isShared() @property
282   {
283     return mod.kind == TOK.Shared;
284   }
285 
286   bool isInout() @property
287   {
288     return mod.kind == TOK.Inout;
289   }
290 
291   mixin methods;
292 }