comparison dmd/enum.c @ 1:c53b6e3fe49a trunk

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