Mercurial > projects > ldc
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 |