root/branches/dmdfe/enum.c

Revision 656, 6.3 kB (checked in by Gregor, 1 year ago)

MERGE: DMD 1.014

Line 
1 // Copyright (c) 1999-2006 by Digital Mars
2 // All Rights Reserved
3 // written by Walter Bright
4 // http://www.digitalmars.com
5 // License for redistribution is by either the Artistic License
6 // in artistic.txt, or the GNU General Public License in gnu.txt.
7 // See the included readme.txt for details.
8
9 #include <stdio.h>
10 #include <assert.h>
11
12 #include "root.h"
13 #include "enum.h"
14 #include "mtype.h"
15 #include "scope.h"
16
17 /********************************* EnumDeclaration ****************************/
18
19 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
20     : ScopeDsymbol(id)
21 {
22     this->loc = loc;
23     type = new TypeEnum(this);
24     this->memtype = memtype;
25     maxval = 0;
26     minval = 0;
27     defaultval = 0;
28     sinit = NULL;
29 }
30
31 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
32 {
33     Type *t = NULL;
34     if (memtype)
35     t = memtype->syntaxCopy();
36
37     EnumDeclaration *ed;
38     if (s)
39     {   ed = (EnumDeclaration *)s;
40     ed->memtype = t;
41     }
42     else
43     ed = new EnumDeclaration(loc, ident, t);
44     ScopeDsymbol::syntaxCopy(ed);
45     return ed;
46 }
47
48 void EnumDeclaration::semantic(Scope *sc)
49 {   int i;
50     uinteger_t number;
51     Type *t;
52     Scope *sce;
53
54     //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars());
55     if (symtab)         // if already done
56     return;
57     if (!memtype)
58     memtype = Type::tint32;
59     parent = sc->scopesym;
60     memtype = memtype->semantic(loc, sc);
61
62     /* Check to see if memtype is forward referenced
63      */
64     if (memtype->ty == Tenum)
65     {   EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
66     if (!sym->memtype)
67     {
68         error("base enum %s is forward referenced", sym->toChars());
69         memtype = Type::tint32;
70     }
71     }
72
73     if (!memtype->isintegral())
74     {   error("base type must be of integral type, not %s", memtype->toChars());
75     memtype = Type::tint32;
76     }
77
78     t = isAnonymous() ? memtype : type;
79     symtab = new DsymbolTable();
80     sce = sc->push(this);
81     sce->parent = this;
82     number = 0;
83     if (!members)       // enum ident;
84     return;
85     if (members->dim == 0)
86     error("enum %s must have at least one member", toChars());
87     int first = 1;
88     for (i = 0; i < members->dim; i++)
89     {
90     EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
91     Expression *e;
92
93     if (!em)
94         /* The e->semantic(sce) can insert other symbols, such as
95          * template instances and function literals.
96          */
97         continue;
98
99     //printf("Enum member '%s'\n",em->toChars());
100     e = em->value;
101     if (e)
102     {
103         assert(e->dyncast() == DYNCAST_EXPRESSION);
104         e = e->semantic(sce);
105         e = e->optimize(WANTvalue);
106         // Need to copy it because we're going to change the type
107         e = e->copy();
108         e = e->implicitCastTo(sc, memtype);
109         e = e->optimize(WANTvalue);
110         number = e->toInteger();
111         e->type = t;
112     }
113     else
114     {   // Default is the previous number plus 1
115
116         // Check for overflow
117         if (!first)
118         {
119         switch (t->toBasetype()->ty)
120         {
121             case Tbool:
122             if (number == 2)    goto Loverflow;
123             break;
124
125             case Tint8:
126             if (number == 128) goto Loverflow;
127             break;
128
129             case Tchar:
130             case Tuns8:
131             if (number == 256) goto Loverflow;
132             break;
133
134             case Tint16:
135             if (number == 0x8000) goto Loverflow;
136             break;
137
138             case Twchar:
139             case Tuns16:
140             if (number == 0x10000) goto Loverflow;
141             break;
142
143             case Tint32:
144             if (number == 0x80000000) goto Loverflow;
145             break;
146
147             case Tdchar:
148             case Tuns32:
149             if (number == 0x100000000LL) goto Loverflow;
150             break;
151
152             case Tint64:
153             if (number == 0x8000000000000000LL) goto Loverflow;
154             break;
155
156             case Tuns64:
157             if (number == 0) goto Loverflow;
158             break;
159
160             Loverflow:
161             error("overflow of enum value");
162             break;
163
164             default:
165             assert(0);
166         }
167         }
168         e = new IntegerExp(em->loc, number, t);
169     }
170     em->value = e;
171
172     // Add to symbol table only after evaluating 'value'
173     if (isAnonymous())
174     {
175         //sce->enclosing->insert(em);
176         for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing)
177         {
178         if (scx->scopesym)
179         {
180             if (!scx->scopesym->symtab)
181             scx->scopesym->symtab = new DsymbolTable();
182             em->addMember(sce, scx->scopesym, 1);
183             break;
184         }
185         }
186     }
187     else
188         em->addMember(sc, this, 1);
189
190     if (first)
191     {   first = 0;
192         defaultval = number;
193         minval = number;
194         maxval = number;
195     }
196     else if (memtype->isunsigned())
197     {
198         if (number < minval)
199         minval = number;
200         if (number > maxval)
201         maxval = number;
202     }
203     else
204     {
205         if ((sinteger_t)number < (sinteger_t)minval)
206         minval = number;
207         if ((sinteger_t)number > (sinteger_t)maxval)
208         maxval = number;
209     }
210
211     number++;
212     }
213     //printf("defaultval = %lld\n", defaultval);
214
215     sce->pop();
216     //members->print();
217 }
218
219 int EnumDeclaration::oneMember(Dsymbol **ps)
220 {
221     if (isAnonymous())
222     return Dsymbol::oneMembers(members, ps);
223     return Dsymbol::oneMember(ps);
224 }
225
226 void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
227 {   int i;
228
229     buf->writestring("enum ");
230     if (ident)
231     {   buf->writestring(ident->toChars());
232     buf->writeByte(' ');
233     }
234     if (memtype)
235     {
236     buf->writestring(": ");
237     memtype->toCBuffer(buf, NULL, hgs);
238     }
239     if (!members)
240     {
241     buf->writeByte(';');
242     buf->writenl();
243     return;
244     }
245     buf->writenl();
246     buf->writeByte('{');
247     buf->writenl();
248     for (i = 0; i < members->dim; i++)
249     {
250     EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
251     if (!em)
252         continue;
253     //buf->writestring("    ");
254     em->toCBuffer(buf, hgs);
255     buf->writeByte(',');
256     buf->writenl();
257     }
258     buf->writeByte('}');
259     buf->writenl();
260 }
261
262 Type *EnumDeclaration::getType()
263 {
264     return type;
265 }
266
267 char *EnumDeclaration::kind()
268 {
269     return "enum";
270 }
271
272 /********************************* EnumMember ****************************/
273
274 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value)
275     : Dsymbol(id)
276 {
277     this->value = value;
278     this->loc = loc;
279 }
280
281 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
282 {
283     Expression *e = NULL;
284     if (value)
285     e = value->syntaxCopy();
286
287     EnumMember *em;
288     if (s)
289     {   em = (EnumMember *)s;
290     em->loc = loc;
291     em->value = e;
292     }
293     else
294     em = new EnumMember(loc, ident, e);
295     return em;
296 }
297
298 void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
299 {
300     buf->writestring(ident->toChars());
301     if (value)
302     {
303     buf->writestring(" = ");
304     value->toCBuffer(buf, hgs);
305     }
306 }
307
308 char *EnumMember::kind()
309 {
310     return "enum member";
311 }
Note: See TracBrowser for help on using the browser.