comparison dmd2/enum.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 638d16625da2
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1
2 // Copyright (c) 1999-2008 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <assert.h>
12
13 #include "root.h"
14 #include "enum.h"
15 #include "mtype.h"
16 #include "scope.h"
17 #include "id.h"
18 #include "expression.h"
19 #include "module.h"
20 #include "declaration.h"
21
22 /********************************* EnumDeclaration ****************************/
23
24 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
25 : ScopeDsymbol(id)
26 {
27 this->loc = loc;
28 type = new TypeEnum(this);
29 this->memtype = memtype;
30 maxval = NULL;
31 minval = NULL;
32 defaultval = NULL;
33 sinit = NULL;
34 scope = NULL;
35 isdeprecated = 0;
36 }
37
38 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
39 {
40 Type *t = NULL;
41 if (memtype)
42 t = memtype->syntaxCopy();
43
44 EnumDeclaration *ed;
45 if (s)
46 { ed = (EnumDeclaration *)s;
47 ed->memtype = t;
48 }
49 else
50 ed = new EnumDeclaration(loc, ident, t);
51 ScopeDsymbol::syntaxCopy(ed);
52 return ed;
53 }
54
55 void EnumDeclaration::semantic(Scope *sc)
56 {
57 Type *t;
58 Scope *sce;
59
60 //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
61 //printf("EnumDeclaration::semantic() %s\n", toChars());
62 if (!members) // enum ident;
63 return;
64
65 if (!memtype && !isAnonymous())
66 { // Set memtype if we can to reduce fwd reference errors
67 memtype = Type::tint32; // case 1) enum ident { ... }
68 }
69
70 if (symtab) // if already done
71 { if (!scope)
72 return; // semantic() already completed
73 }
74 else
75 symtab = new DsymbolTable();
76
77 Scope *scx = NULL;
78 if (scope)
79 { sc = scope;
80 scx = scope; // save so we don't make redundant copies
81 scope = NULL;
82 }
83
84 if (sc->stc & STCdeprecated)
85 isdeprecated = 1;
86
87 parent = sc->parent;
88
89 /* The separate, and distinct, cases are:
90 * 1. enum { ... }
91 * 2. enum : memtype { ... }
92 * 3. enum ident { ... }
93 * 4. enum ident : memtype { ... }
94 */
95
96 if (memtype)
97 {
98 memtype = memtype->semantic(loc, sc);
99
100 /* Check to see if memtype is forward referenced
101 */
102 if (memtype->ty == Tenum)
103 { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
104 if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
105 { // memtype is forward referenced, so try again later
106 scope = scx ? scx : new Scope(*sc);
107 scope->setNoFree();
108 scope->module->addDeferredSemantic(this);
109 printf("\tdeferring %s\n", toChars());
110 return;
111 }
112 }
113 #if 0 // Decided to abandon this restriction for D 2.0
114 if (!memtype->isintegral())
115 { error("base type must be of integral type, not %s", memtype->toChars());
116 memtype = Type::tint32;
117 }
118 #endif
119 }
120
121 type = type->semantic(loc, sc);
122 if (isAnonymous())
123 sce = sc;
124 else
125 { sce = sc->push(this);
126 sce->parent = this;
127 }
128 if (members->dim == 0)
129 error("enum %s must have at least one member", toChars());
130 int first = 1;
131 Expression *elast = NULL;
132 for (int i = 0; i < members->dim; i++)
133 {
134 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
135 Expression *e;
136
137 if (!em)
138 /* The e->semantic(sce) can insert other symbols, such as
139 * template instances and function literals.
140 */
141 continue;
142
143 //printf(" Enum member '%s'\n",em->toChars());
144 if (em->type)
145 em->type = em->type->semantic(em->loc, sce);
146 e = em->value;
147 if (e)
148 {
149 assert(e->dyncast() == DYNCAST_EXPRESSION);
150 e = e->semantic(sce);
151 e = e->optimize(WANTvalue | WANTinterpret);
152 if (memtype)
153 {
154 e = e->implicitCastTo(sce, memtype);
155 e = e->optimize(WANTvalue | WANTinterpret);
156 if (!isAnonymous())
157 e = e->castTo(sce, type);
158 t = memtype;
159 }
160 else if (em->type)
161 {
162 e = e->implicitCastTo(sce, em->type);
163 e = e->optimize(WANTvalue | WANTinterpret);
164 assert(isAnonymous());
165 t = e->type;
166 }
167 else
168 t = e->type;
169 }
170 else if (first)
171 {
172 if (memtype)
173 t = memtype;
174 else if (em->type)
175 t = em->type;
176 else
177 t = Type::tint32;
178 e = new IntegerExp(em->loc, 0, Type::tint32);
179 e = e->implicitCastTo(sce, t);
180 e = e->optimize(WANTvalue | WANTinterpret);
181 if (!isAnonymous())
182 e = e->castTo(sce, type);
183 }
184 else
185 {
186 // Set value to (elast + 1).
187 // But first check that (elast != t.max)
188 assert(elast);
189 e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
190 e = e->semantic(sce);
191 e = e->optimize(WANTvalue | WANTinterpret);
192 if (e->toInteger())
193 error("overflow of enum value %s", elast->toChars());
194
195 // Now set e to (elast + 1)
196 e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
197 e = e->semantic(sce);
198 e = e->castTo(sce, elast->type);
199 e = e->optimize(WANTvalue | WANTinterpret);
200 }
201 elast = e;
202 em->value = e;
203
204 // Add to symbol table only after evaluating 'value'
205 if (isAnonymous())
206 {
207 /* Anonymous enum members get added to enclosing scope.
208 */
209 for (Scope *scx = sce; scx; scx = scx->enclosing)
210 {
211 if (scx->scopesym)
212 {
213 if (!scx->scopesym->symtab)
214 scx->scopesym->symtab = new DsymbolTable();
215 em->addMember(sce, scx->scopesym, 1);
216 break;
217 }
218 }
219 }
220 else
221 em->addMember(sc, this, 1);
222
223 /* Compute .min, .max and .default values.
224 * If enum doesn't have a name, we can never identify the enum type,
225 * so there is no purpose for a .min, .max or .default
226 */
227 if (!isAnonymous())
228 {
229 if (first)
230 { defaultval = e;
231 minval = e;
232 maxval = e;
233 }
234 else
235 { Expression *ec;
236
237 /* In order to work successfully with UDTs,
238 * build expressions to do the comparisons,
239 * and let the semantic analyzer and constant
240 * folder give us the result.
241 */
242
243 // Compute if(e < minval)
244 ec = new CmpExp(TOKlt, em->loc, e, minval);
245 ec = ec->semantic(sce);
246 ec = ec->optimize(WANTvalue | WANTinterpret);
247 if (ec->toInteger())
248 minval = e;
249
250 ec = new CmpExp(TOKgt, em->loc, e, maxval);
251 ec = ec->semantic(sce);
252 ec = ec->optimize(WANTvalue | WANTinterpret);
253 if (ec->toInteger())
254 maxval = e;
255 }
256 }
257 first = 0;
258 }
259 //printf("defaultval = %lld\n", defaultval);
260
261 //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
262 if (sc != sce)
263 sce->pop();
264 //members->print();
265 }
266
267 int EnumDeclaration::oneMember(Dsymbol **ps)
268 {
269 if (isAnonymous())
270 return Dsymbol::oneMembers(members, ps);
271 return Dsymbol::oneMember(ps);
272 }
273
274 void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
275 { int i;
276
277 buf->writestring("enum ");
278 if (ident)
279 { buf->writestring(ident->toChars());
280 buf->writeByte(' ');
281 }
282 if (memtype)
283 {
284 buf->writestring(": ");
285 memtype->toCBuffer(buf, NULL, hgs);
286 }
287 if (!members)
288 {
289 buf->writeByte(';');
290 buf->writenl();
291 return;
292 }
293 buf->writenl();
294 buf->writeByte('{');
295 buf->writenl();
296 for (i = 0; i < members->dim; i++)
297 {
298 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
299 if (!em)
300 continue;
301 //buf->writestring(" ");
302 em->toCBuffer(buf, hgs);
303 buf->writeByte(',');
304 buf->writenl();
305 }
306 buf->writeByte('}');
307 buf->writenl();
308 }
309
310 Type *EnumDeclaration::getType()
311 {
312 return type;
313 }
314
315 const char *EnumDeclaration::kind()
316 {
317 return "enum";
318 }
319
320 int EnumDeclaration::isDeprecated()
321 {
322 return isdeprecated;
323 }
324
325 Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
326 {
327 //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
328 if (scope)
329 // Try one last time to resolve this enum
330 semantic(scope);
331
332 if (!members || !symtab || scope)
333 { error("is forward referenced when looking for '%s'", ident->toChars());
334 //*(char*)0=0;
335 return NULL;
336 }
337
338 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
339 return s;
340 }
341
342 /********************************* EnumMember ****************************/
343
344 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
345 : Dsymbol(id)
346 {
347 this->value = value;
348 this->type = type;
349 this->loc = loc;
350 }
351
352 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
353 {
354 Expression *e = NULL;
355 if (value)
356 e = value->syntaxCopy();
357
358 Type *t = NULL;
359 if (type)
360 t = type->syntaxCopy();
361
362 EnumMember *em;
363 if (s)
364 { em = (EnumMember *)s;
365 em->loc = loc;
366 em->value = e;
367 em->type = t;
368 }
369 else
370 em = new EnumMember(loc, ident, e, t);
371 return em;
372 }
373
374 void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
375 {
376 if (type)
377 type->toCBuffer(buf, ident, hgs);
378 else
379 buf->writestring(ident->toChars());
380 if (value)
381 {
382 buf->writestring(" = ");
383 value->toCBuffer(buf, hgs);
384 }
385 }
386
387 const char *EnumMember::kind()
388 {
389 return "enum member";
390 }
391
392