Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/enum.c Sat Sep 01 21:43:27 2007 +0200 @@ -0,0 +1,314 @@ + +// Copyright (c) 1999-2006 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include <stdio.h> +#include <assert.h> + +#include "root.h" +#include "enum.h" +#include "mtype.h" +#include "scope.h" + +/********************************* EnumDeclaration ****************************/ + +EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype) + : ScopeDsymbol(id) +{ + this->loc = loc; + type = new TypeEnum(this); + this->memtype = memtype; + maxval = 0; + minval = 0; + defaultval = 0; + sinit = NULL; +} + +Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) +{ + Type *t = NULL; + if (memtype) + t = memtype->syntaxCopy(); + + EnumDeclaration *ed; + if (s) + { ed = (EnumDeclaration *)s; + ed->memtype = t; + } + else + ed = new EnumDeclaration(loc, ident, t); + ScopeDsymbol::syntaxCopy(ed); + return ed; +} + +void EnumDeclaration::semantic(Scope *sc) +{ int i; + uinteger_t number; + Type *t; + Scope *sce; + + //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars()); + if (symtab) // if already done + return; + if (!memtype) + memtype = Type::tint32; + parent = sc->scopesym; + memtype = memtype->semantic(loc, sc); + + /* Check to see if memtype is forward referenced + */ + if (memtype->ty == Tenum) + { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc); + if (!sym->memtype) + { + error("base enum %s is forward referenced", sym->toChars()); + memtype = Type::tint32; + } + } + + if (!memtype->isintegral()) + { error("base type must be of integral type, not %s", memtype->toChars()); + memtype = Type::tint32; + } + + t = isAnonymous() ? memtype : type; + symtab = new DsymbolTable(); + sce = sc->push(this); + sce->parent = this; + number = 0; + if (!members) // enum ident; + return; + if (members->dim == 0) + error("enum %s must have at least one member", toChars()); + int first = 1; + for (i = 0; i < members->dim; i++) + { + EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); + Expression *e; + + if (!em) + /* The e->semantic(sce) can insert other symbols, such as + * template instances and function literals. + */ + continue; + + //printf("Enum member '%s'\n",em->toChars()); + e = em->value; + if (e) + { + assert(e->dyncast() == DYNCAST_EXPRESSION); + e = e->semantic(sce); + e = e->optimize(WANTvalue); + // Need to copy it because we're going to change the type + e = e->copy(); + e = e->implicitCastTo(sc, memtype); + e = e->optimize(WANTvalue); + number = e->toInteger(); + e->type = t; + } + else + { // Default is the previous number plus 1 + + // Check for overflow + if (!first) + { + switch (t->toBasetype()->ty) + { + case Tbool: + if (number == 2) goto Loverflow; + break; + + case Tint8: + if (number == 128) goto Loverflow; + break; + + case Tchar: + case Tuns8: + if (number == 256) goto Loverflow; + break; + + case Tint16: + if (number == 0x8000) goto Loverflow; + break; + + case Twchar: + case Tuns16: + if (number == 0x10000) goto Loverflow; + break; + + case Tint32: + if (number == 0x80000000) goto Loverflow; + break; + + case Tdchar: + case Tuns32: + if (number == 0x100000000LL) goto Loverflow; + break; + + case Tint64: + if (number == 0x8000000000000000LL) goto Loverflow; + break; + + case Tuns64: + if (number == 0) goto Loverflow; + break; + + Loverflow: + error("overflow of enum value"); + break; + + default: + assert(0); + } + } + e = new IntegerExp(em->loc, number, t); + } + em->value = e; + + // Add to symbol table only after evaluating 'value' + if (isAnonymous()) + { + //sce->enclosing->insert(em); + for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing) + { + if (scx->scopesym) + { + if (!scx->scopesym->symtab) + scx->scopesym->symtab = new DsymbolTable(); + em->addMember(sce, scx->scopesym, 1); + break; + } + } + } + else + em->addMember(sc, this, 1); + + if (first) + { first = 0; + defaultval = number; + minval = number; + maxval = number; + } + else if (memtype->isunsigned()) + { + if (number < minval) + minval = number; + if (number > maxval) + maxval = number; + } + else + { + if ((sinteger_t)number < (sinteger_t)minval) + minval = number; + if ((sinteger_t)number > (sinteger_t)maxval) + maxval = number; + } + + number++; + } + //printf("defaultval = %lld\n", defaultval); + + sce->pop(); + //members->print(); +} + +int EnumDeclaration::oneMember(Dsymbol **ps) +{ + if (isAnonymous()) + return Dsymbol::oneMembers(members, ps); + return Dsymbol::oneMember(ps); +} + +void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ int i; + + buf->writestring("enum "); + if (ident) + { buf->writestring(ident->toChars()); + buf->writeByte(' '); + } + if (memtype) + { + buf->writestring(": "); + memtype->toCBuffer(buf, NULL, hgs); + } + if (!members) + { + buf->writeByte(';'); + buf->writenl(); + return; + } + buf->writenl(); + buf->writeByte('{'); + buf->writenl(); + for (i = 0; i < members->dim; i++) + { + EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); + if (!em) + continue; + //buf->writestring(" "); + em->toCBuffer(buf, hgs); + buf->writeByte(','); + buf->writenl(); + } + buf->writeByte('}'); + buf->writenl(); +} + +Type *EnumDeclaration::getType() +{ + return type; +} + +char *EnumDeclaration::kind() +{ + return "enum"; +} + +/********************************* EnumMember ****************************/ + +EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value) + : Dsymbol(id) +{ + this->value = value; + this->loc = loc; +} + +Dsymbol *EnumMember::syntaxCopy(Dsymbol *s) +{ + Expression *e = NULL; + if (value) + e = value->syntaxCopy(); + + EnumMember *em; + if (s) + { em = (EnumMember *)s; + em->loc = loc; + em->value = e; + } + else + em = new EnumMember(loc, ident, e); + return em; +} + +void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring(ident->toChars()); + if (value) + { + buf->writestring(" = "); + value->toCBuffer(buf, hgs); + } +} + +char *EnumMember::kind() +{ + return "enum member"; +} + +