diff -uNr dmd-0.123/dmd/src/dmd/attrib.c dmd-0.124/dmd/src/dmd/attrib.c --- dmd-0.123/dmd/src/dmd/attrib.c 2005-04-25 10:51:08.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/attrib.c 2005-05-15 01:05:46.000000000 +0200 @@ -20,7 +20,7 @@ #include "init.h" #include "declaration.h" #include "attrib.h" -#include "debcond.h" +#include "cond.h" #include "scope.h" #include "id.h" #include "expression.h" @@ -29,6 +29,7 @@ extern void obj_includelib(char *name); + /********************************* AttribDeclaration ****************************/ AttribDeclaration::AttribDeclaration(Array *decl) @@ -37,15 +38,15 @@ this->decl = decl; } -Array *AttribDeclaration::include() +Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) { return decl; } -void AttribDeclaration::addMember(ScopeDsymbol *sd) +void AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd) { unsigned i; - Array *d = include(); + Array *d = include(sc, sd); if (d) { @@ -53,14 +54,14 @@ { Dsymbol *s; s = (Dsymbol *)d->data[i]; - s->addMember(sd); + s->addMember(sc, sd); } } } void AttribDeclaration::semantic(Scope *sc) { - Array *d = include(); + Array *d = include(sc, NULL); //printf("\tAttribDeclaration::semantic '%s'\n",toChars()); if (d) @@ -77,7 +78,7 @@ void AttribDeclaration::semantic2(Scope *sc) { unsigned i; - Array *d = include(); + Array *d = include(sc, NULL); if (d) { @@ -93,7 +94,7 @@ void AttribDeclaration::semantic3(Scope *sc) { unsigned i; - Array *d = include(); + Array *d = include(sc, NULL); if (d) { @@ -109,7 +110,7 @@ void AttribDeclaration::inlineScan() { unsigned i; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -126,7 +127,7 @@ void AttribDeclaration::toObjFile() { unsigned i; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -144,7 +145,7 @@ unsigned i; int nwritten = 0; int n; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -168,7 +169,7 @@ Dsymbol *AttribDeclaration::oneMember() { Dsymbol *s; - Array *d = include(); + Array *d = include(NULL, NULL); if (d && d->dim == 1) { s = (Dsymbol *)d->data[0]; @@ -182,7 +183,7 @@ void AttribDeclaration::addLocalClass(Array *aclasses) { unsigned i; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -667,45 +668,40 @@ } -/********************************* DebugDeclaration ****************************/ +/********************************* ConditionalDeclaration ****************************/ -DebugDeclaration::DebugDeclaration(Condition *condition, Array *decl, Array *elsedecl) +ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl) : AttribDeclaration(decl) { - //printf("DebugDeclaration::DebugDeclaration()\n"); + //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); this->condition = condition; this->elsedecl = elsedecl; } -Dsymbol *DebugDeclaration::syntaxCopy(Dsymbol *s) +Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s) { - DebugDeclaration *dd; + ConditionalDeclaration *dd; assert(!s); - dd = new DebugDeclaration(condition, + dd = new ConditionalDeclaration(condition->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl), Dsymbol::arraySyntaxCopy(elsedecl)); return dd; } -// Decide if debug code should be included +// Decide if 'then' or 'else' code should be included -Array *DebugDeclaration::include() +Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) { assert(condition); - return condition->include() ? decl : elsedecl; + return condition->include(sc, sd) ? decl : elsedecl; } -void DebugDeclaration::toCBuffer(OutBuffer *buf) +void ConditionalDeclaration::toCBuffer(OutBuffer *buf) { - if (isVersionDeclaration()) - buf->writestring("version("); - else - buf->writestring("debug("); condition->toCBuffer(buf); - buf->writeByte(')'); if (decl || elsedecl) { buf->writenl(); @@ -745,23 +741,3 @@ } -/********************************* VersionDeclaration ****************************/ - -VersionDeclaration::VersionDeclaration(Condition *condition, Array *decl, Array *elsedecl) - : DebugDeclaration(condition, decl, elsedecl) -{ - //printf("VersionDeclaration::VersionDeclaration()\n"); -} - -Dsymbol *VersionDeclaration::syntaxCopy(Dsymbol *s) -{ - VersionDeclaration *vd; - - assert(!s); - vd = new VersionDeclaration(condition, - Dsymbol::arraySyntaxCopy(decl), - Dsymbol::arraySyntaxCopy(elsedecl)); - return vd; -} - - diff -uNr dmd-0.123/dmd/src/dmd/attrib.h dmd-0.124/dmd/src/dmd/attrib.h --- dmd-0.123/dmd/src/dmd/attrib.h 2005-04-25 10:48:38.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/attrib.h 2005-05-15 01:04:54.000000000 +0200 @@ -30,8 +30,8 @@ Array *decl; // array of Dsymbol's AttribDeclaration(Array *decl); - virtual Array *include(); - void addMember(ScopeDsymbol *s); + virtual Array *include(Scope *sc, ScopeDsymbol *s); + void addMember(Scope *sc, ScopeDsymbol *s); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); @@ -110,23 +110,15 @@ void toObjFile(); // compile to .obj file }; -struct DebugDeclaration : AttribDeclaration +struct ConditionalDeclaration : AttribDeclaration { Condition *condition; Array *elsedecl; // array of Dsymbol's for else block - DebugDeclaration(Condition *condition, Array *decl, Array *elsedecl); + ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl); Dsymbol *syntaxCopy(Dsymbol *s); - Array *include(); + Array *include(Scope *sc, ScopeDsymbol *s); void toCBuffer(OutBuffer *buf); }; -struct VersionDeclaration : DebugDeclaration -{ - VersionDeclaration(Condition *condition, Array *decl, Array *elsedecl); - Dsymbol *syntaxCopy(Dsymbol *s); - - VersionDeclaration *isVersionDeclaration() { return this; } -}; - #endif /* DMD_ATTRIB_H */ diff -uNr dmd-0.123/dmd/src/dmd/class.c dmd-0.124/dmd/src/dmd/class.c --- dmd-0.123/dmd/src/dmd/class.c 2005-05-08 16:42:44.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/class.c 2005-05-12 18:50:32.000000000 +0200 @@ -308,7 +308,7 @@ for (i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; - s->addMember(this); + s->addMember(sc, this); } } @@ -395,7 +395,7 @@ ctor = new CtorDeclaration(0, 0, NULL, 0); ctor->fbody = new CompoundStatement(0, new Array()); members->push(ctor); - ctor->addMember(this); + ctor->addMember(sc, this); *sc = scsave; sc->offset = structsize; ctor->semantic(sc); @@ -810,7 +810,7 @@ for (i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; - s->addMember(this); + s->addMember(sc, this); } sc = sc->push(this); diff -uNr dmd-0.123/dmd/src/dmd/cond.c dmd-0.124/dmd/src/dmd/cond.c --- dmd-0.123/dmd/src/dmd/cond.c 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.124/dmd/src/dmd/cond.c 2005-05-15 11:56:00.000000000 +0200 @@ -0,0 +1,338 @@ + +// Copyright (c) 1999-2005 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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 +#include + +#include "id.h" +#include "init.h" +#include "declaration.h" +#include "identifier.h" +#include "expression.h" +#include "cond.h" +#include "module.h" +#include "template.h" + +int findCondition(Array *ids, Identifier *ident) +{ + if (ids) + { + for (int i = 0; i < ids->dim; i++) + { + char *id = (char *)ids->data[i]; + + if (strcmp(id, ident->toChars()) == 0) + return TRUE; + } + } + + return FALSE; +} + +/* ============================================================ */ + +Condition::Condition(Loc loc) +{ + this->loc = loc; + inc = 0; +} + +/* ============================================================ */ + +DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident) + : Condition(0) +{ + this->mod = mod; + this->level = level; + this->ident = ident; +} + +Condition *DVCondition::syntaxCopy() +{ + return this; // don't need to copy +} + +/* ============================================================ */ + +void DebugCondition::setGlobalLevel(unsigned level) +{ + global.params.debuglevel = level; +} + +void DebugCondition::addGlobalIdent(char *ident) +{ + if (!global.params.debugids) + global.params.debugids = new Array(); + global.params.debugids->push(ident); +} + + +DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) + : DVCondition(mod, level, ident) +{ +} + +int DebugCondition::include(Scope *sc, ScopeDsymbol *s) +{ + //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); + if (inc == 0) + { + inc = 2; + if (ident) + { + if (findCondition(mod->debugids, ident)) + inc = 1; + else if (findCondition(global.params.debugids, ident)) + inc = 1; + } + else if (level <= global.params.debuglevel || level <= mod->debuglevel) + inc = 1; + } + return (inc == 1); +} + +void DebugCondition::toCBuffer(OutBuffer *buf) +{ + if (ident) + buf->printf("debug (%s)", ident->toChars()); + else + buf->printf("debug (%u)", level); +} + +/* ============================================================ */ + +void VersionCondition::setGlobalLevel(unsigned level) +{ + global.params.versionlevel = level; +} + +void VersionCondition::checkPredefined(Loc loc, char *ident) +{ + static char* reserved[] = + { + "DigitalMars", "X86", "X86_64", + "Windows", "Win32", "Win64", + "linux", + "LittleEndian", "BigEndian", + "all", + "none", + }; + + for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) + { + if (strcmp(ident, reserved[i]) == 0) + goto Lerror; + } + + if (ident[0] == 'D' && ident[1] == '_') + goto Lerror; + + return; + + Lerror: + error(loc, "version identifier '%s' is reserved and cannot be set", ident); +} + +void VersionCondition::addGlobalIdent(char *ident) +{ + checkPredefined(0, ident); + addPredefinedGlobalIdent(ident); +} + +void VersionCondition::addPredefinedGlobalIdent(char *ident) +{ + if (!global.params.versionids) + global.params.versionids = new Array(); + global.params.versionids->push(ident); +} + + +VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) + : DVCondition(mod, level, ident) +{ +} + +int VersionCondition::include(Scope *sc, ScopeDsymbol *s) +{ + //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); + if (inc == 0) + { + inc = 2; + if (ident) + { + if (findCondition(mod->versionids, ident)) + inc = 1; + else if (findCondition(global.params.versionids, ident)) + inc = 1; + } + else if (level <= global.params.versionlevel || level <= mod->versionlevel) + inc = 1; + } + return (inc == 1); +} + +void VersionCondition::toCBuffer(OutBuffer *buf) +{ + if (ident) + buf->printf("version (%s)", ident->toChars()); + else + buf->printf("version (%u)", level); +} + + +/**************************** StaticIfCondition *******************************/ + +StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp) + : Condition(loc) +{ + this->exp = exp; +} + +Condition *StaticIfCondition::syntaxCopy() +{ + return new StaticIfCondition(loc, exp->syntaxCopy()); +} + +int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) +{ + if (inc == 0) + { + if (!sc) + { + error(loc, "static if conditional cannot be at global scope"); + inc = 2; + return 0; + } + + Expression *e = exp->semantic(sc); + e = e->optimize(WANTvalue); + if (e->isBool(TRUE)) + inc = 1; + else if (e->isBool(FALSE)) + inc = 2; + else + { + e->error("expression %s does not evaluate to a boolean", e->toChars()); + inc = 2; + } + } + return (inc == 1); +} + +void StaticIfCondition::toCBuffer(OutBuffer *buf) +{ + buf->writestring("static if("); + exp->toCBuffer(buf); + buf->writeByte(')'); +} + + +/**************************** IftypeCondition *******************************/ + +IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, Type *tspec) + : Condition(loc) +{ + this->targ = targ; + this->id = id; + this->tspec = tspec; +} + +Condition *IftypeCondition::syntaxCopy() +{ + return new IftypeCondition(loc, + targ->syntaxCopy(), + id, + tspec ? tspec->syntaxCopy() : NULL); +} + +int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) +{ + if (inc == 0) + { + if (!sc) + { + error(loc, "iftype conditional cannot be at global scope"); + inc = 2; + return 0; + } + targ = targ->semantic(loc, sc); + + if (id && tspec) + { + /* Evaluate to TRUE if targ matches tspec. + * If TRUE, declare id as an alias for the specialized type. + */ + + MATCH m; + TemplateTypeParameter tp(loc, id, NULL, NULL); + + Array parameters; + parameters.setDim(1); + parameters.data[0] = (void *)&tp; + + Array dedtypes; + dedtypes.setDim(1); + + m = targ->deduceType(tspec, ¶meters, &dedtypes); + if (m == MATCHnomatch) + inc = 2; + else + { + inc = 1; + Type *tded = (Type *)dedtypes.data[0]; + if (!tded) + tded = targ; + Dsymbol *s = new AliasDeclaration(loc, id, tded); + s->semantic(sc); + sc->insert(s); + if (sd) + s->addMember(sc, sd); + } + } + else if (id) + { + /* Declare id as an alias for type targ. Evaluate to TRUE + */ + Dsymbol *s = new AliasDeclaration(loc, id, targ); + s->semantic(sc); + sc->insert(s); + if (sd) + s->addMember(sc, sd); + inc = 1; + } + else if (tspec) + { + /* Evaluate to TRUE if targ matches tspec + */ + tspec = tspec->semantic(loc, sc); + if (targ->equals(tspec)) + inc = 1; + else + inc = 2; + } + else + assert(0); + //printf("inc = %d\n", inc); + } + return (inc == 1); +} + +void IftypeCondition::toCBuffer(OutBuffer *buf) +{ + buf->writestring("iftype("); + targ->toCBuffer(buf, id); + if (tspec) + { + buf->writestring(" : "); + tspec->toCBuffer(buf, NULL); + } + buf->writeByte(')'); +} + + diff -uNr dmd-0.123/dmd/src/dmd/cond.h dmd-0.124/dmd/src/dmd/cond.h --- dmd-0.123/dmd/src/dmd/cond.h 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.124/dmd/src/dmd/cond.h 2005-05-15 11:54:40.000000000 +0200 @@ -0,0 +1,96 @@ + +// Copyright (c) 1999-2005 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#ifndef DMD_DEBCOND_H +#define DMD_DEBCOND_H + +struct Expression; +struct Identifier; +struct OutBuffer; +struct Module; +struct Scope; +struct ScopeDsymbol; + +struct Condition +{ + Loc loc; + int inc; // 0: not computed yet + // 1: include + // 2: do not include + + Condition(Loc loc); + + virtual Condition *syntaxCopy() = 0; + virtual int include(Scope *sc, ScopeDsymbol *s) = 0; + virtual void toCBuffer(OutBuffer *buf) = 0; +}; + +struct DVCondition : Condition +{ + unsigned level; + Identifier *ident; + Module *mod; + + DVCondition(Module *mod, unsigned level, Identifier *ident); + + Condition *syntaxCopy(); +}; + +struct DebugCondition : DVCondition +{ + static void setGlobalLevel(unsigned level); + static void addGlobalIdent(char *ident); + static void addPredefinedGlobalIdent(char *ident); + + DebugCondition(Module *mod, unsigned level, Identifier *ident); + + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + +struct VersionCondition : DVCondition +{ + static void setGlobalLevel(unsigned level); + static void checkPredefined(Loc loc, char *ident); + static void addGlobalIdent(char *ident); + static void addPredefinedGlobalIdent(char *ident); + + VersionCondition(Module *mod, unsigned level, Identifier *ident); + + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + +struct StaticIfCondition : Condition +{ + Expression *exp; + + StaticIfCondition(Loc loc, Expression *exp); + Condition *syntaxCopy(); + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + +struct IftypeCondition : Condition +{ + /* iftype (targ id : tspec) + */ + Loc loc; + Type *targ; + Identifier *id; // can be NULL + Type *tspec; // can be NULL + + IftypeCondition(Loc loc, Type *targ, Identifier *id, Type *tspec); + Condition *syntaxCopy(); + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + + +#endif diff -uNr dmd-0.123/dmd/src/dmd/constfold.c dmd-0.124/dmd/src/dmd/constfold.c --- dmd-0.123/dmd/src/dmd/constfold.c 2005-05-11 01:12:38.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/constfold.c 2005-05-17 10:35:32.000000000 +0200 @@ -351,6 +351,10 @@ n1 = e1->toInteger(); n2 = e2->toInteger(); + if (n2 == 0) + { error("divide by 0"); + n2 = 1; + } if (isunsigned()) n = ((d_uns64) n1) % ((d_uns64) n2); else @@ -504,6 +508,7 @@ real_t r1; real_t r2; + //printf("CmpExp::constFold()\n"); e1 = e1->constFold(); e2 = e2->constFold(); if (e1->type->isreal()) diff -uNr dmd-0.123/dmd/src/dmd/debcond.c dmd-0.124/dmd/src/dmd/debcond.c --- dmd-0.123/dmd/src/dmd/debcond.c 2005-04-24 02:03:28.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/debcond.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,175 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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 -#include - -#include "id.h" -#include "init.h" -#include "declaration.h" -#include "identifier.h" -#include "expression.h" -#include "debcond.h" -#include "module.h" - -int findCondition(Array *ids, Identifier *ident) -{ - if (ids) - { - for (int i = 0; i < ids->dim; i++) - { - char *id = (char *)ids->data[i]; - - if (strcmp(id, ident->toChars()) == 0) - return TRUE; - } - } - - return FALSE; -} - -/* ============================================================ */ - -Condition::Condition(Module *mod, unsigned level, Identifier *ident) -{ - this->mod = mod; - this->level = level; - this->ident = ident; -} - -int Condition::include() -{ - assert(0); - return FALSE; -} - -int Condition::isBool(int result) -{ - return (result == include()); -} - -Expression *Condition::toExpr() -{ - assert(0); // BUG: not implemented - return NULL; -} - -void Condition::toCBuffer(OutBuffer *buf) -{ - if (ident) - buf->printf("%s", ident->toChars()); - else - buf->printf("%u", level); -} - -/* ============================================================ */ - -void DebugCondition::setGlobalLevel(unsigned level) -{ - global.params.debuglevel = level; -} - -void DebugCondition::addGlobalIdent(char *ident) -{ - if (!global.params.debugids) - global.params.debugids = new Array(); - global.params.debugids->push(ident); -} - - -DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(mod, level, ident) -{ -} - -int DebugCondition::include() -{ - //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); - if (ident) - { - if (findCondition(mod->debugids, ident)) - return TRUE; - - if (findCondition(global.params.debugids, ident)) - return TRUE; - } - else if (level <= global.params.debuglevel || level <= mod->debuglevel) - return TRUE; - return FALSE; -} - -/* ============================================================ */ - -void VersionCondition::setGlobalLevel(unsigned level) -{ - global.params.versionlevel = level; -} - -void VersionCondition::checkPredefined(Loc loc, char *ident) -{ - static char* reserved[] = - { - "DigitalMars", "X86", "X86_64", - "Windows", "Win32", "Win64", - "linux", - "LittleEndian", "BigEndian", - "all", - "none", - }; - - for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) - { - if (strcmp(ident, reserved[i]) == 0) - goto Lerror; - } - - if (ident[0] == 'D' && ident[1] == '_') - goto Lerror; - - return; - - Lerror: - error(loc, "version identifier '%s' is reserved and cannot be set", ident); -} - -void VersionCondition::addGlobalIdent(char *ident) -{ - checkPredefined(0, ident); - addPredefinedGlobalIdent(ident); -} - -void VersionCondition::addPredefinedGlobalIdent(char *ident) -{ - if (!global.params.versionids) - global.params.versionids = new Array(); - global.params.versionids->push(ident); -} - - -VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(mod, level, ident) -{ -} - -int VersionCondition::include() -{ - //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); - if (ident) - { - if (findCondition(mod->versionids, ident)) - return TRUE; - - if (findCondition(global.params.versionids, ident)) - return TRUE; - } - else if (level <= global.params.versionlevel || level <= mod->versionlevel) - return TRUE; - return FALSE; -} - diff -uNr dmd-0.123/dmd/src/dmd/debcond.h dmd-0.124/dmd/src/dmd/debcond.h --- dmd-0.123/dmd/src/dmd/debcond.h 2005-04-24 02:05:46.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/debcond.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#ifndef DMD_DEBCOND_H -#define DMD_DEBCOND_H - -struct Expression; -struct Identifier; -struct OutBuffer; -struct Module; - -struct Condition -{ - unsigned level; - Identifier *ident; - Module *mod; - - Condition(Module *mod, unsigned level, Identifier *ident); - - virtual int include(); - int isBool(int result); - Expression *toExpr(); - void toCBuffer(OutBuffer *buf); -}; - -struct DebugCondition : Condition -{ - static void setGlobalLevel(unsigned level); - static void addGlobalIdent(char *ident); - static void addPredefinedGlobalIdent(char *ident); - - DebugCondition(Module *mod, unsigned level, Identifier *ident); - - int include(); -}; - -struct VersionCondition : Condition -{ - static void setGlobalLevel(unsigned level); - static void checkPredefined(Loc loc, char *ident); - static void addGlobalIdent(char *ident); - static void addPredefinedGlobalIdent(char *ident); - - VersionCondition(Module *mod, unsigned level, Identifier *ident); - - int include(); -}; - -#endif /* DMD_DEBCOND_H */ diff -uNr dmd-0.123/dmd/src/dmd/declaration.h dmd-0.124/dmd/src/dmd/declaration.h --- dmd-0.123/dmd/src/dmd/declaration.h 2005-04-24 11:21:38.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/declaration.h 2005-05-18 22:34:34.000000000 +0200 @@ -25,6 +25,7 @@ struct ForeachStatement; struct FuncDeclaration; struct ExpInitializer; +struct StructDeclaration; enum PROT; enum LINK; @@ -178,10 +179,14 @@ struct SymbolDeclaration : Declaration { Symbol *sym; + StructDeclaration *dsym; - SymbolDeclaration(Loc loc, Symbol *s); + SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym); Symbol *toSymbol(); + + // Eliminate need for dynamic_cast + SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; } }; struct ClassInfoDeclaration : VarDeclaration diff -uNr dmd-0.123/dmd/src/dmd/dsymbol.c dmd-0.124/dmd/src/dmd/dsymbol.c --- dmd-0.123/dmd/src/dmd/dsymbol.c 2005-05-08 16:43:26.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/dsymbol.c 2005-05-12 18:44:32.000000000 +0200 @@ -260,7 +260,7 @@ return FALSE; } -void Dsymbol::addMember(ScopeDsymbol *sd) +void Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd) { //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); diff -uNr dmd-0.123/dmd/src/dmd/dsymbol.h dmd-0.124/dmd/src/dmd/dsymbol.h --- dmd-0.123/dmd/src/dmd/dsymbol.h 2005-03-25 20:26:10.000000000 +0100 +++ dmd-0.124/dmd/src/dmd/dsymbol.h 2005-05-18 22:30:54.000000000 +0200 @@ -40,7 +40,6 @@ struct UnitTestDeclaration; struct NewDeclaration; struct VarDeclaration; -struct VersionDeclaration; struct Symbol; struct Package; struct Module; @@ -56,6 +55,7 @@ struct ScopeDsymbol; struct WithScopeSymbol; struct ArrayScopeSymbol; +struct SymbolDeclaration; struct Expression; struct TYPE; @@ -101,7 +101,7 @@ virtual char *kind(); virtual Dsymbol *toAlias(); // resolve real symbol - virtual void addMember(ScopeDsymbol *s); + virtual void addMember(Scope *sc, ScopeDsymbol *s); virtual void semantic(Scope *sc); virtual void semantic2(Scope *sc); virtual void semantic3(Scope *sc); @@ -162,12 +162,12 @@ virtual StructDeclaration *isStructDeclaration() { return NULL; } virtual UnionDeclaration *isUnionDeclaration() { return NULL; } virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; } - virtual VersionDeclaration *isVersionDeclaration() { return NULL; } virtual ScopeDsymbol *isScopeDsymbol() { return NULL; } virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; } virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; } virtual Import *isImport() { return NULL; } virtual EnumDeclaration *isEnumDeclaration() { return NULL; } + virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; } }; // Dsymbol that generates a scope diff -uNr dmd-0.123/dmd/src/dmd/enum.c dmd-0.124/dmd/src/dmd/enum.c --- dmd-0.123/dmd/src/dmd/enum.c 2005-05-09 17:47:08.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/enum.c 2005-05-12 18:51:14.000000000 +0200 @@ -101,12 +101,12 @@ // Add to symbol table only after evaluating 'value' if (isAnonymous()) - { //em->addMember((ScopeDsymbol *)parent); + { sce->enclosing->insert(em); em->parent = sce->enclosing->parent; } else - em->addMember(this); + em->addMember(sc, this); if (first) { first = 0; diff -uNr dmd-0.123/dmd/src/dmd/expression.c dmd-0.124/dmd/src/dmd/expression.c --- dmd-0.123/dmd/src/dmd/expression.c 2005-05-11 12:21:42.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/expression.c 2005-05-18 21:17:52.000000000 +0200 @@ -2512,7 +2512,7 @@ type = Type::tvoid; return this; } - else if (e1->type->ty == Tpointer && ident != Id::size && + else if (e1->type->ty == Tpointer && ident != Id::init && ident != Id::__sizeof && ident != Id::alignof && ident != Id::offsetof) { @@ -5254,7 +5254,7 @@ error("need member function opCmp() for struct %s to compare", t1->toChars()); e = this; } -#if 0 +#if 1 else if (t1->iscomplex() || t2->iscomplex()) { error("compare not defined for complex operands"); diff -uNr dmd-0.123/dmd/src/dmd/lexer.c dmd-0.124/dmd/src/dmd/lexer.c --- dmd-0.123/dmd/src/dmd/lexer.c 2005-05-10 14:53:18.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/lexer.c 2005-05-18 15:17:28.000000000 +0200 @@ -1072,6 +1072,8 @@ p++; if (u == PS || u == LS) loc.linnum++; + stringbuffer.writeUTF8(u); + continue; } break; } @@ -1915,9 +1917,9 @@ case 0x1A: case '\n': Lnewline: - loc.linnum = linnum; + this->loc.linnum = linnum; if (filespec) - loc.filename = filespec; + this->loc.filename = filespec; return; case '\r': @@ -2074,6 +2076,7 @@ { "pragma", TOKpragma }, { "typeof", TOKtypeof }, { "typeid", TOKtypeid }, + { "iftype", TOKiftype }, { "template", TOKtemplate }, { "instance", TOKinstance }, diff -uNr dmd-0.123/dmd/src/dmd/lexer.h dmd-0.124/dmd/src/dmd/lexer.h --- dmd-0.123/dmd/src/dmd/lexer.h 2005-05-10 14:37:26.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/lexer.h 2005-05-13 01:17:50.000000000 +0200 @@ -64,6 +64,7 @@ TOKdeclaration, TOKtypeof, TOKpragma, TOKdsymbol, TOKtypeid, TOKuadd, + TOKiftype, // Operators TOKlt, TOKgt, diff -uNr dmd-0.123/dmd/src/dmd/link.c dmd-0.124/dmd/src/dmd/link.c --- dmd-0.123/dmd/src/dmd/link.c 2004-07-06 11:32:24.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/link.c 2005-05-11 21:11:52.000000000 +0200 @@ -182,11 +182,14 @@ argv.push((void *) global.params.linkswitches->data[i]); } - // Print it - for (i = 0; i < argv.dim; i++) - printf("%s ", (char *)argv.data[i]); - printf("\n"); - fflush(stdout); + if (!global.params.quiet) + { + // Print it + for (i = 0; i < argv.dim; i++) + printf("%s ", (char *)argv.data[i]); + printf("\n"); + fflush(stdout); + } argv.push(NULL); childpid = fork(); diff -uNr dmd-0.123/dmd/src/dmd/mars.c dmd-0.124/dmd/src/dmd/mars.c --- dmd-0.123/dmd/src/dmd/mars.c 2005-05-10 14:17:08.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/mars.c 2005-05-14 23:15:46.000000000 +0200 @@ -28,7 +28,7 @@ #include "module.h" #include "mtype.h" #include "id.h" -#include "debcond.h" +#include "cond.h" void getenv_setargv(const char *envvar, int *pargc, char** *pargv); @@ -49,7 +49,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.123"; + version = "v0.124"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -128,21 +128,22 @@ files.d D source files\n\ -c do not link\n\ -d allow deprecated features\n\ + -debug compile in debug code\n\ + -debug=level compile in debug code <= level\n\ + -debug=ident compile in debug code identified by ident\n\ -g add symbolic debug info\n\ - -v verbose\n\ + -Ipath where to look for imports\n\ + -inline do function inlining\n\ + -Llinkerflag pass linkerflag to link\n\ -O optimize\n\ -odobjdir write object files to directory objdir\n\ -offilename name output file to filename\n\ -op do not strip paths from source file\n\ - -Ipath where to look for imports\n\ - -Llinkerflag pass linkerflag to link\n\ - -debug compile in debug code\n\ - -debug=level compile in debug code <= level\n\ - -debug=ident compile in debug code identified by ident\n\ - -inline do function inlining\n\ -profile profile runtime performance of generated code\n\ + -quiet suppress unnecessary messages\n\ -release compile release version\n\ -unittest compile in unit tests\n\ + -v verbose\n\ -version=level compile in version code >= level\n\ -version=ident compile in version code identified by ident\n\ -w enable warnings\n\ @@ -269,6 +270,8 @@ } else if (strcmp(p + 1, "inline") == 0) global.params.useInline = 1; + else if (strcmp(p + 1, "quiet") == 0) + global.params.quiet = 1; else if (strcmp(p + 1, "release") == 0) global.params.release = 1; else if (strcmp(p + 1, "unittest") == 0) diff -uNr dmd-0.123/dmd/src/dmd/mars.h dmd-0.124/dmd/src/dmd/mars.h --- dmd-0.123/dmd/src/dmd/mars.h 2005-05-09 16:48:50.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/mars.h 2005-05-11 21:11:56.000000000 +0200 @@ -21,6 +21,7 @@ { char link; // perform link char trace; // insert profiling hooks + char quiet; // suppress non-error messages char verbose; // verbose compile char symdebug; // insert debug symbolic information char optimize; // run optimizer diff -uNr dmd-0.123/dmd/src/dmd/module.c dmd-0.124/dmd/src/dmd/module.c --- dmd-0.123/dmd/src/dmd/module.c 2005-05-10 14:20:08.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/module.c 2005-05-12 18:51:46.000000000 +0200 @@ -450,7 +450,7 @@ { Dsymbol *s; s = (Dsymbol *)members->data[i]; - s->addMember(sc->scopesym); + s->addMember(NULL, sc->scopesym); } // Pass 1 semantic routines: do public side of the definition diff -uNr dmd-0.123/dmd/src/dmd/mtype.c dmd-0.124/dmd/src/dmd/mtype.c --- dmd-0.123/dmd/src/dmd/mtype.c 2005-05-09 17:47:28.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/mtype.c 2005-05-18 22:31:16.000000000 +0200 @@ -484,8 +484,7 @@ } else if (ident == Id::size) { - if (!global.params.useDeprecated) - error(loc, ".size property is deprecated, use .sizeof"); + error(loc, ".size property should be replaced with .sizeof"); e = new IntegerExp(loc, size(loc), Type::tsize_t); } else if (ident == Id::alignof) @@ -3643,7 +3642,7 @@ printf("TypeStruct::defaultInit() '%s'\n", toChars()); #endif s = sym->toInitializer(); - d = new SymbolDeclaration(sym->loc, s); + d = new SymbolDeclaration(sym->loc, s, sym); assert(d); d->type = this; return new VarExp(sym->loc, d); diff -uNr dmd-0.123/dmd/src/dmd/optimize.c dmd-0.124/dmd/src/dmd/optimize.c --- dmd-0.123/dmd/src/dmd/optimize.c 2005-04-04 01:11:24.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/optimize.c 2005-05-12 21:21:32.000000000 +0200 @@ -23,6 +23,7 @@ Expression *Expression::optimize(int result) { + //printf("Expression::optimize(result = %d) %s\n", result, toChars()); return this; } @@ -156,6 +157,7 @@ Expression *BinExp::optimize(int result) { Expression *e; + //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) diff -uNr dmd-0.123/dmd/src/dmd/parse.c dmd-0.124/dmd/src/dmd/parse.c --- dmd-0.123/dmd/src/dmd/parse.c 2005-05-09 15:53:20.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/parse.c 2005-05-19 11:17:56.000000000 +0200 @@ -15,7 +15,7 @@ #include "parse.h" #include "init.h" #include "attrib.h" -#include "debcond.h" +#include "cond.h" #include "mtype.h" #include "template.h" #include "staticassert.h" @@ -138,8 +138,10 @@ { Dsymbol *s; Array *decldefs; Array *a; + Array *aelse; enum PROT prot; unsigned stc; + Condition *condition; //printf("Parser::parseDeclDefs()\n"); decldefs = new Array(); @@ -245,6 +247,10 @@ s = parseStaticDtor(); else if (token.value == TOKassert) s = parseStaticAssert(); + else if (token.value == TOKif) + { condition = parseStaticIfCondition(); + goto Lcondition; + } else { stc = STCstatic; goto Lstc2; @@ -392,9 +398,6 @@ } case TOKdebug: - { DebugCondition *condition; - Array *aelse; - nextToken(); if (token.value == TOKassign) { @@ -414,28 +417,10 @@ break; } - if (token.value == TOKlparen) - { - nextToken(); - condition = parseDebugCondition(); - check(TOKrparen); - } - else - condition = new DebugCondition(mod, 1, NULL); - a = parseBlock(); - aelse = NULL; - if (token.value == TOKelse) - { nextToken(); - aelse = parseBlock(); - } - s = new DebugDeclaration(condition, a, aelse); - break; - } + condition = parseDebugCondition(); + goto Lcondition; case TOKversion: - { VersionCondition *condition; - Array *aelse; - nextToken(); if (token.value == TOKassign) { @@ -454,26 +439,22 @@ nextToken(); break; } + condition = parseVersionCondition(); + goto Lcondition; - if (token.value == TOKlparen) - { - nextToken(); - condition = parseVersionCondition(); - check(TOKrparen); - } - else - { error("(condition) expected following version"); - condition = NULL; - } + case TOKiftype: + condition = parseIftypeCondition(); + goto Lcondition; + + Lcondition: a = parseBlock(); aelse = NULL; if (token.value == TOKelse) { nextToken(); aelse = parseBlock(); } - s = new VersionDeclaration(condition, a, aelse); + s = new ConditionalDeclaration(condition, a, aelse); break; - } case TOKsemicolon: // empty declaration nextToken(); @@ -494,6 +475,7 @@ return decldefs; } + /******************************************** * Parse declarations after an align, protection, or extern decl. */ @@ -560,40 +542,132 @@ * Parse a debug conditional */ -DebugCondition *Parser::parseDebugCondition() +Condition *Parser::parseDebugCondition() { - unsigned level = 1; - Identifier *id = NULL; + Condition *c; - if (token.value == TOKidentifier) - id = token.ident; - else if (token.value == TOKint32v) - level = (unsigned)token.uns64value; + if (token.value == TOKlparen) + { + nextToken(); + unsigned level = 1; + Identifier *id = NULL; + + if (token.value == TOKidentifier) + id = token.ident; + else if (token.value == TOKint32v) + level = (unsigned)token.uns64value; + else + error("identifier or integer expected, not %s", token.toChars()); + nextToken(); + check(TOKrparen); + c = new DebugCondition(mod, level, id); + } else - error("identifier or integer expected, not %s", token.toChars()); - nextToken(); + c = new DebugCondition(mod, 1, NULL); + return c; - return new DebugCondition(mod, level, id); } /************************************** * Parse a version conditional */ -VersionCondition *Parser::parseVersionCondition() +Condition *Parser::parseVersionCondition() { - unsigned level = 1; - Identifier *id = NULL; + Condition *c; - if (token.value == TOKidentifier) - id = token.ident; - else if (token.value == TOKint32v) - level = (unsigned)token.uns64value; + if (token.value == TOKlparen) + { + unsigned level = 1; + Identifier *id = NULL; + + nextToken(); + if (token.value == TOKidentifier) + id = token.ident; + else if (token.value == TOKint32v) + level = (unsigned)token.uns64value; + else + error("identifier or integer expected, not %s", token.toChars()); + nextToken(); + check(TOKrparen); + + c = new VersionCondition(mod, level, id); + } + else + { error("(condition) expected following version"); + c = NULL; + } + return c; + +} + +/*********************************************** + * static if (expression) + * body + * else + * body + */ + +Condition *Parser::parseStaticIfCondition() +{ Expression *exp; + Condition *condition; + Array *aif; + Array *aelse; + Loc loc = this->loc; + + nextToken(); + if (token.value == TOKlparen) + { + nextToken(); + exp = parseAssignExp(); + check(TOKrparen); + } else - error("identifier or integer expected, not %s", token.toChars()); + { error("(expression) expected following static if"); + exp = NULL; + } + condition = new StaticIfCondition(loc, exp); + return condition; +} + + +/*********************************************** + * iftype (type identifier : specialization) + * body + * else + * body + */ + +Condition *Parser::parseIftypeCondition() +{ + Type *targ; + Identifier *ident = NULL; + Type *tspec = NULL; + Loc loc = this->loc; + nextToken(); + if (token.value == TOKlparen) + { + nextToken(); + targ = parseBasicType(); + targ = parseDeclarator(targ, &ident); + if (token.value == TOKcolon) + { + nextToken(); + tspec = parseBasicType(); + tspec = parseDeclarator(tspec, NULL); + } + check(TOKrparen); - return new VersionCondition(mod, level, id); + if (!ident && !tspec) + error("expected either Identifier or TypeSpecialization or both"); + } + else + { error("(type identifier : specialization) expected following iftype"); + return NULL; + } + Condition *condition = new IftypeCondition(loc, targ, ident, tspec); + return condition; } /***************************************** @@ -2193,6 +2267,9 @@ Statement *Parser::parseStatement(int flags) { Statement *s; Token *t; + Condition *condition; + Statement *ifbody; + Statement *elsebody; Loc loc = this->loc; //printf("parseStatement()\n"); @@ -2302,7 +2379,7 @@ break; case TOKstatic: - { // Look ahead to see if it's static assert() + { // Look ahead to see if it's static assert() or static if() Token *t; t = peek(&token); @@ -2312,6 +2389,12 @@ s = new StaticAssertStatement(parseStaticAssert()); break; } + if (t->value == TOKif) + { + nextToken(); + condition = parseStaticIfCondition(); + goto Lcondition; + } goto Ldeclaration; } @@ -2535,58 +2618,29 @@ } case TOKdebug: - { Condition *condition; - Statement *ifbody; - Statement *elsebody; - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - condition = parseDebugCondition(); - check(TOKrparen); - } - else - condition = new DebugCondition(mod, 1, NULL); - ifbody = parseStatement(PSsemi); - if (token.value == TOKelse) - { - nextToken(); - elsebody = parseStatement(PSsemi); - } - else - elsebody = NULL; - s = new ConditionalStatement(loc, condition, ifbody, elsebody); - break; - } + condition = parseDebugCondition(); + goto Lcondition; case TOKversion: - { Condition *condition; - Statement *ifbody; - Statement *elsebody; - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - condition = parseVersionCondition(); - check(TOKrparen); - } - else - { error("(condition) expected after version"); - condition = NULL; - } + condition = parseVersionCondition(); + goto Lcondition; + + case TOKiftype: + condition = parseIftypeCondition(); + goto Lcondition; + + Lcondition: ifbody = parseStatement(PSsemi); + elsebody = NULL; if (token.value == TOKelse) { nextToken(); elsebody = parseStatement(PSsemi); } - else - elsebody = NULL; s = new ConditionalStatement(loc, condition, ifbody, elsebody); break; - } case TOKpragma: { Identifier *ident; @@ -2916,6 +2970,7 @@ continue; case TOKeof: + /* { */ error("matching '}' expected, not end of file"); break; diff -uNr dmd-0.123/dmd/src/dmd/parse.h dmd-0.124/dmd/src/dmd/parse.h --- dmd-0.123/dmd/src/dmd/parse.h 2005-03-07 13:21:44.000000000 +0100 +++ dmd-0.124/dmd/src/dmd/parse.h 2005-05-15 02:13:12.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2003 by Digital Mars +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -28,12 +28,12 @@ struct DtorDeclaration; struct StaticCtorDeclaration; struct StaticDtorDeclaration; +struct ConditionalDeclaration; struct InvariantDeclaration; struct UnitTestDeclaration; struct NewDeclaration; struct DeleteDeclaration; -struct DebugCondition; -struct VersionCondition; +struct Condition; struct Module; struct ModuleDeclaration; struct TemplateDeclaration; @@ -58,8 +58,10 @@ Dsymbol *parseMixin(); Array *parseTemplateArgumentList(); StaticAssert *parseStaticAssert(); - DebugCondition *parseDebugCondition(); - VersionCondition *parseVersionCondition(); + Condition *parseDebugCondition(); + Condition *parseVersionCondition(); + Condition *parseStaticIfCondition(); + Condition *parseIftypeCondition(); CtorDeclaration *parseCtor(); DtorDeclaration *parseDtor(); StaticCtorDeclaration *parseStaticCtor(); diff -uNr dmd-0.123/dmd/src/dmd/scope.c dmd-0.124/dmd/src/dmd/scope.c --- dmd-0.123/dmd/src/dmd/scope.c 2005-04-02 10:52:22.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/scope.c 2005-05-12 18:52:16.000000000 +0200 @@ -107,7 +107,7 @@ Dsymbol *m = module; while (m->parent) m = m->parent; - m->addMember(sc->scopesym); + m->addMember(NULL, sc->scopesym); m->parent = NULL; // got changed by addMember() // Create the module scope underneath the global scope diff -uNr dmd-0.123/dmd/src/dmd/statement.c dmd-0.124/dmd/src/dmd/statement.c --- dmd-0.123/dmd/src/dmd/statement.c 2005-05-10 02:13:58.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/statement.c 2005-05-15 11:49:52.000000000 +0200 @@ -15,7 +15,7 @@ #include "statement.h" #include "expression.h" -#include "debcond.h" +#include "cond.h" #include "init.h" #include "staticassert.h" #include "mtype.h" @@ -1004,41 +1004,18 @@ // semantic analysis of the skipped code. // This feature allows a limited form of conditional compilation. condition = condition->optimize(WANTflags); -#if 0 - /* Don't do this because of: - * if (0) { Label: ... ; } else { ... ; goto Label; } - */ - if (condition->isBool(FALSE)) - { Statement *s; - s = new ExpStatement(loc, condition); - if (elsebody) - { elsebody = elsebody->semanticScope(sc, NULL, NULL); - s = new CompoundStatement(loc, s, elsebody); - } - return s; - } - else if (condition->isBool(TRUE)) - { Statement *s; + // Evaluate at runtime + unsigned cs0 = sc->callSuper; + unsigned cs1; + + ifbody = ifbody->semanticScope(sc, NULL, NULL); + cs1 = sc->callSuper; + sc->callSuper = cs0; + if (elsebody) + elsebody = elsebody->semanticScope(sc, NULL, NULL); + sc->mergeCallSuper(loc, cs1); - s = new ExpStatement(loc, condition); - ifbody = ifbody->semanticScope(sc, NULL, NULL); - s = new CompoundStatement(loc, s, ifbody); - return s; - } - else -#endif - { // Evaluate at runtime - unsigned cs0 = sc->callSuper; - unsigned cs1; - - ifbody = ifbody->semanticScope(sc, NULL, NULL); - cs1 = sc->callSuper; - sc->callSuper = cs0; - if (elsebody) - elsebody = elsebody->semanticScope(sc, NULL, NULL); - sc->mergeCallSuper(loc, cs1); - } return this; } @@ -1078,7 +1055,7 @@ if (elsebody) e = elsebody->syntaxCopy(); ConditionalStatement *s = new ConditionalStatement(loc, - condition, ifbody->syntaxCopy(), e); + condition->syntaxCopy(), ifbody->syntaxCopy(), e); return s; } @@ -1089,26 +1066,17 @@ // If we can short-circuit evaluate the if statement, don't do the // semantic analysis of the skipped code. // This feature allows a limited form of conditional compilation. - if (condition->isBool(FALSE)) - { - if (elsebody) - elsebody = elsebody->semantic(sc); - return elsebody; - } - else if (condition->isBool(TRUE)) + if (condition->include(sc, NULL)) { ifbody = ifbody->semantic(sc); return ifbody; } else - { Statement *s; - - // Evaluate at runtime - s = new IfStatement(loc, condition->toExpr(), ifbody, elsebody); - s = s->semantic(sc); - return s; + { + if (elsebody) + elsebody = elsebody->semantic(sc); + return elsebody; } - return this; } int ConditionalStatement::usesEH() @@ -1118,6 +1086,8 @@ void ConditionalStatement::toCBuffer(OutBuffer *buf) { + condition->toCBuffer(buf); + buf->writenl(); buf->printf("ConditionalStatement::toCBuffer()"); buf->writenl(); } diff -uNr dmd-0.123/dmd/src/dmd/staticassert.c dmd-0.124/dmd/src/dmd/staticassert.c --- dmd-0.123/dmd/src/dmd/staticassert.c 2004-02-21 17:33:22.000000000 +0100 +++ dmd-0.124/dmd/src/dmd/staticassert.c 2005-05-12 18:44:50.000000000 +0200 @@ -33,7 +33,7 @@ return sa; } -void StaticAssert::addMember(ScopeDsymbol *sd) +void StaticAssert::addMember(Scope *sc, ScopeDsymbol *sd) { } diff -uNr dmd-0.123/dmd/src/dmd/staticassert.h dmd-0.124/dmd/src/dmd/staticassert.h --- dmd-0.123/dmd/src/dmd/staticassert.h 2003-09-15 02:27:56.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/staticassert.h 2005-05-12 18:43:20.000000000 +0200 @@ -25,7 +25,7 @@ StaticAssert(Loc loc, Expression *exp); Dsymbol *syntaxCopy(Dsymbol *s); - void addMember(ScopeDsymbol *sd); + void addMember(Scope *sc, ScopeDsymbol *sd); void semantic(Scope *sc); void semantic2(Scope *sc); void inlineScan(); diff -uNr dmd-0.123/dmd/src/dmd/struct.c dmd-0.124/dmd/src/dmd/struct.c --- dmd-0.123/dmd/src/dmd/struct.c 2005-05-02 22:32:14.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/struct.c 2005-05-12 18:53:12.000000000 +0200 @@ -243,7 +243,7 @@ { Dsymbol *s = (Dsymbol *)members->data[i]; //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); - s->addMember(this); + s->addMember(sc, this); } } @@ -312,7 +312,7 @@ ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); assert(s); s->members->push(fdptr); - fdptr->addMember(s); + fdptr->addMember(sc, s); fdptr->semantic(sc2); } } diff -uNr dmd-0.123/dmd/src/dmd/template.c dmd-0.124/dmd/src/dmd/template.c --- dmd-0.123/dmd/src/dmd/template.c 2005-05-09 22:02:30.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/template.c 2005-05-12 21:21:54.000000000 +0200 @@ -1443,7 +1443,7 @@ #if LOG printf("\tadding member '%s' %p to '%s'\n", s->toChars(), s, this->toChars()); #endif - s->addMember(this); + s->addMember(scope, this); } /* See if there is only one member of template instance, and that @@ -2187,34 +2187,8 @@ symtab = new DsymbolTable(); - // Add members to enclosing scope, as well as this scope - for (unsigned i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - s->addMember(this); - //sc->insert(s); - //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); - //printf("s->parent = %s\n", s->parent->toChars()); - if (isAnonymous()) - { -#if 0 - if (sc->parent != sc->scopesym) - { - if (!sc->insert(s)) - error("%s is multiply defined", s->toChars()); - } - else - s->addMember((ScopeDsymbol *)sc->parent); -#endif - //s->parent = parent; - } - } - -// if (isAnonymous()) { ScopeDsymbol *sds = (ScopeDsymbol *)sc->scopesym; - sds->importScope(this, PROTpublic); } @@ -2222,11 +2196,9 @@ printf("\tcreate scope for template parameters '%s'\n", toChars()); #endif Scope *scx = sc; -// if (!isAnonymous()) - { - scx = sc->push(this); - scx->parent = this; - } + scx = sc->push(this); + scx->parent = this; + argsym = new ScopeDsymbol(); argsym->parent = scx->parent; Scope *scope = scx->push(argsym); @@ -2234,6 +2206,17 @@ // Declare each template parameter as an alias for the argument type declareParameters(scope); + // Add members to enclosing scope, as well as this scope + for (unsigned i = 0; i < members->dim; i++) + { Dsymbol *s; + + s = (Dsymbol *)members->data[i]; + s->addMember(scope, this); + //sc->insert(s); + //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); + //printf("s->parent = %s\n", s->parent->toChars()); + } + // Do semantic() analysis on template instance members #if LOG printf("\tdo semantic() on template instance members '%s'\n", toChars()); diff -uNr dmd-0.123/dmd/src/dmd/tocsym.c dmd-0.124/dmd/src/dmd/tocsym.c --- dmd-0.123/dmd/src/dmd/tocsym.c 2005-04-15 01:23:10.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/tocsym.c 2005-05-18 22:35:18.000000000 +0200 @@ -42,11 +42,12 @@ /********************************* SymbolDeclaration ****************************/ -SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s) +SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym) : Declaration(new Identifier(s->Sident, TOKidentifier)) { this->loc = loc; sym = s; + this->dsym = dsym; storage_class |= STCconst; } diff -uNr dmd-0.123/dmd/src/dmd/todt.c dmd-0.124/dmd/src/dmd/todt.c --- dmd-0.123/dmd/src/dmd/todt.c 2005-05-11 00:48:02.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/todt.c 2005-05-19 01:08:20.000000000 +0200 @@ -549,17 +549,23 @@ dt_t **VarExp::toDt(dt_t **pdt) { //printf("VarExp::toDt() %d\n", op); + for (; *pdt; pdt = &((*pdt)->DTnext)) + ; + VarDeclaration *v = var->isVarDeclaration(); if (v && v->isConst() && type->toBasetype()->ty != Tsarray && v->init) - { dt_t **pdtend; - - for (pdtend = pdt; *pdtend; pdtend = &((*pdtend)->DTnext)) - ; - *pdtend = v->init->toDt(); + { + *pdt = v->init->toDt(); + return pdt; + } + SymbolDeclaration *sd = var->isSymbolDeclaration(); + if (sd && sd->dsym) + { + sd->dsym->toDt(pdt); return pdt; } #ifdef DEBUG - printf("VarExp::toDt() %d\n", op); + printf("VarExp::toDt(), kind = %s\n", var->kind()); #endif error("non-constant expression %s", toChars()); pdt = dtnzeros(pdt, 1); @@ -734,8 +740,16 @@ { while (*pdt) pdt = &((*pdt)->DTnext); - Expression *e = next->defaultInit(); - Type *tbn = next->toBasetype(); + Type *tnext = next; + Type *tbn = tnext->toBasetype(); + while (tbn->ty == Tsarray) + { TypeSArray *tsa = (TypeSArray *)tbn; + + len *= tsa->dim->toInteger(); + tnext = tbn->next; + tbn = tnext->toBasetype(); + } + Expression *e = tnext->defaultInit(); if (tbn->ty == Tbit) { Bits databits; @@ -749,7 +763,7 @@ else { if (tbn->ty == Tstruct) - next->toDt(pdt); + tnext->toDt(pdt); else e->toDt(pdt); dt_optimize(*pdt); @@ -769,7 +783,7 @@ for (i = 1; i < len; i++) { if (tbn->ty == Tstruct) - pdt = next->toDt(pdt); + pdt = tnext->toDt(pdt); else pdt = e->toDt(pdt); } diff -uNr dmd-0.123/dmd/src/dmd/total.h dmd-0.124/dmd/src/dmd/total.h --- dmd-0.123/dmd/src/dmd/total.h 2003-02-25 17:44:42.000000000 +0100 +++ dmd-0.124/dmd/src/dmd/total.h 2005-05-14 23:15:34.000000000 +0200 @@ -37,7 +37,7 @@ #include "import.h" #include "module.h" #include "id.h" -#include "debcond.h" +#include "cond.h" #include "version.h" #endif /* DMD_TOTAL_H */ diff -uNr dmd-0.123/dmd/src/dmd/version.c dmd-0.124/dmd/src/dmd/version.c --- dmd-0.123/dmd/src/dmd/version.c 2005-04-24 02:05:48.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/version.c 2005-05-14 23:15:46.000000000 +0200 @@ -13,12 +13,17 @@ #include "identifier.h" #include "dsymbol.h" -#include "debcond.h" +#include "cond.h" #include "version.h" #include "module.h" /* ================================================== */ +/* DebugSymbol's happen for statements like: + * debug = identifier; + * debug = integer; + */ + DebugSymbol::DebugSymbol(Loc loc, Identifier *ident) : Dsymbol(ident) { @@ -40,7 +45,7 @@ return ds; } -void DebugSymbol::addMember(ScopeDsymbol *sd) +void DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd) { //printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); Module *m; @@ -91,6 +96,11 @@ /* ================================================== */ +/* VersionSymbol's happen for statements like: + * version = identifier; + * version = integer; + */ + VersionSymbol::VersionSymbol(Loc loc, Identifier *ident) : Dsymbol(ident) { @@ -112,7 +122,7 @@ return ds; } -void VersionSymbol::addMember(ScopeDsymbol *sd) +void VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd) { //printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); Module *m; diff -uNr dmd-0.123/dmd/src/dmd/version.h dmd-0.124/dmd/src/dmd/version.h --- dmd-0.123/dmd/src/dmd/version.h 2005-04-24 02:03:58.000000000 +0200 +++ dmd-0.124/dmd/src/dmd/version.h 2005-05-12 18:43:20.000000000 +0200 @@ -26,7 +26,7 @@ DebugSymbol(Loc loc, unsigned level); Dsymbol *syntaxCopy(Dsymbol *); - void addMember(ScopeDsymbol *s); + void addMember(Scope *sc, ScopeDsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); char *kind(); @@ -40,7 +40,7 @@ VersionSymbol(Loc loc, unsigned level); Dsymbol *syntaxCopy(Dsymbol *); - void addMember(ScopeDsymbol *s); + void addMember(Scope *sc, ScopeDsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); char *kind(); diff -uNr dmd-0.123/dmd/src/phobos/linux.mak dmd-0.124/dmd/src/phobos/linux.mak --- dmd-0.123/dmd/src/phobos/linux.mak 2005-05-11 14:55:04.000000000 +0200 +++ dmd-0.124/dmd/src/phobos/linux.mak 2005-05-19 11:18:30.000000000 +0200 @@ -56,7 +56,7 @@ crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ - perf.o openrj.o uni.o trace.o \ + perf.o openrj.o uni.o trace.o boxer.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -98,7 +98,8 @@ std/intrinsic.d std/array.d std/switcherr.d std/syserror.d \ std/regexp.d std/random.d std/stream.d std/process.d std/recls.d \ std/socket.d std/socketstream.d std/loader.d std/stdarg.d \ - std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d + std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d \ + std/boxer.d SRC_STD_C= std/c/process.d std/c/stdlib.d std/c/time.d std/c/stdio.d \ std/c/math.d std/c/stdarg.d std/c/stddef.d @@ -471,6 +472,9 @@ base64.o : std/base64.d $(DMD) -c $(DFLAGS) std/base64.d +boxer.o : std/boxer.d + $(DMD) -c $(DFLAGS) std/boxer.d + compiler.o : std/compiler.d $(DMD) -c $(DFLAGS) std/compiler.d diff -uNr dmd-0.123/dmd/src/phobos/std/boxer.d dmd-0.124/dmd/src/phobos/std/boxer.d --- dmd-0.123/dmd/src/phobos/std/boxer.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.124/dmd/src/phobos/std/boxer.d 2005-05-19 11:18:32.000000000 +0200 @@ -0,0 +1,755 @@ +/* This module is written by Burton Radons and placed into the public domain. */ +module std.boxer; + +private import std.format; +private import std.string; +private import std.utf; + +/** These functions and types allow packing objects into generic containers + * and recovering them later. This comes into play in a wide spectrum of + * utilities, such as with a scripting language, or as additional user data + * for an object. + * + * Box an object by calling the box function: + * + * Box x = box(4); + * + * Recover the value by using the unbox template: + * + * int y = unbox!(int)(x); + * + * If it cannot unbox the object to that type, it throws UnboxException. It will + * use implicit casts to behave in the exact same way as D does - for + * instance: + * + * byte v; + * int i = v; // Implicitly cast from byte to int. + * int j = unbox!(int)(Box(i)); // Do the exact same thing at runtime. + * + * This therefore means that attempting to unbox an int as a string will + * throw an error and not format it. In general, you can call the toString + * method on the box and receive a good result, depending upon whether + * std.string.format accepts it. + * + * Boxes can be compared to one another and they can be used as keys for + * associative arrays. Boxes of different types can be compared to one + * another, using the same casting rules as the main type system. + * + * boxArray has two forms: + * + * Box[] boxArray(...); + * Box[] boxArray(TypeInfo[] types, void* data); + * + * This converts an array of arguments into an array of boxes. To convert + * back into an array of arguments, use boxArrayToArguments: + * + * void boxArrayToArguments(Box[] arguments, out TypeInfo[] types, + * out void[] data); + * + * Finally, you can discover whether unboxing as a certain type is legal by + * using the unboxable template or method: + * + * bit unboxable!(T) (Box value); + * bit Box.unboxable(TypeInfo T); + */ + +/** Return the next type in an array typeinfo, or null if there is none. */ +private bit isArrayTypeInfo(TypeInfo type) +{ + char[] name = type.classinfo.name; + return name.length >= 10 && name[9] == 'A' && name != "TypeInfo_AssociativeArray"; +} + +/** The type class returned from Box.findTypeClass; the order of entries is important. */ +private enum TypeClass +{ + Bit, /**< bit */ + Integer, /**< byte, ubyte, short, ushort, int, uint, long, ulong */ + Float, /**< float, double, real */ + Complex, /**< cfloat, cdouble, creal */ + Imaginary, /**< ifloat, idouble, ireal */ + Class, /**< Inherits from Object */ + Pointer, /**< Pointer type (T *) */ + Array, /**< Array type (T []) */ + Other, /**< Any other type, such as delegates, function pointers, struct, void... */ +} + +/** A box object contains a value in a generic fashion, allowing it to be + * passed from one place to another without having to know its type. It is + * created by calling the box function, and you can recover the value by + * instantiating the unbox template. + */ +struct Box +{ + private TypeInfo p_type; /**< The type of the contained object. */ + + private union + { + void* p_longData; /**< An array of the contained object. */ + void[8] p_shortData; /**< Data used when the object is small. */ + } + + private static TypeClass findTypeClass(TypeInfo type) + { + if (cast(TypeInfo_Class) type) + return TypeClass.Class; + if (cast(TypeInfo_Pointer) type) + return TypeClass.Pointer; + if (isArrayTypeInfo(type)) + return TypeClass.Array; + + version (DigitalMars) + { + /* Depend upon the name of the base type classes. */ + if (type.classinfo.name.length != "TypeInfo_?".length) + return TypeClass.Other; + switch (type.classinfo.name[9]) + { + case 'b': return TypeClass.Bit; + case 'g', 'h', 's', 't', 'i', 'k', 'l', 'm': return TypeClass.Integer; + case 'f', 'd', 'e': return TypeClass.Float; + case 'q', 'r', 'c': return TypeClass.Complex; + case 'o', 'p', 'j': return TypeClass.Imaginary; + default: return TypeClass.Other; + } + } + else + { + /* Use the name returned from toString, which might (but hopefully doesn't) include an allocation. */ + switch (type.toString) + { + case "bit": return TypeClass.Bit; + case "byte", "ubyte", "short", "ushort", "int", "uint", "long", "ulong": return TypeClass.Integer; + case "float", "real", "double": return TypeClass.Float; + case "cfloat", "cdouble", "creal": return TypeClass.Complex; + case "ifloat", "idouble", "ireal": return TypeClass.Imaginary; + default: return TypeClass.Other; + } + } + } + + /** Return whether this value could be unboxed as the given type without throwing. */ + bit unboxable(TypeInfo test) + { + if (type is test) + return true; + + TypeInfo_Class ca = cast(TypeInfo_Class) type, cb = cast(TypeInfo_Class) test; + + if (ca !== null && cb !== null) + { + ClassInfo ia = (*cast(Object *) data).classinfo, ib = cb.info; + + for ( ; ia !== null; ia = ia.base) + if (ia is ib) + return true; + return false; + } + + TypeClass ta = findTypeClass(type), tb = findTypeClass(test); + + if (type is typeid(void*) && *cast(void**) data is null) + return (tb == TypeClass.Class || tb == TypeClass.Pointer || tb == TypeClass.Array); + + if (test is typeid(void*)) + return (tb == TypeClass.Class || tb == TypeClass.Pointer || tb == TypeClass.Array); + + if (ta == TypeClass.Pointer && tb == TypeClass.Pointer) + return (cast(TypeInfo_Pointer)type).next is (cast(TypeInfo_Pointer)test).next; + + if ((ta == tb && ta != TypeClass.Other) + || (ta == TypeClass.Bit && tb == TypeClass.Integer) + || (ta <= TypeClass.Integer && tb == TypeClass.Float) + || (ta <= TypeClass.Imaginary && tb == TypeClass.Complex)) + return true; + return false; + } + + /** Return the type of the contained object. */ + TypeInfo type() + { + return p_type; + } + + /** Return the data array. */ + void[] data() + { + size_t size = type.tsize(); + + return size <= p_shortData.length ? p_shortData[0..size] : p_longData[0..size]; + } + + /** Attempt to convert the object to a string by doing D formatting on it. + */ + char[] toString() + { + if (type is null) + return ""; + + TypeInfo[2] arguments; + char[] string; + void[] args = new void[(char[]).sizeof + data.length]; + char[] format = "%s"; + + arguments[0] = typeid(char[]); + arguments[1] = type; + + void putc(dchar ch) + { + std.utf.encode(string, ch); + } + + args[0..(char[]).sizeof] = (cast(void*) &format)[0..(char[]).sizeof]; + args[(char[]).sizeof..length] = data; + std.format.doFormat(&putc, arguments, args); + delete args; + + return string; + } + + private bit opEqualsInternal(Box other, bit inverted) + { + if (type != other.type) + { + if (!unboxable(other.type)) + { + if (inverted) + return false; + return other.opEqualsInternal(*this, true); + } + + TypeClass ta = findTypeClass(type), tb = findTypeClass(other.type); + + if (ta <= TypeClass.Integer && tb <= TypeClass.Integer) + { + char[] na = type.toString, nb = other.type.toString; + + if (na == "ulong" || nb == "ulong") + return unbox!(ulong)(*this) == unbox!(ulong)(other); + return unbox!(long)(*this) == unbox!(long)(other); + } + else if (tb == TypeClass.Float) + return unbox!(real)(*this) == unbox!(real)(other); + else if (tb == TypeClass.Complex) + return unbox!(creal)(*this) == unbox!(creal)(other); + else if (tb == TypeClass.Imaginary) + return unbox!(ireal)(*this) == unbox!(ireal)(other); + + assert (0); + } + + return cast(bit)type.equals(data, other.data); + } + + /** Implement the equals operator. */ + bit opEquals(Box other) + { + return opEqualsInternal(other, false); + } + + private float opCmpInternal(Box other, bit inverted) + { + if (type != other.type) + { + if (!unboxable(other.type)) + { + if (inverted) + return 0; + return other.opCmpInternal(*this, true); + } + + TypeClass ta = findTypeClass(type), tb = findTypeClass(other.type); + + if (ta <= TypeClass.Integer && tb == TypeClass.Integer) + { + if (type == typeid(ulong) || other.type == typeid(ulong)) + { + ulong va = unbox!(ulong)(*this), vb = unbox!(ulong)(other); + return va > vb ? 1 : va < vb ? -1 : 0; + } + + long va = unbox!(long)(*this), vb = unbox!(long)(other); + return va > vb ? 1 : va < vb ? -1 : 0; + } + else if (tb == TypeClass.Float) + { + real va = unbox!(real)(*this), vb = unbox!(real)(other); + return va > vb ? 1 : va < vb ? -1 : va == vb ? 0 : float.nan; + } + else if (tb == TypeClass.Complex) + { + creal va = unbox!(creal)(*this), vb = unbox!(creal)(other); + return va == vb ? 0 : float.nan; + } + else if (tb == TypeClass.Imaginary) + { + ireal va = unbox!(ireal)(*this), vb = unbox!(ireal)(other); + return va > vb ? 1 : va < vb ? -1 : va == vb ? 0 : float.nan; + } + + assert (0); + } + + return type.compare(data, other.data); + } + + /** Implement the compare operator. */ + float opCmp(Box other) + { + return opCmpInternal(other, false); + } + + uint toHash() + { + return type.getHash(data); + } +} + +/** Create a box out of the first argument passed. */ +Box box(...) +in +{ + assert (_arguments.length == 1); +} +body +{ + return box(_arguments[0], _argptr); +} + +/** Assign the parameters, copying data as needed. */ +Box box(TypeInfo type, void* data) +in +{ + assert(type !== null); +} +body +{ + Box result; + size_t size = type.tsize(); + + result.p_type = type; + if (size <= result.p_shortData.length) + result.p_shortData[0..size] = data[0..size]; + else + result.p_longData = data[0..size].dup; + + return result; +} + +/** Return the length of an argument in bytes. */ +private size_t argumentLength(size_t baseLength) +{ + return (baseLength + int.sizeof - 1) & ~(int.sizeof - 1); +} + +/** Box each argument in the list. */ +Box[] boxArray(TypeInfo[] types, void* data) +{ + Box[] array = new Box[types.length]; + + foreach(size_t index, TypeInfo type; types) + { + array[index] = box(type, data); + data += argumentLength(type.tsize()); + } + + return array; +} + +/** Box each argument passed to the function, returning an array of boxes. */ +Box[] boxArray(...) +{ + return boxArray(_arguments, _argptr); +} + +/** Convert an array of boxes into an array of arguments. */ +void boxArrayToArguments(Box[] arguments, out TypeInfo[] types, out void* data) +{ + size_t dataLength; + void* pointer; + + /* Determine the number of bytes of data to allocate by summing the arguments. */ + foreach (Box item; arguments) + dataLength += argumentLength(item.data.length); + + types = new TypeInfo[arguments.length]; + pointer = data = new void[dataLength]; + + /* Stash both types and data. */ + foreach (size_t index, Box item; arguments) + { + types[index] = item.type; + pointer[0..item.data.length] = item.data; + pointer += argumentLength(item.data.length); + } +} + +/** This is thrown if you try to unbox an incompatible type. */ +class UnboxException : Exception +{ + /** The boxed object spawning the error. */ + Box object; + + /** The type that we tried to unbox as. */ + TypeInfo outputType; + + /** Assign parameters and the message. */ + this(Box object, TypeInfo outputType) + { + this.object = object; + this.outputType = outputType; + super(format("Could not unbox from type %s to %s.", object.type, outputType)); + } +} + +/** A generic unboxer for the real numeric types. */ +private template unboxCastReal(T) +{ + T unboxCastReal(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(float)) + return cast(T) *cast(float*) value.data; + if (value.type is typeid(double)) + return cast(T) *cast(double*) value.data; + if (value.type is typeid(real)) + return cast(T) *cast(real*) value.data; + return unboxCastInteger!(T)(value); + } +} + +/** A generic unboxer for the integral numeric types. */ +private template unboxCastInteger(T) +{ + T unboxCastInteger(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(int)) + return cast(T) *cast(int*) value.data; + if (value.type is typeid(uint)) + return cast(T) *cast(uint*) value.data; + if (value.type is typeid(long)) + return cast(T) *cast(long*) value.data; + if (value.type is typeid(ulong)) + return cast(T) *cast(ulong*) value.data; + if (value.type is typeid(bit)) + return cast(T) *cast(bit*) value.data; + if (value.type is typeid(byte)) + return cast(T) *cast(byte*) value.data; + if (value.type is typeid(ubyte)) + return cast(T) *cast(ubyte*) value.data; + if (value.type is typeid(short)) + return cast(T) *cast(short*) value.data; + if (value.type is typeid(ushort)) + return cast(T) *cast(ushort*) value.data; + throw new UnboxException(value, typeid(T)); + } +} + +/** A generic unboxer for the complex numeric types. */ +private template unboxCastComplex(T) +{ + T unboxCastComplex(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(cfloat)) + return cast(T) *cast(cfloat*) value.data; + if (value.type is typeid(cdouble)) + return cast(T) *cast(cdouble*) value.data; + if (value.type is typeid(creal)) + return cast(T) *cast(creal*) value.data; + if (value.type is typeid(ifloat)) + return cast(T) *cast(ifloat*) value.data; + if (value.type is typeid(idouble)) + return cast(T) *cast(idouble*) value.data; + if (value.type is typeid(ireal)) + return cast(T) *cast(ireal*) value.data; + return unboxCastReal!(T)(value); + } +} + +/** A generic unboxer for the imaginary numeric types. */ +private template unboxCastImaginary(T) +{ + T unboxCastImaginary(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(ifloat)) + return cast(T) *cast(ifloat*) value.data; + if (value.type is typeid(idouble)) + return cast(T) *cast(idouble*) value.data; + if (value.type is typeid(ireal)) + return cast(T) *cast(ireal*) value.data; + throw new UnboxException(value, typeid(T)); + } +} + +/** This unbox template takes a template parameter and returns a function that + * takes a box object and returns the specified type. If it cannot cast to + * the type, it throws UnboxException. For example: + * + * Box y = box(4); + * int x = unbox!(int) (y); + */ +template unbox(T) +{ + T unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T) is value.type) + return *cast(T*) value.data; + throw new UnboxException(value, typeid(T)); + } +} + +template unbox(T : byte) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : ubyte) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : short) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : ushort) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : int) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : uint) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : long) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : ulong) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : float) { T unbox(Box value) { return unboxCastReal!(T) (value); } } +template unbox(T : double) { T unbox(Box value) { return unboxCastReal!(T) (value); } } +template unbox(T : real) { T unbox(Box value) { return unboxCastReal!(T) (value); } } +template unbox(T : cfloat) { T unbox(Box value) { return unboxCastComplex!(T) (value); } } +template unbox(T : cdouble) { T unbox(Box value) { return unboxCastComplex!(T) (value); } } +template unbox(T : creal) { T unbox(Box value) { return unboxCastComplex!(T) (value); } } +template unbox(T : ifloat) { T unbox(Box value) { return unboxCastImaginary!(T) (value); } } +template unbox(T : idouble) { T unbox(Box value) { return unboxCastImaginary!(T) (value); } } +template unbox(T : ireal) { T unbox(Box value) { return unboxCastImaginary!(T) (value); } } + +template unbox(T : Object) +{ + T unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T) == value.type || cast(TypeInfo_Class) value.type) + { + Object object = *cast(Object*)value.data; + T result = cast(T)object; + + if (object is null) + return null; + if (result is null) + throw new UnboxException(value, typeid(T)); + return result; + } + + if (typeid(void*) is value.type && *cast(void**) value.data is null) + return null; + throw new UnboxException(value, typeid(T)); + } +} + +template unbox(T : T[]) +{ + T[] unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T[]) is value.type) + return *cast(T[]*) value.data; + if (typeid(void*) is value.type && *cast(void**) value.data is null) + return null; + throw new UnboxException(value, typeid(T[])); + } +} + +template unbox(T : T*) +{ + T* unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T*) is value.type) + return *cast(T**) value.data; + if (typeid(void*) is value.type && *cast(void**) value.data is null) + return null; + if (typeid(T[]) is value.type) + return *cast(T[]*) value.data; + + throw new UnboxException(value, typeid(T*)); + } +} + +template unbox(T : void*) +{ + T unbox(Box value) + { + assert (value.type !== null); + + if (cast(TypeInfo_Pointer) value.type) + return *cast(void**) value.data; + if (isArrayTypeInfo(value.type)) + return *cast(void[]*) value.data; + if (typeid(Object) == value.type) + return *cast(Object*) value.data; + + throw new UnboxException(value, typeid(T)); + } +} + +/** Return whether the value can be unboxed to this type without throwing + * UnboxException. + */ +template unboxable(T) +{ + bit unboxable(Box value) + { + return value.unboxable(typeid(T)); + } +} + +/* Tests unboxing - assert that if it says it's unboxable, it is. */ +private template unboxTest(T) +{ + T unboxTest(Box value) + { + T result; + bit unboxable = value.unboxable(typeid(T)); + + try result = unbox!(T) (value); + catch (UnboxException error) + { + if (unboxable) + throw new Error ("Could not unbox " ~ value.type.toString ~ " as " ~ typeid(T).toString ~ "; however, unboxable says it would work."); + assert (!unboxable); + throw error; + } + + if (!unboxable) + throw new Error ("Unboxed " ~ value.type.toString ~ " as " ~ typeid(T).toString ~ "; however, unboxable says it should fail."); + return result; + } +} + +unittest +{ + class A { } + class B : A { } + struct SA { } + struct SB { } + + Box a, b; + + /* Call the function, catch UnboxException, return that it threw correctly. */ + bit fails(void delegate()func) + { + try func(); + catch (UnboxException error) + return true; + return false; + } + + /* Check that equals and comparison work properly. */ + a = box(0); + b = box(32); + assert (a != b); + assert (a == a); + assert (a < b); + + /* Check that toString works properly. */ + assert (b.toString == "32"); + + /* Assert that unboxable works. */ + assert (unboxable!(char[])(box("foobar"))); + + /* Assert that we can cast from int to byte. */ + assert (unboxTest!(byte)(b) == 32); + + /* Assert that we can cast from int to real. */ + assert (unboxTest!(real)(b) == 32.0L); + + /* Check that real works properly. */ + assert (unboxTest!(real)(box(32.45L)) == 32.45L); + + /* Assert that we cannot implicitly cast from real to int. */ + assert(fails(delegate void() { unboxTest!(int)(box(1.3)); })); + + /* Check that the unspecialized unbox template works. */ + assert(unboxTest!(char[])(box("foobar")) == "foobar"); + + /* Assert that complex works correctly. */ + assert(unboxTest!(cdouble)(box(1 + 2i)) == 1 + 2i); + + /* Assert that imaginary works correctly. */ + assert(unboxTest!(ireal)(box(45i)) == 45i); + + /* Create an array of boxes from arguments. */ + Box[] array = boxArray(16, "foobar", new Object); + + assert(array.length == 3); + assert(unboxTest!(int)(array[0]) == 16); + assert(unboxTest!(char[])(array[1]) == "foobar"); + assert(unboxTest!(Object)(array[2]) !== null); + + /* Convert the box array back into arguments. */ + TypeInfo[] array_types; + void* array_data; + + boxArrayToArguments(array, array_types, array_data); + assert (array_types.length == 3); + + /* Confirm the symmetry. */ + assert (boxArray(array_types, array_data) == array); + + /* Assert that we can cast from int to creal. */ + assert (unboxTest!(creal)(box(45)) == 45+0i); + + /* Assert that we can cast from idouble to creal. */ + assert (unboxTest!(creal)(box(45i)) == 0+45i); + + /* Assert that equality testing casts properly. */ + assert (box(1) == box(cast(byte)1)); + assert (box(cast(real)4) == box(4)); + assert (box(5) == box(5+0i)); + assert (box(0+4i) == box(4i)); + assert (box(8i) == box(0+8i)); + + /* Assert that comparisons cast properly. */ + assert (box(450) < box(451)); + assert (box(4) > box(3.0)); + assert (box(0+3i) < box(0+4i)); + + /* Assert that casting from bit to int works. */ + assert (1 == unboxTest!(int)(box(true))); + assert (box(1) == box(true)); + + /* Assert that unboxing to an object works properly. */ + assert (unboxTest!(B)(box(cast(A)new B)) !== null); + + /* Assert that illegal object casting fails properly. */ + assert (fails(delegate void() { unboxTest!(B)(box(new A)); })); + + /* Assert that we can unbox a null. */ + assert (unboxTest!(A)(box(cast(A)null)) is null); + assert (unboxTest!(A)(box(null)) is null); + + /* Unboxing null in various contexts. */ + assert (unboxTest!(char[])(box(null)) is null); + assert (unboxTest!(int*)(box(null)) is null); + + /* Assert that unboxing between pointer types fails. */ + int [1] p; + assert (fails(delegate void() { unboxTest!(char*)(box(p.ptr)); })); + + /* Assert that unboxing various types as void* does work. */ + assert (unboxTest!(void*)(box(p.ptr))); // int* + assert (unboxTest!(void*)(box(p))); // int[] + assert (unboxTest!(void*)(box(new A))); // Object + + /* Assert that we can't unbox an integer as bit. */ + assert (!unboxable!(bit) (box(4))); + + /* Assert that we can't unbox a struct as another struct. */ + SA sa; + assert (!unboxable!(SB)(box(sa))); +} diff -uNr dmd-0.123/dmd/src/phobos/std/stream.d dmd-0.124/dmd/src/phobos/std/stream.d --- dmd-0.123/dmd/src/phobos/std/stream.d 2005-05-11 14:55:04.000000000 +0200 +++ dmd-0.124/dmd/src/phobos/std/stream.d 2005-05-19 11:18:32.000000000 +0200 @@ -1387,7 +1387,7 @@ throw new WriteException("Unable to write to stream"); } } - long diff = bufferCurPos-bufferSourcePos; + long diff = cast(long)bufferCurPos-bufferSourcePos; if (diff != 0 && seekable) { // move actual file pointer to current position streamPos = s.seek(diff, SeekPos.Current); @@ -1417,7 +1417,7 @@ // returns size of stream ulong size() { - flush(); + if (bufferDirty) flush(); return s.size(); } @@ -1785,12 +1785,17 @@ assert(file.position() == 18 + 13 + 4); // we must be at the end of file assert(file.eof()); + long oldsize = file.size(); file.close(); // no operations are allowed when file is closed assert(!file.readable && !file.writeable && !file.seekable); file.open("stream.$$$"); // should be ok to read assert(file.readable); + // test getc/ungetc and size() + char c1 = file.getc(); + file.ungetc(c1); + assert( file.size() == oldsize ); assert(!std.string.cmp(file.readLine(), "Testing stream.d:")); // jump over "Hello, " file.seek(7, SeekPos.Current); diff -uNr dmd-0.123/dmd/src/phobos/std/string.d dmd-0.124/dmd/src/phobos/std/string.d --- dmd-0.123/dmd/src/phobos/std/string.d 2005-05-11 14:55:04.000000000 +0200 +++ dmd-0.124/dmd/src/phobos/std/string.d 2005-05-19 11:18:30.000000000 +0200 @@ -1374,6 +1374,7 @@ /************************************** * Split s[] into an array of lines, * using CR, LF, or CR-LF as the delimiter. + * The delimiter is not included in the line. */ char[][] splitlines(char[] s) diff -uNr dmd-0.123/dmd/src/phobos/std/typeinfo/ti_void.d dmd-0.124/dmd/src/phobos/std/typeinfo/ti_void.d --- dmd-0.123/dmd/src/phobos/std/typeinfo/ti_void.d 2005-05-11 14:55:04.000000000 +0200 +++ dmd-0.124/dmd/src/phobos/std/typeinfo/ti_void.d 2005-05-19 11:18:32.000000000 +0200 @@ -13,13 +13,11 @@ int equals(void *p1, void *p2) { - assert(0); return *cast(byte *)p1 == *cast(byte *)p2; } int compare(void *p1, void *p2) { - assert(0); return *cast(byte *)p1 - *cast(byte *)p2; } @@ -32,7 +30,6 @@ { byte t; - assert(0); t = *cast(byte *)p1; *cast(byte *)p1 = *cast(byte *)p2; *cast(byte *)p2 = t; diff -uNr dmd-0.123/dmd/src/phobos/unittest.d dmd-0.124/dmd/src/phobos/unittest.d --- dmd-0.123/dmd/src/phobos/unittest.d 2005-05-11 14:55:04.000000000 +0200 +++ dmd-0.124/dmd/src/phobos/unittest.d 2005-05-19 11:18:30.000000000 +0200 @@ -44,6 +44,7 @@ import std.md5; import std.stdio; import std.conv; +import std.boxer; int main(char[][] args) { @@ -76,6 +77,7 @@ writefln("hello world!"); // std.format + Box abox; { creal c = 3.0 + 4.0i; c = sqrt(c); diff -uNr dmd-0.123/dmd/src/phobos/win32.mak dmd-0.124/dmd/src/phobos/win32.mak --- dmd-0.123/dmd/src/phobos/win32.mak 2005-05-11 14:55:04.000000000 +0200 +++ dmd-0.124/dmd/src/phobos/win32.mak 2005-05-19 11:18:30.000000000 +0200 @@ -65,7 +65,7 @@ Czlib.obj Dzlib.obj zip.obj process.obj registry.obj recls.obj \ socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \ perf.obj openrj.obj uni.obj winsock.obj oldsyserror.obj \ - errno.obj \ + errno.obj boxer.obj \ ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ @@ -90,7 +90,7 @@ std\intrinsic.d std\array.d std\switcherr.d std\syserror.d \ std\regexp.d std\random.d std\stream.d std\process.d std\recls.d \ std\socket.d std\socketstream.d std\loader.d std\stdarg.d std\format.d \ - std\stdio.d std\perf.d std\openrj.d std\uni.d + std\stdio.d std\perf.d std\openrj.d std\uni.d std\boxer.d SRC_STD_C= std\c\process.d std\c\stdlib.d std\c\time.d std\c\stdio.d \ std\c\math.d std\c\stdarg.d std\c\stddef.d @@ -436,6 +436,9 @@ base64.obj : std\base64.d $(DMD) -c $(DFLAGS) -inline std\base64.d +boxer.obj : std\boxer.d + $(DMD) -c $(DFLAGS) std\boxer.d + compiler.obj : std\compiler.d $(DMD) -c $(DFLAGS) std\compiler.d