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