Mercurial > projects > ddmd
annotate dmd/IsExp.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | 60bb0fe4563e |
children | e3afd1303184 |
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; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
31 import dmd.Parameter; |
72 | 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: | |
135 | 149 if (!targ.isImmutable()) |
0 | 150 goto Lno; |
151 tded = targ; | |
152 break; | |
153 | |
154 case TOKshared: | |
155 if (!targ.isShared()) | |
135 | 156 goto Lno; |
157 tded = targ; | |
158 break; | |
159 | |
160 case TOKwild: | |
161 if (!targ.isWild()) | |
0 | 162 goto Lno; |
163 tded = targ; | |
164 break; | |
165 } | |
166 | |
167 case TOKsuper: | |
168 // If class or interface, get the base class and interfaces | |
169 if (targ.ty != Tclass) | |
170 goto Lno; | |
171 else | |
172 { ClassDeclaration cd = (cast(TypeClass)targ).sym; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
173 auto args = new Parameters; |
0 | 174 args.reserve(cd.baseclasses.dim); |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
175 foreach (b; cd.baseclasses) |
0 | 176 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
177 args.push(new Parameter(STCin, b.type, null, null)); |
0 | 178 } |
179 tded = new TypeTuple(args); | |
180 } | |
181 break; | |
182 | |
183 case TOKenum: | |
184 if (targ.ty != Tenum) | |
185 goto Lno; | |
186 tded = (cast(TypeEnum)targ).sym.memtype; | |
187 break; | |
188 | |
189 case TOKdelegate: | |
190 if (targ.ty != Tdelegate) | |
191 goto Lno; | |
192 tded = (cast(TypeDelegate)targ).next; // the underlying function type | |
193 break; | |
194 | |
195 case TOKfunction: | |
196 { | |
197 if (targ.ty != Tfunction) | |
198 goto Lno; | |
199 tded = targ; | |
200 | |
201 /* Generate tuple from function parameter types. | |
202 */ | |
203 assert(tded.ty == Tfunction); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
204 auto params = (cast(TypeFunction)tded).parameters; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
205 size_t dim = Parameter.dim(params); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
206 auto args = new Parameters; |
0 | 207 args.reserve(dim); |
208 for (size_t i = 0; i < dim; i++) | |
209 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
210 auto arg = Parameter.getNth(params, i); |
0 | 211 assert(arg && arg.type); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
212 args.push(new Parameter(arg.storageClass, arg.type, null, null)); |
0 | 213 } |
214 tded = new TypeTuple(args); | |
215 break; | |
216 } | |
217 | |
218 case TOKreturn: | |
219 /* Get the 'return type' for the function, | |
220 * delegate, or pointer to function. | |
221 */ | |
222 if (targ.ty == Tfunction) | |
223 tded = (cast(TypeFunction)targ).next; | |
224 else if (targ.ty == Tdelegate) | |
225 { tded = (cast(TypeDelegate)targ).next; | |
226 tded = (cast(TypeFunction)tded).next; | |
227 } | |
228 else if (targ.ty == Tpointer && | |
229 (cast(TypePointer)targ).next.ty == Tfunction) | |
230 { tded = (cast(TypePointer)targ).next; | |
231 tded = (cast(TypeFunction)tded).next; | |
232 } | |
233 else | |
234 goto Lno; | |
235 break; | |
236 | |
237 default: | |
238 assert(0); | |
239 } | |
240 goto Lyes; | |
241 } | |
242 else if (id && tspec) | |
243 { | |
244 /* Evaluate to true if targ matches tspec. | |
245 * If true, declare id as an alias for the specialized type. | |
246 */ | |
247 | |
248 assert(parameters && parameters.dim); | |
249 | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
250 scope dedtypes = new Objects(); |
0 | 251 dedtypes.setDim(parameters.dim); |
252 dedtypes.zero(); | |
253 | |
109 | 254 MATCH m = targ.deduceType(null, tspec, parameters, dedtypes); |
0 | 255 if (m == MATCHnomatch || |
256 (m != MATCHexact && tok == TOKequal)) | |
257 { | |
258 goto Lno; | |
259 } | |
260 else | |
261 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
262 tded = cast(Type)dedtypes[0]; |
0 | 263 if (!tded) |
264 tded = targ; | |
265 | |
266 scope Objects tiargs = new Objects(); | |
267 tiargs.setDim(1); | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
268 tiargs[0] = targ; |
0 | 269 |
270 /* Declare trailing parameters | |
271 */ | |
272 for (int i = 1; i < parameters.dim; i++) | |
273 { | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
274 auto tp = parameters[i]; |
0 | 275 Declaration s = null; |
276 | |
277 m = tp.matchArg(sc, tiargs, i, parameters, dedtypes, &s); | |
278 if (m == MATCHnomatch) | |
279 goto Lno; | |
280 s.semantic(sc); | |
281 if (!sc.insert(s)) | |
282 error("declaration %s is already defined", s.toChars()); | |
283 static if (false) { | |
284 Object o = cast(Object)dedtypes.data[i]; | |
285 Dsymbol s = TemplateDeclaration.declareParameter(loc, sc, tp, o); | |
286 } | |
287 if (sc.sd) | |
13 | 288 s.addMember(sc, sc.sd, true); |
0 | 289 } |
290 | |
291 goto Lyes; | |
292 } | |
293 } | |
294 else if (id) | |
295 { | |
296 /* Declare id as an alias for type targ. Evaluate to true | |
297 */ | |
298 tded = targ; | |
299 goto Lyes; | |
300 } | |
301 else if (tspec) | |
302 { | |
303 /* Evaluate to true if targ matches tspec | |
304 * is(targ == tspec) | |
305 * is(targ : tspec) | |
306 */ | |
307 tspec = tspec.semantic(loc, sc); | |
308 //printf("targ = %s\n", targ.toChars()); | |
309 //printf("tspec = %s\n", tspec.toChars()); | |
310 if (tok == TOKcolon) | |
311 { | |
312 if (targ.implicitConvTo(tspec)) | |
313 goto Lyes; | |
314 else | |
315 goto Lno; | |
316 } | |
317 else /* == */ | |
318 { | |
319 if (targ.equals(tspec)) | |
320 goto Lyes; | |
321 else | |
322 goto Lno; | |
323 } | |
324 } | |
325 | |
326 Lyes: | |
327 if (id) | |
328 { | |
329 Dsymbol s = new AliasDeclaration(loc, id, tded); | |
330 s.semantic(sc); | |
331 if (!sc.insert(s)) | |
332 error("declaration %s is already defined", s.toChars()); | |
333 if (sc.sd) | |
13 | 334 s.addMember(sc, sc.sd, true); |
0 | 335 } |
336 //printf("Lyes\n"); | |
337 return new IntegerExp(loc, 1, Type.tbool); | |
338 | |
339 Lno: | |
340 //printf("Lno\n"); | |
341 return new IntegerExp(loc, 0, Type.tbool); | |
342 } | |
343 | |
72 | 344 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 345 { |
72 | 346 buf.writestring("is("); |
347 targ.toCBuffer(buf, id, hgs); | |
348 if (tok2 != TOKreserved) | |
349 { | |
350 buf.printf(" %s %s", Token.toChars(tok), Token.toChars(tok2)); | |
351 } | |
352 else if (tspec) | |
353 { | |
354 if (tok == TOKcolon) | |
355 buf.writestring(" : "); | |
356 else | |
357 buf.writestring(" == "); | |
358 tspec.toCBuffer(buf, null, hgs); | |
359 } | |
360 version (DMDV2) { | |
361 if (parameters) | |
362 { | |
363 // First parameter is already output, so start with second | |
364 for (int i = 1; i < parameters.dim; i++) | |
365 { | |
366 buf.writeByte(','); | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
367 auto tp = parameters[i]; |
72 | 368 tp.toCBuffer(buf, hgs); |
369 } | |
370 } | |
371 } | |
50 | 372 buf.writeByte(')'); |
0 | 373 } |
374 } | |
375 |