Merged Delight changes to D1 into D2
[delight/core.git] / dmd / enum.c
blob09036efbb47e029cddc3736e45203a7f7db29ded
2 // Copyright (c) 1999-2006 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.
10 /* NOTE: This file has been patched from the original DMD distribution to
11 work with the GDC compiler.
13 Modified by David Friedman, December 2006
16 #include <stdio.h>
17 #include <assert.h>
19 #include "root.h"
20 #include "enum.h"
21 #include "mtype.h"
22 #include "scope.h"
24 /********************************* EnumDeclaration ****************************/
26 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
27 : ScopeDsymbol(id)
29 this->loc = loc;
30 type = new TypeEnum(this);
31 this->memtype = memtype;
32 maxval = 0;
33 minval = 0;
34 defaultval = 0;
35 sinit = NULL;
36 attributes = NULL;
39 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
41 Type *t = NULL;
42 if (memtype)
43 t = memtype->syntaxCopy();
45 EnumDeclaration *ed;
46 if (s)
47 { ed = (EnumDeclaration *)s;
48 ed->memtype = t;
50 else
51 ed = new EnumDeclaration(loc, ident, t);
52 ScopeDsymbol::syntaxCopy(ed);
53 return ed;
56 void EnumDeclaration::semantic(Scope *sc)
57 { int i;
58 uinteger_t number;
59 Type *t;
60 Scope *sce;
62 //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars());
63 if (symtab) // if already done
64 return;
65 if (!memtype)
66 memtype = Type::tint32;
67 parent = sc->scopesym;
68 if (attributes)
69 attributes->append(sc->attributes);
70 else
71 attributes = sc->attributes;
72 memtype = memtype->semantic(loc, sc);
74 /* Check to see if memtype is forward referenced
76 if (memtype->ty == Tenum)
77 { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
78 if (!sym->memtype)
80 error("base enum %s is forward referenced", sym->toChars());
81 memtype = Type::tint32;
85 if (!memtype->isintegral())
86 { error("base type must be of integral type, not %s", memtype->toChars());
87 memtype = Type::tint32;
90 t = isAnonymous() ? memtype : type;
91 symtab = new DsymbolTable();
92 sce = sc->push(this);
93 sce->parent = this;
94 number = 0;
95 if (!members) // enum ident;
96 return;
97 if (members->dim == 0)
98 error("enum %s must have at least one member", toChars());
99 int first = 1;
100 for (i = 0; i < members->dim; i++)
102 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
103 Expression *e;
105 if (!em)
106 /* The e->semantic(sce) can insert other symbols, such as
107 * template instances and function literals.
109 continue;
111 //printf("Enum member '%s'\n",em->toChars());
112 e = em->value;
113 if (e)
115 assert(e->dyncast() == DYNCAST_EXPRESSION);
116 e = e->semantic(sce);
117 e = e->optimize(WANTvalue);
118 // Need to copy it because we're going to change the type
119 e = e->copy();
120 e = e->implicitCastTo(sc, memtype);
121 e = e->optimize(WANTvalue);
122 number = e->toInteger();
123 e->type = t;
125 else
126 { // Default is the previous number plus 1
128 // Check for overflow
129 if (!first)
131 switch (t->toBasetype()->ty)
133 case Tbool:
134 if (number == 2) goto Loverflow;
135 break;
137 case Tint8:
138 if (number == 128) goto Loverflow;
139 break;
141 case Tchar:
142 case Tuns8:
143 if (number == 256) goto Loverflow;
144 break;
146 case Tint16:
147 if (number == 0x8000) goto Loverflow;
148 break;
150 case Twchar:
151 case Tuns16:
152 if (number == 0x10000) goto Loverflow;
153 break;
155 case Tint32:
156 if (number == 0x80000000) goto Loverflow;
157 break;
159 case Tdchar:
160 case Tuns32:
161 if (number == 0x100000000LL) goto Loverflow;
162 break;
164 case Tint64:
165 if (number == 0x8000000000000000LL) goto Loverflow;
166 break;
168 case Tuns64:
169 if (number == 0) goto Loverflow;
170 break;
172 Loverflow:
173 error("overflow of enum value");
174 break;
176 default:
177 assert(0);
180 e = new IntegerExp(em->loc, number, t);
182 em->value = e;
184 // Add to symbol table only after evaluating 'value'
185 if (isAnonymous())
187 //sce->enclosing->insert(em);
188 for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing)
190 if (scx->scopesym)
192 if (!scx->scopesym->symtab)
193 scx->scopesym->symtab = new DsymbolTable();
194 em->addMember(sce, scx->scopesym, 1);
195 break;
199 else
200 em->addMember(sc, this, 1);
202 if (first)
203 { first = 0;
204 defaultval = number;
205 minval = number;
206 maxval = number;
208 else if (memtype->isunsigned())
210 if (number < minval)
211 minval = number;
212 if (number > maxval)
213 maxval = number;
215 else
217 if ((sinteger_t)number < (sinteger_t)minval)
218 minval = number;
219 if ((sinteger_t)number > (sinteger_t)maxval)
220 maxval = number;
223 number++;
225 //printf("defaultval = %lld\n", defaultval);
227 sce->pop();
228 //members->print();
231 int EnumDeclaration::oneMember(Dsymbol **ps)
233 if (isAnonymous())
234 return Dsymbol::oneMembers(members, ps);
235 return Dsymbol::oneMember(ps);
238 void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
239 { int i;
241 buf->writestring("enum ");
242 if (ident)
243 { buf->writestring(ident->toChars());
244 buf->writeByte(' ');
246 if (memtype)
248 buf->writestring(": ");
249 memtype->toCBuffer(buf, NULL, hgs);
251 if (!members)
253 buf->writeByte(';');
254 buf->writenl();
255 return;
257 buf->writenl();
258 buf->writeByte('{');
259 buf->writenl();
260 for (i = 0; i < members->dim; i++)
262 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
263 if (!em)
264 continue;
265 //buf->writestring(" ");
266 em->toCBuffer(buf, hgs);
267 buf->writeByte(',');
268 buf->writenl();
270 buf->writeByte('}');
271 buf->writenl();
274 Type *EnumDeclaration::getType()
276 return type;
279 char *EnumDeclaration::kind()
281 return "enum";
284 /********************************* EnumMember ****************************/
286 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value)
287 : Dsymbol(id)
289 this->value = value;
290 this->loc = loc;
293 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
295 Expression *e = NULL;
296 if (value)
297 e = value->syntaxCopy();
299 EnumMember *em;
300 if (s)
301 { em = (EnumMember *)s;
302 em->loc = loc;
303 em->value = e;
305 else
306 em = new EnumMember(loc, ident, e);
307 return em;
310 void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
312 buf->writestring(ident->toChars());
313 if (value)
315 buf->writestring(" = ");
316 value->toCBuffer(buf, hgs);
320 char *EnumMember::kind()
322 return "enum member";