Mercurial > projects > ddmd
annotate dmd/EnumDeclaration.d @ 77:ad4792a1cfd6
more D-ification container accessing
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Sun, 29 Aug 2010 14:36:55 +0100 |
parents | 2e2a5c3f943a |
children | 43073c7c7769 |
rev | line source |
---|---|
0 | 1 module dmd.EnumDeclaration; |
2 | |
3 import dmd.ScopeDsymbol; | |
4 import dmd.AddExp; | |
5 import dmd.Type; | |
6 import dmd.CmpExp; | |
7 import dmd.IntegerExp; | |
8 import dmd.EqualExp; | |
9 import dmd.TOK; | |
10 import dmd.Id; | |
11 import dmd.TY; | |
12 import dmd.DsymbolTable; | |
13 import dmd.STC; | |
14 import dmd.Expression; | |
15 import dmd.Identifier; | |
16 import dmd.Dsymbol; | |
17 import dmd.Scope; | |
18 import dmd.OutBuffer; | |
19 import dmd.HdrGenState; | |
20 import dmd.Global; | |
21 import dmd.Loc; | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
20
diff
changeset
|
22 import dmd.Module; |
0 | 23 import dmd.TypeEnum; |
24 import dmd.EnumMember; | |
25 import dmd.DYNCAST; | |
26 import dmd.WANT; | |
27 import dmd.Id; | |
28 import dmd.Lexer; | |
29 | |
30 import dmd.backend.SC; | |
31 import dmd.backend.FL; | |
32 import dmd.backend.Util; | |
33 import dmd.backend.Symbol; | |
34 import dmd.backend.Classsym; | |
35 import dmd.backend.SFL; | |
36 import dmd.backend.LIST; | |
37 import dmd.codegen.Util; | |
38 | |
39 import std.stdio : writef; | |
40 | |
41 class EnumDeclaration : ScopeDsymbol | |
42 { /* enum ident : memtype { ... } | |
43 */ | |
44 Type type; // the TypeEnum | |
45 Type memtype; // type of the members | |
46 | |
47 version (DMDV1) { | |
48 ulong maxval; | |
49 ulong minval; | |
50 ulong defaultval; // default initializer | |
51 } else { | |
52 Expression maxval; | |
53 Expression minval; | |
54 Expression defaultval; // default initializer | |
55 } | |
56 bool isdeprecated; | |
57 | |
58 this(Loc loc, Identifier id, Type memtype) | |
59 { | |
60 super(id); | |
61 this.loc = loc; | |
62 type = new TypeEnum(this); | |
63 this.memtype = memtype; | |
64 } | |
65 | |
72 | 66 override Dsymbol syntaxCopy(Dsymbol s) |
0 | 67 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
68 Type t = null; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
69 if (memtype) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
70 t = memtype.syntaxCopy(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
71 |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
72 EnumDeclaration ed; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
73 if (s) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
74 { ed = cast(EnumDeclaration)s; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
75 ed.memtype = t; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
76 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
77 else |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
78 ed = new EnumDeclaration(loc, ident, t); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
79 ScopeDsymbol.syntaxCopy(ed); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
80 return ed; |
0 | 81 } |
82 | |
72 | 83 override void semantic(Scope sc) |
0 | 84 { |
85 Type t; | |
86 Scope sce; | |
87 | |
88 //writef("EnumDeclaration.semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), toChars()); | |
89 //writef("EnumDeclaration.semantic() %s\n", toChars()); | |
90 if (!members) // enum ident; | |
91 return; | |
92 | |
93 if (!memtype && !isAnonymous()) | |
94 { | |
95 // Set memtype if we can to reduce fwd reference errors | |
96 memtype = Type.tint32; // case 1) enum ident { ... } | |
97 } | |
98 | |
99 if (symtab) // if already done | |
100 { | |
101 if (!scope_) | |
102 return; // semantic() already completed | |
103 } | |
104 else | |
105 symtab = new DsymbolTable(); | |
106 | |
107 Scope scx = null; | |
108 if (scope_) | |
109 { sc = scope_; | |
110 scx = scope_; // save so we don't make redundant copies | |
111 scope_ = null; | |
112 } | |
113 | |
114 if (sc.stc & STC.STCdeprecated) | |
115 isdeprecated = true; | |
116 | |
117 parent = sc.parent; | |
118 | |
119 /* The separate, and distinct, cases are: | |
120 * 1. enum { ... } | |
121 * 2. enum : memtype { ... } | |
122 * 3. enum ident { ... } | |
123 * 4. enum ident : memtype { ... } | |
124 */ | |
125 | |
126 if (memtype) | |
127 { | |
128 memtype = memtype.semantic(loc, sc); | |
129 | |
130 /* Check to see if memtype is forward referenced | |
131 */ | |
132 if (memtype.ty == TY.Tenum) | |
133 { EnumDeclaration sym = cast(EnumDeclaration)memtype.toDsymbol(sc); | |
134 if (!sym.memtype || !sym.members || !sym.symtab || sym.scope_) | |
135 { | |
136 // memtype is forward referenced, so try again later | |
137 scope_ = scx ? scx : new Scope(sc); | |
138 scope_.setNoFree(); | |
139 scope_.module_.addDeferredSemantic(this); | |
140 writef("\tdeferring %s\n", toChars()); | |
141 return; | |
142 } | |
143 } | |
144 static if (false) { | |
145 // Decided to abandon this restriction for D 2.0 | |
146 if (!memtype.isintegral()) | |
147 { error("base type must be of integral type, not %s", memtype.toChars()); | |
148 memtype = Type.tint32; | |
149 } | |
150 } | |
151 } | |
152 | |
153 type = type.semantic(loc, sc); | |
154 if (isAnonymous()) | |
155 sce = sc; | |
156 else | |
157 { sce = sc.push(this); | |
158 sce.parent = this; | |
159 } | |
160 if (members.dim == 0) | |
161 error("enum %s must have at least one member", toChars()); | |
162 int first = 1; | |
163 Expression elast = null; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
164 foreach (Dsymbol s; members) |
0 | 165 { |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
166 EnumMember em = s.isEnumMember(); |
0 | 167 Expression e; |
168 | |
169 if (!em) | |
170 /* The e.semantic(sce) can insert other symbols, such as | |
171 * template instances and function literals. | |
172 */ | |
173 continue; | |
174 | |
175 //printf(" Enum member '%s'\n",em.toChars()); | |
176 if (em.type) | |
177 em.type = em.type.semantic(em.loc, sce); | |
178 e = em.value; | |
179 if (e) | |
180 { | |
181 assert(e.dyncast() == DYNCAST.DYNCAST_EXPRESSION); | |
182 e = e.semantic(sce); | |
183 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
184 if (memtype) | |
185 { | |
186 e = e.implicitCastTo(sce, memtype); | |
187 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
188 if (!isAnonymous()) | |
189 e = e.castTo(sce, type); | |
190 t = memtype; | |
191 } | |
192 else if (em.type) | |
193 { | |
194 e = e.implicitCastTo(sce, em.type); | |
195 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
196 assert(isAnonymous()); | |
197 t = e.type; | |
198 } | |
199 else | |
200 t = e.type; | |
201 } | |
202 else if (first) | |
203 { | |
204 if (memtype) | |
205 t = memtype; | |
206 else if (em.type) | |
207 t = em.type; | |
208 else | |
209 t = Type.tint32; | |
210 e = new IntegerExp(em.loc, 0, Type.tint32); | |
211 e = e.implicitCastTo(sce, t); | |
212 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
213 if (!isAnonymous()) | |
214 e = e.castTo(sce, type); | |
215 } | |
216 else | |
217 { | |
218 // Set value to (elast + 1). | |
219 // But first check that (elast != t.max) | |
220 assert(elast); | |
221 e = new EqualExp(TOK.TOKequal, em.loc, elast, t.getProperty(Loc(0), Id.max)); | |
222 e = e.semantic(sce); | |
223 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
224 if (e.toInteger()) | |
225 error("overflow of enum value %s", elast.toChars()); | |
226 | |
227 // Now set e to (elast + 1) | |
228 e = new AddExp(em.loc, elast, new IntegerExp(em.loc, 1, Type.tint32)); | |
229 e = e.semantic(sce); | |
230 e = e.castTo(sce, elast.type); | |
231 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
232 } | |
233 elast = e; | |
234 em.value = e; | |
235 | |
236 // Add to symbol table only after evaluating 'value' | |
237 if (isAnonymous()) | |
238 { | |
239 /* Anonymous enum members get added to enclosing scope. | |
240 */ | |
241 for (Scope scxx = sce; scxx; scxx = scxx.enclosing) | |
242 { | |
243 if (scxx.scopesym) | |
244 { | |
245 if (!scxx.scopesym.symtab) | |
246 scxx.scopesym.symtab = new DsymbolTable(); | |
13 | 247 em.addMember(sce, scxx.scopesym, true); |
0 | 248 break; |
249 } | |
250 } | |
251 } | |
252 else | |
13 | 253 em.addMember(sc, this, true); |
0 | 254 |
255 /* Compute .min, .max and .default values. | |
256 * If enum doesn't have a name, we can never identify the enum type, | |
257 * so there is no purpose for a .min, .max or .default | |
258 */ | |
259 if (!isAnonymous()) | |
260 { | |
261 if (first) | |
262 { defaultval = e; | |
263 minval = e; | |
264 maxval = e; | |
265 } | |
266 else | |
267 { Expression ec; | |
268 | |
269 /* In order to work successfully with UDTs, | |
270 * build expressions to do the comparisons, | |
271 * and let the semantic analyzer and constant | |
272 * folder give us the result. | |
273 */ | |
274 | |
275 // Compute if(e < minval) | |
276 ec = new CmpExp(TOK.TOKlt, em.loc, e, minval); | |
277 ec = ec.semantic(sce); | |
278 ec = ec.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
279 if (ec.toInteger()) | |
280 minval = e; | |
281 | |
282 ec = new CmpExp(TOK.TOKgt, em.loc, e, maxval); | |
283 ec = ec.semantic(sce); | |
284 ec = ec.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
285 if (ec.toInteger()) | |
286 maxval = e; | |
287 } | |
288 } | |
289 first = 0; | |
290 } | |
291 //printf("defaultval = %lld\n", defaultval); | |
292 | |
293 //if (defaultval) printf("defaultval: %s %s\n", defaultval.toChars(), defaultval.type.toChars()); | |
294 if (sc != sce) | |
295 sce.pop(); | |
296 //members.print(); | |
297 } | |
298 | |
72 | 299 override bool oneMember(Dsymbol* ps) |
0 | 300 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
301 if (isAnonymous()) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
302 return Dsymbol.oneMembers(members, ps); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
303 return Dsymbol.oneMember(ps); |
0 | 304 } |
305 | |
72 | 306 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 307 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
308 int i; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
309 |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
310 buf.writestring("enum "); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
311 if (ident) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
312 { buf.writestring(ident.toChars()); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
313 buf.writeByte(' '); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
314 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
315 if (memtype) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
316 { |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
317 buf.writestring(": "); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
318 memtype.toCBuffer(buf, null, hgs); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
319 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
320 if (!members) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
321 { |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
322 buf.writeByte(';'); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
323 buf.writenl(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
324 return; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
325 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
326 buf.writenl(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
327 buf.writeByte('{'); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
328 buf.writenl(); |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
329 foreach(Dsymbol s; members) |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
330 { |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
331 EnumMember em = s.isEnumMember(); |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
332 if (!em) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
333 continue; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
334 //buf.writestring(" "); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
335 em.toCBuffer(buf, hgs); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
336 buf.writeByte(','); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
337 buf.writenl(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
338 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
339 buf.writeByte('}'); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
340 buf.writenl(); |
0 | 341 } |
342 | |
72 | 343 override Type getType() |
0 | 344 { |
345 return type; | |
346 } | |
347 | |
72 | 348 override string kind() |
0 | 349 { |
350 return "enum"; | |
351 } | |
352 | |
353 version (DMDV2) { | |
72 | 354 override Dsymbol search(Loc, Identifier ident, int flags) |
0 | 355 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
356 //printf("%s.EnumDeclaration.search('%s')\n", toChars(), ident.toChars()); |
0 | 357 if (scope_) |
358 // Try one last time to resolve this enum | |
359 semantic(scope_); | |
360 | |
361 if (!members || !symtab || scope_) | |
362 { | |
363 error("is forward referenced when looking for '%s'", ident.toChars()); | |
364 //*(char*)0=0; | |
365 return null; | |
366 } | |
367 | |
368 return ScopeDsymbol.search(loc, ident, flags); | |
369 } | |
370 } | |
72 | 371 override bool isDeprecated() // is Dsymbol deprecated? |
0 | 372 { |
373 return isdeprecated; | |
374 } | |
375 | |
72 | 376 override void emitComment(Scope sc) |
0 | 377 { |
378 assert(false); | |
379 } | |
380 | |
72 | 381 override void toDocBuffer(OutBuffer buf) |
0 | 382 { |
383 assert(false); | |
384 } | |
385 | |
72 | 386 override EnumDeclaration isEnumDeclaration() { return this; } |
0 | 387 |
72 | 388 override void toObjFile(int multiobj) // compile to .obj file |
0 | 389 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
390 //printf("EnumDeclaration.toObjFile('%s')\n", toChars()); |
0 | 391 version (DMDV2) { |
392 if (isAnonymous()) | |
393 return; | |
394 } | |
395 | |
396 if (global.params.symdebug) | |
397 toDebug(); | |
398 | |
399 type.getTypeInfo(null); // generate TypeInfo | |
400 | |
401 TypeEnum tc = cast(TypeEnum)type; | |
402 if (!tc.sym.defaultval || type.isZeroInit(Loc(0))) { | |
403 ; | |
404 } else { | |
405 SC scclass = SCglobal; | |
406 if (inTemplateInstance()) | |
407 scclass = SCcomdat; | |
408 | |
409 // Generate static initializer | |
410 toInitializer(); | |
411 sinit.Sclass = scclass; | |
412 sinit.Sfl = FLdata; | |
413 version (ELFOBJ) { // Burton | |
414 sinit.Sseg = Segment.CDATA; | |
415 } | |
416 version (MACHOBJ) { | |
417 sinit.Sseg = Segment.DATA; | |
418 } | |
419 version (DMDV1) { | |
420 dtnbytes(&sinit.Sdt, tc.size(0), cast(char*)&tc.sym.defaultval); | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
421 //sinit.Sdt = tc.sym.init.toDt(); |
0 | 422 } |
423 version (DMDV2) { | |
424 tc.sym.defaultval.toDt(&sinit.Sdt); | |
425 } | |
426 outdata(sinit); | |
427 } | |
428 } | |
429 | |
430 void toDebug() | |
431 { | |
432 assert(false); | |
433 } | |
434 | |
72 | 435 override int cvMember(ubyte* p) |
0 | 436 { |
437 assert(false); | |
438 } | |
439 | |
440 Symbol* sinit; | |
441 | |
442 Symbol* toInitializer() | |
443 { | |
444 Symbol* s; | |
445 Classsym* stag; | |
446 | |
447 if (!sinit) | |
448 { | |
449 stag = fake_classsym(Id.ClassInfo); | |
450 Identifier ident_save = ident; | |
451 if (!ident) | |
452 ident = Lexer.uniqueId("__enum"); | |
453 s = toSymbolX("__init", SCextern, stag.Stype, "Z"); | |
454 ident = ident_save; | |
455 s.Sfl = FLextern; | |
456 s.Sflags |= SFLnodebug; | |
457 slist_add(s); | |
458 sinit = s; | |
459 } | |
460 | |
461 return sinit; | |
462 } | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
463 }; |