Mercurial > projects > ddmd
annotate dmd/IsExp.d @ 125:767a01c2a272
BaseClasses -> Vector
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Fri, 03 Sep 2010 22:17:54 +0100 |
parents | 347de076ad34 |
children | 1765f3ef917d |
rev | line source |
---|---|
72 | 1 module dmd.IsExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Identifier; | |
6 import dmd.ArrayTypes; | |
7 import dmd.Type; | |
8 import dmd.TOK; | |
9 import dmd.OutBuffer; | |
10 import dmd.Loc; | |
11 import dmd.Scope; | |
0 | 12 import dmd.HdrGenState; |
13 import dmd.TY; | |
14 import dmd.TypeEnum; | |
15 import dmd.STC; | |
16 import dmd.TypeClass; | |
17 import dmd.TemplateParameter; | |
18 import dmd.BaseClass; | |
19 import dmd.ClassDeclaration; | |
20 import dmd.TypeStruct; | |
21 import dmd.TypeTypedef; | |
22 import dmd.IntegerExp; | |
23 import dmd.AliasDeclaration; | |
24 import dmd.Dsymbol; | |
25 import dmd.TypeTuple; | |
26 import dmd.TypeDelegate; | |
27 import dmd.Declaration; | |
28 import dmd.TypeFunction; | |
29 import dmd.MATCH; | |
30 import dmd.TypePointer; | |
72 | 31 import dmd.Argument; |
32 import dmd.Token; | |
33 | |
0 | 34 class IsExp : Expression |
35 { | |
36 /* is(targ id tok tspec) | |
37 * is(targ id == tok2) | |
38 */ | |
39 Type targ; | |
40 Identifier id; // can be null | |
41 TOK tok; // ':' or '==' | |
42 Type tspec; // can be null | |
43 TOK tok2; // 'struct', 'union', 'typedef', etc. | |
44 TemplateParameters parameters; | |
45 | |
46 this(Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters parameters) | |
47 { | |
48 super(loc, TOK.TOKis, IsExp.sizeof); | |
49 | |
50 this.targ = targ; | |
51 this.id = id; | |
52 this.tok = tok; | |
53 this.tspec = tspec; | |
54 this.tok2 = tok2; | |
55 this.parameters = parameters; | |
56 } | |
57 | |
72 | 58 override Expression syntaxCopy() |
0 | 59 { |
72 | 60 // This section is identical to that in TemplateDeclaration.syntaxCopy() |
61 TemplateParameters p = null; | |
62 if (parameters) | |
63 { | |
64 p = new TemplateParameters(); | |
65 p.setDim(parameters.dim); | |
66 for (int i = 0; i < p.dim; i++) | |
67 { | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
68 auto tp = parameters[i]; |
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
69 p[i] = tp.syntaxCopy(); |
72 | 70 } |
71 } | |
72 | |
73 return new IsExp(loc, | |
74 targ.syntaxCopy(), | |
75 id, | |
76 tok, | |
77 tspec ? tspec.syntaxCopy() : null, | |
78 tok2, | |
42 | 79 p); |
0 | 80 } |
81 | |
72 | 82 override Expression semantic(Scope sc) |
0 | 83 { |
84 Type tded; | |
85 | |
86 /* is(targ id tok tspec) | |
109 | 87 * is(targ id : tok2) |
0 | 88 * is(targ id == tok2) |
89 */ | |
90 | |
91 //printf("IsExp.semantic(%s)\n", toChars()); | |
92 if (id && !(sc.flags & SCOPE.SCOPEstaticif)) | |
93 error("can only declare type aliases within static if conditionals"); | |
94 | |
95 Type t = targ.trySemantic(loc, sc); | |
96 if (!t) | |
97 goto Lno; // errors, so condition is false | |
98 targ = t; | |
99 if (tok2 != TOK.TOKreserved) | |
100 { | |
101 switch (tok2) | |
102 { | |
103 case TOKtypedef: | |
104 if (targ.ty != Ttypedef) | |
105 goto Lno; | |
106 tded = (cast(TypeTypedef)targ).sym.basetype; | |
107 break; | |
108 | |
109 case TOKstruct: | |
110 if (targ.ty != Tstruct) | |
111 goto Lno; | |
112 if ((cast(TypeStruct)targ).sym.isUnionDeclaration()) | |
113 goto Lno; | |
114 tded = targ; | |
115 break; | |
116 | |
117 case TOKunion: | |
118 if (targ.ty != Tstruct) | |
119 goto Lno; | |
120 if (!(cast(TypeStruct)targ).sym.isUnionDeclaration()) | |
121 goto Lno; | |
122 tded = targ; | |
123 break; | |
124 | |
125 case TOKclass: | |
126 if (targ.ty != Tclass) | |
127 goto Lno; | |
128 if ((cast(TypeClass)targ).sym.isInterfaceDeclaration()) | |
129 goto Lno; | |
130 tded = targ; | |
131 break; | |
132 | |
133 case TOKinterface: | |
134 if (targ.ty != Tclass) | |
135 goto Lno; | |
136 if (!(cast(TypeClass)targ).sym.isInterfaceDeclaration()) | |
137 goto Lno; | |
138 tded = targ; | |
139 break; | |
140 version (DMDV2) { | |
141 case TOKconst: | |
142 if (!targ.isConst()) | |
143 goto Lno; | |
144 tded = targ; | |
145 break; | |
146 | |
147 case TOKinvariant: | |
148 case TOKimmutable: | |
149 if (!targ.isInvariant()) | |
150 goto Lno; | |
151 tded = targ; | |
152 break; | |
153 | |
154 case TOKshared: | |
155 if (!targ.isShared()) | |
156 goto Lno; | |
157 tded = targ; | |
158 break; | |
159 } | |
160 | |
161 case TOKsuper: | |
162 // If class or interface, get the base class and interfaces | |
163 if (targ.ty != Tclass) | |
164 goto Lno; | |
165 else | |
166 { ClassDeclaration cd = (cast(TypeClass)targ).sym; | |
167 Arguments args = new Arguments; | |
168 args.reserve(cd.baseclasses.dim); | |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
169 foreach (b; cd.baseclasses) |
0 | 170 { |
171 args.push(cast(void*)new Argument(STCin, b.type, null, null)); | |
172 } | |
173 tded = new TypeTuple(args); | |
174 } | |
175 break; | |
176 | |
177 case TOKenum: | |
178 if (targ.ty != Tenum) | |
179 goto Lno; | |
180 tded = (cast(TypeEnum)targ).sym.memtype; | |
181 break; | |
182 | |
183 case TOKdelegate: | |
184 if (targ.ty != Tdelegate) | |
185 goto Lno; | |
186 tded = (cast(TypeDelegate)targ).next; // the underlying function type | |
187 break; | |
188 | |
189 case TOKfunction: | |
190 { | |
191 if (targ.ty != Tfunction) | |
192 goto Lno; | |
193 tded = targ; | |
194 | |
195 /* Generate tuple from function parameter types. | |
196 */ | |
197 assert(tded.ty == Tfunction); | |
198 Arguments params = (cast(TypeFunction)tded).parameters; | |
199 size_t dim = Argument.dim(params); | |
200 Arguments args = new Arguments; | |
201 args.reserve(dim); | |
202 for (size_t i = 0; i < dim; i++) | |
203 { | |
204 Argument arg = Argument.getNth(params, i); | |
205 assert(arg && arg.type); | |
206 args.push(cast(void*)new Argument(arg.storageClass, arg.type, null, null)); | |
207 } | |
208 tded = new TypeTuple(args); | |
209 break; | |
210 } | |
211 | |
212 case TOKreturn: | |
213 /* Get the 'return type' for the function, | |
214 * delegate, or pointer to function. | |
215 */ | |
216 if (targ.ty == Tfunction) | |
217 tded = (cast(TypeFunction)targ).next; | |
218 else if (targ.ty == Tdelegate) | |
219 { tded = (cast(TypeDelegate)targ).next; | |
220 tded = (cast(TypeFunction)tded).next; | |
221 } | |
222 else if (targ.ty == Tpointer && | |
223 (cast(TypePointer)targ).next.ty == Tfunction) | |
224 { tded = (cast(TypePointer)targ).next; | |
225 tded = (cast(TypeFunction)tded).next; | |
226 } | |
227 else | |
228 goto Lno; | |
229 break; | |
230 | |
231 default: | |
232 assert(0); | |
233 } | |
234 goto Lyes; | |
235 } | |
236 else if (id && tspec) | |
237 { | |
238 /* Evaluate to true if targ matches tspec. | |
239 * If true, declare id as an alias for the specialized type. | |
240 */ | |
241 | |
242 assert(parameters && parameters.dim); | |
243 | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
244 scope dedtypes = new Objects(); |
0 | 245 dedtypes.setDim(parameters.dim); |
246 dedtypes.zero(); | |
247 | |
109 | 248 MATCH m = targ.deduceType(null, tspec, parameters, dedtypes); |
0 | 249 if (m == MATCHnomatch || |
250 (m != MATCHexact && tok == TOKequal)) | |
251 { | |
252 goto Lno; | |
253 } | |
254 else | |
255 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
256 tded = cast(Type)dedtypes[0]; |
0 | 257 if (!tded) |
258 tded = targ; | |
259 | |
260 scope Objects tiargs = new Objects(); | |
261 tiargs.setDim(1); | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
262 tiargs[0] = targ; |
0 | 263 |
264 /* Declare trailing parameters | |
265 */ | |
266 for (int i = 1; i < parameters.dim; i++) | |
267 { | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
268 auto tp = parameters[i]; |
0 | 269 Declaration s = null; |
270 | |
271 m = tp.matchArg(sc, tiargs, i, parameters, dedtypes, &s); | |
272 if (m == MATCHnomatch) | |
273 goto Lno; | |
274 s.semantic(sc); | |
275 if (!sc.insert(s)) | |
276 error("declaration %s is already defined", s.toChars()); | |
277 static if (false) { | |
278 Object o = cast(Object)dedtypes.data[i]; | |
279 Dsymbol s = TemplateDeclaration.declareParameter(loc, sc, tp, o); | |
280 } | |
281 if (sc.sd) | |
13 | 282 s.addMember(sc, sc.sd, true); |
0 | 283 } |
284 | |
285 goto Lyes; | |
286 } | |
287 } | |
288 else if (id) | |
289 { | |
290 /* Declare id as an alias for type targ. Evaluate to true | |
291 */ | |
292 tded = targ; | |
293 goto Lyes; | |
294 } | |
295 else if (tspec) | |
296 { | |
297 /* Evaluate to true if targ matches tspec | |
298 * is(targ == tspec) | |
299 * is(targ : tspec) | |
300 */ | |
301 tspec = tspec.semantic(loc, sc); | |
302 //printf("targ = %s\n", targ.toChars()); | |
303 //printf("tspec = %s\n", tspec.toChars()); | |
304 if (tok == TOKcolon) | |
305 { | |
306 if (targ.implicitConvTo(tspec)) | |
307 goto Lyes; | |
308 else | |
309 goto Lno; | |
310 } | |
311 else /* == */ | |
312 { | |
313 if (targ.equals(tspec)) | |
314 goto Lyes; | |
315 else | |
316 goto Lno; | |
317 } | |
318 } | |
319 | |
320 Lyes: | |
321 if (id) | |
322 { | |
323 Dsymbol s = new AliasDeclaration(loc, id, tded); | |
324 s.semantic(sc); | |
325 if (!sc.insert(s)) | |
326 error("declaration %s is already defined", s.toChars()); | |
327 if (sc.sd) | |
13 | 328 s.addMember(sc, sc.sd, true); |
0 | 329 } |
330 //printf("Lyes\n"); | |
331 return new IntegerExp(loc, 1, Type.tbool); | |
332 | |
333 Lno: | |
334 //printf("Lno\n"); | |
335 return new IntegerExp(loc, 0, Type.tbool); | |
336 } | |
337 | |
72 | 338 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 339 { |
72 | 340 buf.writestring("is("); |
341 targ.toCBuffer(buf, id, hgs); | |
342 if (tok2 != TOKreserved) | |
343 { | |
344 buf.printf(" %s %s", Token.toChars(tok), Token.toChars(tok2)); | |
345 } | |
346 else if (tspec) | |
347 { | |
348 if (tok == TOKcolon) | |
349 buf.writestring(" : "); | |
350 else | |
351 buf.writestring(" == "); | |
352 tspec.toCBuffer(buf, null, hgs); | |
353 } | |
354 version (DMDV2) { | |
355 if (parameters) | |
356 { | |
357 // First parameter is already output, so start with second | |
358 for (int i = 1; i < parameters.dim; i++) | |
359 { | |
360 buf.writeByte(','); | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
361 auto tp = parameters[i]; |
72 | 362 tp.toCBuffer(buf, hgs); |
363 } | |
364 } | |
365 } | |
50 | 366 buf.writeByte(')'); |
0 | 367 } |
368 } | |
369 |