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