diff -uNr dmd-1.005/dmd/src/dmd/arraytypes.h dmd-1.006/dmd/src/dmd/arraytypes.h --- dmd-1.005/dmd/src/dmd/arraytypes.h 2006-10-26 00:30:42.000000000 +0200 +++ dmd-1.006/dmd/src/dmd/arraytypes.h 2007-02-09 19:50:02.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 2006 by Digital Mars +// Copyright (c) 2006-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com diff -uNr dmd-1.005/dmd/src/dmd/constfold.c dmd-1.006/dmd/src/dmd/constfold.c --- dmd-1.005/dmd/src/dmd/constfold.c 2007-01-30 23:46:28.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/constfold.c 2007-02-13 21:48:02.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -17,6 +17,9 @@ #include #endif +#include "mem.h" +#include "root.h" + #include "mtype.h" #include "expression.h" @@ -29,6 +32,7 @@ static real_t zero; // work around DMC bug for now +#define LOG 0 /* ================================== isConst() ============================== */ @@ -58,139 +62,66 @@ return 2; } -/* ================================== constFold() ============================== */ +/* =============================== constFold() ============================== */ -Expression *Expression::constFold() -{ - return this; -} +/* The constFold() functions were redundant with the optimize() ones, + * and so have been folded in with them. + */ -Expression *NegExp::constFold() -{ - e1 = e1->constFold(); - if (e1->type->isreal()) - { RealExp *e; +/* ========================================================================== */ +Expression *Neg(Type *type, Expression *e1) +{ Expression *e; + Loc loc = e1->loc; + + if (e1->type->isreal()) + { e = new RealExp(loc, -e1->toReal(), type); - return e; } else if (e1->type->isimaginary()) - { RealExp *e; - + { e = new RealExp(loc, -e1->toImaginary(), type); - return e; } else if (e1->type->iscomplex()) - { ComplexExp *e; - + { e = new ComplexExp(loc, -e1->toComplex(), type); - return e; } else - return new IntegerExp(loc, -e1->toInteger(), type); -} - -Expression *ComExp::constFold() -{ - e1 = e1->constFold(); - return new IntegerExp(loc, ~e1->toInteger(), type); + e = new IntegerExp(loc, -e1->toInteger(), type); + return e; } -Expression *NotExp::constFold() -{ - e1 = e1->constFold(); - return new IntegerExp(loc, e1->isBool(0), type); -} +Expression *Com(Type *type, Expression *e1) +{ Expression *e; + Loc loc = e1->loc; -Expression *BoolExp::constFold() -{ - e1 = e1->constFold(); - return new IntegerExp(loc, e1->isBool(1), type); + e = new IntegerExp(loc, ~e1->toInteger(), type); + return e; } -Expression *CastExp::constFold() -{ - //printf("CastExp::constFold(%s)\n", toChars()); - //printf("from %s to %s\n", type->toChars(), to->toChars()); - //printf("type = %p\n", type); - assert(type); - - e1 = e1->constFold(); - if (e1->op == TOKsymoff) - { - if (type->size() == e1->type->size() && - type->toBasetype()->ty != Tsarray) - { - e1->type = type; - return e1; - } - return this; - } - - Type *tb = to->toBasetype(); - if (tb->ty == Tbit || tb->ty == Tbool) - return new IntegerExp(loc, e1->toInteger() != 0, type); - if (type->isintegral()) - { - if (e1->type->isfloating()) - { integer_t result; - real_t r = e1->toReal(); - - switch (type->toBasetype()->ty) - { - case Tint8: result = (d_int8)r; break; - case Tchar: - case Tuns8: result = (d_uns8)r; break; - case Tint16: result = (d_int16)r; break; - case Twchar: - case Tuns16: result = (d_uns16)r; break; - case Tint32: result = (d_int32)r; break; - case Tdchar: - case Tuns32: result = (d_uns32)r; break; - case Tint64: result = (d_int64)r; break; - case Tuns64: result = (d_uns64)r; break; - default: - assert(0); - } - - return new IntegerExp(loc, result, type); - } - if (type->isunsigned()) - return new IntegerExp(loc, e1->toUInteger(), type); - else - return new IntegerExp(loc, e1->toInteger(), type); - } - if (tb->isreal()) - { real_t value = e1->toReal(); +Expression *Not(Type *type, Expression *e1) +{ Expression *e; + Loc loc = e1->loc; - return new RealExp(loc, value, type); - } - if (tb->isimaginary()) - { real_t value = e1->toImaginary(); + e = new IntegerExp(loc, e1->isBool(0), type); + return e; +} - return new RealExp(loc, value, type); - } - if (tb->iscomplex()) - { complex_t value = e1->toComplex(); +Expression *Bool(Type *type, Expression *e1) +{ Expression *e; + Loc loc = e1->loc; - return new ComplexExp(loc, value, type); - } - if (tb->isscalar()) - return new IntegerExp(loc, e1->toInteger(), type); - if (tb->ty != Tvoid) - error("cannot cast %s to %s", e1->type->toChars(), to->toChars()); - return this; + e = new IntegerExp(loc, e1->isBool(1), type); + return e; } -Expression *AddExp::constFold() -{ - Expression *e; +Expression *Add(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; - //printf("AddExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->op == TOKsymoff && e2->op == TOKsymoff) - return this; +#if LOG + printf("Add(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); +#endif if (type->isreal()) { e = new RealExp(loc, e1->toReal() + e2->toReal(), type); @@ -283,14 +214,11 @@ return e; } -Expression *MinExp::constFold() -{ - Expression *e; - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e2->op == TOKsymoff) - return this; +Expression *Min(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + if (type->isreal()) { e = new RealExp(loc, e1->toReal() - e2->toReal(), type); @@ -379,18 +307,16 @@ return e; } -Expression *MulExp::constFold() +Expression *Mul(Type *type, Expression *e1, Expression *e2) { Expression *e; + Loc loc = e1->loc; - //printf("MulExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); if (type->isfloating()) - { complex_t c; + { complex_t c; #ifdef IN_GCC real_t r; #else - d_float80 r; + d_float80 r; #endif if (e1->type->isreal()) @@ -452,18 +378,16 @@ return e; } -Expression *DivExp::constFold() +Expression *Div(Type *type, Expression *e1, Expression *e2) { Expression *e; + Loc loc = e1->loc; - //printf("DivExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); if (type->isfloating()) - { complex_t c; + { complex_t c; #ifdef IN_GCC real_t r; #else - d_float80 r; + d_float80 r; #endif //e1->type->print(); @@ -516,7 +440,7 @@ assert(0); } else - { sinteger_t n1; + { sinteger_t n1; sinteger_t n2; sinteger_t n; @@ -527,7 +451,7 @@ e2 = new IntegerExp(0, 1, e2->type); n2 = 1; } - if (isunsigned()) + if (e1->type->isunsigned() || e2->type->isunsigned()) n = ((d_uns64) n1) / ((d_uns64) n2); else n = n1 / n2; @@ -536,11 +460,10 @@ return e; } -Expression *ModExp::constFold() +Expression *Mod(Type *type, Expression *e1, Expression *e2) { Expression *e; + Loc loc = e1->loc; - e1 = e1->constFold(); - e2 = e2->constFold(); if (type->isfloating()) { complex_t c; @@ -580,7 +503,7 @@ assert(0); } else - { sinteger_t n1; + { sinteger_t n1; sinteger_t n2; sinteger_t n; @@ -591,7 +514,7 @@ e2 = new IntegerExp(0, 1, e2->type); n2 = 1; } - if (isunsigned()) + if (e1->type->isunsigned() || e2->type->isunsigned()) n = ((d_uns64) n1) % ((d_uns64) n2); else n = n1 % n2; @@ -600,21 +523,20 @@ return e; } -Expression *ShlExp::constFold() -{ - //printf("ShlExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); +Expression *Shl(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + + e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); + return e; } -Expression *ShrExp::constFold() -{ +Expression *Shr(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; unsigned count; integer_t value; - e1 = e1->constFold(); - e2 = e2->constFold(); value = e1->toInteger(); count = e2->toInteger(); switch (e1->type->toBasetype()->ty) @@ -654,17 +576,16 @@ default: assert(0); } - return new IntegerExp(loc, value, type); + e = new IntegerExp(loc, value, type); + return e; } -Expression *UshrExp::constFold() -{ - //printf("UshrExp::constFold() %s\n", toChars()); +Expression *Ushr(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; unsigned count; integer_t value; - e1 = e1->constFold(); - e2 = e2->constFold(); value = e1->toInteger(); count = e2->toInteger(); switch (e1->type->toBasetype()->ty) @@ -694,70 +615,159 @@ default: assert(0); } - return new IntegerExp(loc, value, type); + e = new IntegerExp(loc, value, type); + return e; } -Expression *AndExp::constFold() -{ - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() & e2->toInteger(), type); +Expression *And(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + + e = new IntegerExp(loc, e1->toInteger() & e2->toInteger(), type); + return e; } -Expression *OrExp::constFold() -{ - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() | e2->toInteger(), type); +Expression *Or(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + + e = new IntegerExp(loc, e1->toInteger() | e2->toInteger(), type); + return e; } -Expression *XorExp::constFold() -{ - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type); +Expression *Xor(Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + + e = new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type); + return e; } -Expression *AndAndExp::constFold() -{ int n1, n2; +/* Also returns EXP_CANT_INTERPRET if cannot be computed. + */ +Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + int cmp; + real_t r1; + real_t r2; - e1 = e1->constFold(); - e2 = e2->constFold(); + assert(op == TOKequal || op == TOKnotequal); - n1 = e1->isBool(1); - if (n1) - { n2 = e2->isBool(1); - assert(n2 || e2->isBool(0)); + if (e1->op == TOKstring && e2->op == TOKstring) + { StringExp *es1 = (StringExp *)e1; + StringExp *es2 = (StringExp *)e2; + + assert(es1->sz == es2->sz); + if (es1->len == es2->len && + memcmp(es1->string, es2->string, es1->sz * es1->len) == 0) + cmp = 1; + else + cmp = 0; + } + else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral) + { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + + if ((!es1->elements || !es1->elements->dim) && + (!es2->elements || !es2->elements->dim)) + cmp = 1; // both arrays are empty + else if (!es1->elements || !es2->elements) + cmp = 0; + else if (es1->elements->dim != es2->elements->dim) + cmp = 0; + else + { + for (size_t i = 0; i < es1->elements->dim; i++) + { Expression *ee1 = (Expression *)es1->elements->data[i]; + Expression *ee2 = (Expression *)es2->elements->data[i]; + + Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); + if (v == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + cmp = v->toInteger(); + if (cmp == 0) + break; + } + } + } +#if 0 // Should handle this + else if (e1->op == TOKarrayliteral && e2->op == TOKstring) + { + } +#endif + else if (e1->isConst() != 1 || e2->isConst() != 1) + return EXP_CANT_INTERPRET; + else if (e1->type->isreal()) + { + r1 = e1->toReal(); + r2 = e2->toReal(); + goto L1; + } + else if (e1->type->isimaginary()) + { + r1 = e1->toImaginary(); + r2 = e2->toImaginary(); + L1: +#if __DMC__ + cmp = (r1 == r2); +#else + if (isnan(r1) || isnan(r2)) // if unordered + { + cmp = 0; + } + else + { + cmp = (r1 == r2); + } +#endif + } + else if (e1->type->iscomplex()) + { + cmp = e1->toComplex() == e2->toComplex(); + } + else if (e1->type->isintegral()) + { + cmp = (e1->toInteger() == e2->toInteger()); } else - assert(e1->isBool(0)); - return new IntegerExp(loc, n1 && n2, type); + return EXP_CANT_INTERPRET; + if (op == TOKnotequal) + cmp ^= 1; + e = new IntegerExp(loc, cmp, type); + return e; } -Expression *OrOrExp::constFold() -{ int n1, n2; - - e1 = e1->constFold(); - e2 = e2->constFold(); +Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + int cmp; - n1 = e1->isBool(1); - if (!n1) + if (e1->op == TOKsymoff && e2->op == TOKsymoff) { - assert(e1->isBool(0)); - n2 = e2->isBool(1); - assert(n2 || e2->isBool(0)); + SymOffExp *es1 = (SymOffExp *)e1; + SymOffExp *es2 = (SymOffExp *)e2; + + cmp = (es1->var == es2->var && es1->offset == es2->offset); } - return new IntegerExp(loc, n1 || n2, type); + else if (e1->isConst() == 1 && e2->isConst() == 1) + return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, + type, e1, e2); + else + assert(0); + if (op == TOKnotidentity) + cmp ^= 1; + return new IntegerExp(loc, cmp, type); } -Expression *CmpExp::constFold() -{ integer_t n; + +Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2) +{ Expression *e; + Loc loc = e1->loc; + integer_t n; real_t r1; real_t r2; - //printf("CmpExp::constFold() %s\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); if (e1->type->isreal()) { r1 = e1->toReal(); @@ -848,12 +858,12 @@ assert(0); } else - { sinteger_t n1; + { sinteger_t n1; sinteger_t n2; n1 = e1->toInteger(); n2 = e2->toInteger(); - if (isunsigned()) + if (e1->type->isunsigned() || e2->type->isunsigned()) { switch (op) { @@ -898,93 +908,375 @@ } } } - return new IntegerExp(loc, n, type); + e = new IntegerExp(loc, n, type); + return e; } -Expression *EqualExp::constFold() -{ int cmp; - real_t r1; - real_t r2; +/* Also returns EXP_CANT_INTERPRET if cannot be computed. + * to: type to cast to + * type: type to paint the result + */ + +Expression *Cast(Type *type, Type *to, Expression *e1) +{ Expression *e = EXP_CANT_INTERPRET; + Loc loc = e1->loc; + + //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars()); + //printf("e1->type = %s\n", e1->type->toChars()); + if (type->equals(e1->type) && to->equals(type)) + return e1; - //printf("EqualExp::constFold() %s\n", toChars()); - assert(op == TOKequal || op == TOKnotequal); - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isreal()) + if (e1->isConst() != 1) + return EXP_CANT_INTERPRET; + + Type *tb = to->toBasetype(); + if (tb->ty == Tbool) + e = new IntegerExp(loc, e1->toInteger() != 0, type); + else if (type->isintegral()) { - r1 = e1->toReal(); - r2 = e2->toReal(); - goto L1; + if (e1->type->isfloating()) + { integer_t result; + real_t r = e1->toReal(); + + switch (type->toBasetype()->ty) + { + case Tint8: result = (d_int8)r; break; + case Tchar: + case Tuns8: result = (d_uns8)r; break; + case Tint16: result = (d_int16)r; break; + case Twchar: + case Tuns16: result = (d_uns16)r; break; + case Tint32: result = (d_int32)r; break; + case Tdchar: + case Tuns32: result = (d_uns32)r; break; + case Tint64: result = (d_int64)r; break; + case Tuns64: result = (d_uns64)r; break; + default: + assert(0); + } + + e = new IntegerExp(loc, result, type); + } + else if (type->isunsigned()) + e = new IntegerExp(loc, e1->toUInteger(), type); + else + e = new IntegerExp(loc, e1->toInteger(), type); } - else if (e1->type->isimaginary()) + else if (tb->isreal()) + { real_t value = e1->toReal(); + + e = new RealExp(loc, value, type); + } + else if (tb->isimaginary()) + { real_t value = e1->toImaginary(); + + e = new RealExp(loc, value, type); + } + else if (tb->iscomplex()) + { complex_t value = e1->toComplex(); + + e = new ComplexExp(loc, value, type); + } + else if (tb->isscalar()) + e = new IntegerExp(loc, e1->toInteger(), type); + else { - r1 = e1->toImaginary(); - r2 = e2->toImaginary(); - L1: -#if __DMC__ - cmp = (r1 == r2); -#else - if (isnan(r1) || isnan(r2)) // if unordered - { - cmp = 0; - } + if (tb->ty == Tvoid) + e = EXP_CANT_INTERPRET; else - { - cmp = (r1 == r2); + { error("cannot cast %s to %s", e1->type->toChars(), type->toChars()); + e = new IntegerExp(loc, 0, type); } -#endif } - else if (e1->type->iscomplex()) - { - cmp = e1->toComplex() == e2->toComplex(); + return e; +} + + +Expression *ArrayLength(Type *type, Expression *e1) +{ Expression *e; + Loc loc = e1->loc; + + if (e1->op == TOKstring) + { StringExp *es1 = (StringExp *)e1; + + e = new IntegerExp(loc, es1->len, type); + } + else if (e1->op == TOKarrayliteral) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; + size_t dim; + + dim = ale->elements ? ale->elements->dim : 0; + e = new IntegerExp(loc, dim, type); } else - { - cmp = (e1->toInteger() == e2->toInteger()); + e = EXP_CANT_INTERPRET; + return e; +} + +/* Also return EXP_CANT_INTERPRET if this fails + */ +Expression *Index(Type *type, Expression *e1, Expression *e2) +{ Expression *e = EXP_CANT_INTERPRET; + Loc loc = e1->loc; + + //printf("Index()\n"); + if (e1->op == TOKstring && e2->op == TOKint64) + { StringExp *es1 = (StringExp *)e1; + uinteger_t i = e2->toInteger(); + + if (i >= es1->len) + e1->error("string index %ju is out of bounds [0 .. %ju]", i, es1->len); + else + { integer_t value; + + switch (es1->sz) + { + case 1: + value = ((unsigned char *)es1->string)[i]; + break; + + case 2: + value = ((unsigned short *)es1->string)[i]; + break; + + case 4: + value = ((unsigned int *)es1->string)[i]; + break; + + default: + assert(0); + break; + } + e = new IntegerExp(loc, value, type); + } } - if (op == TOKnotequal) - cmp ^= 1; - return new IntegerExp(loc, cmp, type); + else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64) + { TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype(); + uinteger_t length = tsa->dim->toInteger(); + uinteger_t i = e2->toInteger(); + + if (i >= length) + { error("array index %ju is out of bounds [0 .. %ju]", i, length); + } + else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; + e = (Expression *)ale->elements->data[i]; + e->type = type; + } + } + return e; } -Expression *IdentityExp::constFold() -{ int cmp; +/* Also return EXP_CANT_INTERPRET if this fails + */ +Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) +{ Expression *e = EXP_CANT_INTERPRET; + Loc loc = e1->loc; - //printf("IdentityExp::constFold() %s\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isfloating()) - { - cmp = e1->toComplex() == e2->toComplex(); +#if LOG + printf("Slice()\n"); +#endif + if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64) + { StringExp *es1 = (StringExp *)e1; + uinteger_t ilwr = lwr->toInteger(); + uinteger_t iupr = upr->toInteger(); + + if (iupr > es1->len || ilwr > iupr) + e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); + else + { integer_t value; + void *s; + size_t len = iupr - ilwr; + int sz = es1->sz; + StringExp *es; + + s = mem.malloc((len + 1) * sz); + memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz); + memset((unsigned char *)s + len * sz, 0, sz); + + es = new StringExp(loc, s, len, es1->postfix); + es->sz = sz; + es->committed = 1; + es->type = type; + e = es; + } + } + else if (e1->op == TOKarrayliteral && + lwr->op == TOKint64 && upr->op == TOKint64 && + !e1->checkSideEffect(2)) + { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + uinteger_t ilwr = lwr->toInteger(); + uinteger_t iupr = upr->toInteger(); + + if (iupr > es1->elements->dim || ilwr > iupr) + e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); + else + { + Expressions *elements = new Expressions(); + elements->setDim(iupr - ilwr); + memcpy(elements->data, + es1->elements->data + ilwr, + (iupr - ilwr) * sizeof(es1->elements->data[0])); + e = new ArrayLiteralExp(e1->loc, elements); + e->type = type; + } } - else if (e1->type->isintegral()) + return e; +} + +/* Also return EXP_CANT_INTERPRET if this fails + */ +Expression *Cat(Type *type, Expression *e1, Expression *e2) +{ Expression *e = EXP_CANT_INTERPRET; + Loc loc = e1->loc; + + //printf("Cat()\n"); + if (e1->op == TOKstring && e2->op == TOKstring) + { + // Concatenate the strings + void *s; + StringExp *es1 = (StringExp *)e1; + StringExp *es2 = (StringExp *)e2; + StringExp *es; + Type *t; + size_t len = es1->len + es2->len; + int sz = es1->sz; + + assert(sz == es2->sz); + s = mem.malloc((len + 1) * sz); + memcpy(s, es1->string, es1->len * sz); + memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz); + + // Add terminating 0 + memset((unsigned char *)s + len * sz, 0, sz); + + es = new StringExp(loc, s, len); + es->sz = sz; + es->committed = es1->committed | es2->committed; + if (es1->committed) + t = es1->type; + else + t = es2->type; + es->type = type; + e = es; + } + else if (e1->op == TOKstring && e2->op == TOKint64) + { + // Concatenate the strings + void *s; + StringExp *es1 = (StringExp *)e1; + StringExp *es; + Type *t; + size_t len = es1->len + 1; + int sz = es1->sz; + integer_t v = e2->toInteger(); + + s = mem.malloc((len + 1) * sz); + memcpy(s, es1->string, es1->len * sz); + memcpy((unsigned char *)s + es1->len * sz, &v, sz); + + // Add terminating 0 + memset((unsigned char *)s + len * sz, 0, sz); + + es = new StringExp(loc, s, len); + es->sz = sz; + es->committed = es1->committed; + t = es1->type; + es->type = type; + e = es; + } + else if (e1->op == TOKint64 && e2->op == TOKstring) + { + // Concatenate the strings + void *s; + StringExp *es2 = (StringExp *)e2; + StringExp *es; + Type *t; + size_t len = 1 + es2->len; + int sz = es2->sz; + integer_t v = e1->toInteger(); + + s = mem.malloc((len + 1) * sz); + memcpy((unsigned char *)s, &v, sz); + memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); + + // Add terminating 0 + memset((unsigned char *)s + len * sz, 0, sz); + + es = new StringExp(loc, s, len); + es->sz = sz; + es->committed = es2->committed; + t = es2->type; + es->type = type; + e = es; + } + else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral && + e1->type->equals(e2->type)) + { + // Concatenate the arrays + ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + + es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); + es1->elements->insert(es1->elements->dim, es2->elements); + e = es1; + + if (type->toBasetype()->ty == Tsarray) + { + e->type = new TypeSArray(e1->type->toBasetype()->next, new IntegerExp(0, es1->elements->dim, Type::tindex)); + e->type = e->type->semantic(loc, NULL); + } + else + e->type = type; + } + else if (e1->op == TOKarrayliteral && + e1->type->toBasetype()->next->equals(e2->type)) { - cmp = (e1->toInteger() == e2->toInteger()); + ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + + es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); + es1->elements->push(e2); + e = es1; + + if (type->toBasetype()->ty == Tsarray) + { + e->type = new TypeSArray(e2->type, new IntegerExp(0, es1->elements->dim, Type::tindex)); + e->type = e->type->semantic(loc, NULL); + } + else + e->type = type; } - else if (e1->op == TOKsymoff && e2->op == TOKsymoff) + else if (e2->op == TOKarrayliteral && + e2->type->toBasetype()->next->equals(e1->type)) { - SymOffExp *es1 = (SymOffExp *)e1; - SymOffExp *es2 = (SymOffExp *)e2; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; - cmp = (es1->var == es2->var && es1->offset == es2->offset); + es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy()); + es2->elements->shift(e1); + e = es2; + + if (type->toBasetype()->ty == Tsarray) + { + e->type = new TypeSArray(e1->type, new IntegerExp(0, es2->elements->dim, Type::tindex)); + e->type = e->type->semantic(loc, NULL); + } + else + e->type = type; } - else + else if (e1->op == TOKnull && e2->op == TOKstring) { - return this; + e = e2; + goto L1; } - if (op == TOKnotidentity) - cmp ^= 1; - return new IntegerExp(loc, cmp, type); + else if (e1->op == TOKstring && e2->op == TOKnull) + { e = e1; + L1: + if (!e->type->equals(type)) + { StringExp *se = (StringExp *)e->copy(); + e = se->castTo(NULL, type); + } + } + return e; } -Expression *CondExp::constFold() -{ - int n; - - econd = econd->constFold(); - n = econd->isBool(1); - assert(n || econd->isBool(0)); - return n ? e1->constFold() : e2->constFold(); -} - diff -uNr dmd-1.005/dmd/src/dmd/declaration.c dmd-1.006/dmd/src/dmd/declaration.c --- dmd-1.005/dmd/src/dmd/declaration.c 2007-01-24 16:29:26.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/declaration.c 2007-02-13 23:27:12.000000000 +0100 @@ -527,6 +527,7 @@ ctorinit = 0; aliassym = NULL; onstack = 0; + value = NULL; } Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) @@ -885,7 +886,7 @@ } else { - e = e->optimize(WANTvalue); + e = e->optimize(WANTvalue | WANTinterpret); if (e->op == TOKint64 || e->op == TOKstring) { ei->exp = e; // no errors, keep result diff -uNr dmd-1.005/dmd/src/dmd/declaration.h dmd-1.006/dmd/src/dmd/declaration.h --- dmd-1.005/dmd/src/dmd/declaration.h 2007-01-24 16:27:48.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/declaration.h 2007-02-14 20:42:32.000000000 +0100 @@ -210,6 +210,8 @@ int onstack; // 1: it has been allocated on the stack // 2: on stack, run destructor anyway Dsymbol *aliassym; // if redone as alias to another symbol + Expression *value; // when interpreting, this is the value + // (NULL if value not determinable) VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); @@ -414,7 +416,7 @@ #if IN_GCC VarDeclaration *v_argptr; // '_argptr' variable #endif - Array *parameters; // Array of Argument's for parameters + Dsymbols *parameters; // Array of VarDeclaration's for parameters DsymbolTable *labtab; // statement label symbol table Declaration *overnext; // next in overload list Loc endloc; // location of closing curly bracket @@ -423,6 +425,7 @@ int inlineAsm; // !=0 if has inline assembler ILS inlineStatus; int inlineNest; // !=0 if nested inline + int cantInterpret; // !=0 if cannot interpret function int semanticRun; // !=0 if semantic3() had been run int nestedFrameRef; // !=0 if nested variables referenced frame ptr ForeachStatement *fes; // if foreach body, this is the foreach @@ -431,6 +434,7 @@ // of the 'introducing' function // this one is overriding int inferRetType; // !=0 if return type is to be inferred + Scope *scope; // !=NULL means context to use // Things that should really go into Scope int hasReturnExp; // 1 if there's a return exp; statement @@ -446,6 +450,7 @@ FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); + void semantic2(Scope *sc); void semantic3(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -472,6 +477,7 @@ virtual int isVirtual(); virtual int addPreInvariant(); virtual int addPostInvariant(); + Expression *interpret(Expressions *arguments); void inlineScan(); int canInline(int hasthis, int hdrscan = 0); Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments); diff -uNr dmd-1.005/dmd/src/dmd/expression.c dmd-1.006/dmd/src/dmd/expression.c --- dmd-1.005/dmd/src/dmd/expression.c 2007-02-05 16:36:48.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/expression.c 2007-02-13 16:09:14.000000000 +0100 @@ -4046,7 +4046,9 @@ } Expression *FileExp::semantic(Scope *sc) -{ +{ char *name; + StringExp *se; + #if LOGSEMANTIC printf("FileExp::semantic('%s')\n", toChars()); #endif @@ -4055,25 +4057,48 @@ e1 = e1->optimize(WANTvalue); if (e1->op != TOKstring) { error("file name argument must be a string, not (%s)", e1->toChars()); - return this; + goto Lerror; } - StringExp *se = (StringExp *)e1; + se = (StringExp *)e1; se = se->toUTF8(sc); + name = (char *)se->string; - if (global.params.verbose) - printf("file %s\n", se->string); + if (!global.params.fileImppath) + { error("need -Jpath switch to import text file %s", name); + goto Lerror; + } - File f((char *)se->string); - if (f.read()) - { error("cannot read file %s", f.toChars()); - se = new StringExp(loc, ""); + if (name != FileName::name(name)) + { error("use -Jpath switch to provide path for filename %s", name); + goto Lerror; } - else - { - f.ref = 1; - se = new StringExp(loc, f.buffer, f.len); + + name = FileName::searchPath(global.filePath, name, 0); + if (!name) + { error("file %s cannot be found, check -Jpath", se->toChars()); + goto Lerror; } + + if (global.params.verbose) + printf("file %s\t(%s)\n", se->string, name); + + { File f(name); + if (f.read()) + { error("cannot read file %s", f.toChars()); + goto Lerror; + } + else + { + f.ref = 1; + se = new StringExp(loc, f.buffer, f.len); + } + } + Lret: return se->semantic(sc); + + Lerror: + se = new StringExp(loc, ""); + goto Lret; } void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -6332,14 +6357,15 @@ } -/************************* PostIncExp ***********************************/ +/************************* PostExp ***********************************/ -PostIncExp::PostIncExp(Loc loc, Expression *e) - : BinExp(loc, TOKplusplus, sizeof(PostIncExp), e, new IntegerExp(loc, 1, Type::tint32)) +PostExp::PostExp(enum TOK op, Loc loc, Expression *e) + : BinExp(loc, op, sizeof(PostExp), e, + new IntegerExp(loc, 1, Type::tint32)) { } -Expression *PostIncExp::semantic(Scope *sc) +Expression *PostExp::semantic(Scope *sc) { Expression *e = this; if (!type) @@ -6364,50 +6390,15 @@ return e; } -void PostIncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { expToCBuffer(buf, hgs, e1, precedence[op]); - buf->writestring("++"); + buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--"); } /************************************************************/ -PostDecExp::PostDecExp(Loc loc, Expression *e) - : BinExp(loc, TOKminusminus, sizeof(PostDecExp), e, new IntegerExp(loc, 1, Type::tint32)) -{ -} - -Expression *PostDecExp::semantic(Scope *sc) -{ Expression *e = this; - - if (!type) - { - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - e = op_overload(sc); - if (e) - return e; - - e = this; - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - e1->checkNoBool(); - if (e1->type->ty == Tpointer) - e = scaleFactor(sc); - else - e2 = e2->castTo(sc, e1->type); - e->type = e1->type; - } - return e; -} - -void PostDecExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - expToCBuffer(buf, hgs, e1, precedence[op]); - buf->writestring("--"); -} - -/************************************************************/ +/* Can be TOKconstruct too */ AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) diff -uNr dmd-1.005/dmd/src/dmd/expression.h dmd-1.006/dmd/src/dmd/expression.h --- dmd-1.005/dmd/src/dmd/expression.h 2007-02-04 19:32:20.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/expression.h 2007-02-14 19:19:18.000000000 +0100 @@ -39,6 +39,7 @@ struct ClassDeclaration; struct HdrGenState; struct BinExp; +struct InterState; enum TOK; @@ -115,8 +116,10 @@ virtual Expression *optimize(int result); #define WANTflags 1 #define WANTvalue 2 + #define WANTinterpret 4 + + virtual Expression *interpret(InterState *istate); - virtual Expression *constFold(); virtual int isConst(); virtual int isBool(int result); virtual int isBit(); @@ -144,6 +147,7 @@ IntegerExp(integer_t value); int equals(Object *o); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); char *toChars(); void dump(int indent); integer_t toInteger(); @@ -167,6 +171,7 @@ RealExp(Loc loc, real_t value, Type *type); int equals(Object *o); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); char *toChars(); integer_t toInteger(); uinteger_t toUInteger(); @@ -189,6 +194,7 @@ ComplexExp(Loc loc, complex_t value, Type *type); int equals(Object *o); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); char *toChars(); integer_t toInteger(); uinteger_t toUInteger(); @@ -279,6 +285,7 @@ void toMangleBuffer(OutBuffer *buf); int implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *interpret(InterState *istate); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); }; @@ -298,6 +305,7 @@ int equals(Object *o); char *toChars(); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); StringExp *toUTF8(Scope *sc); int implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); @@ -324,6 +332,7 @@ void checkEscape(); int checkSideEffect(int flag); Expression *optimize(int result); + Expression *interpret(InterState *istate); Expression *castTo(Scope *sc, Type *t); int inlineCost(InlineCostState *ics); @@ -346,6 +355,7 @@ void toMangleBuffer(OutBuffer *buf); void scanForNestedRef(Scope *sc); Expression *optimize(int result); + Expression *interpret(InterState *istate); int implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); @@ -469,6 +479,7 @@ VarExp(Loc loc, Declaration *var); int equals(Object *o); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); void dump(int indent); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -512,6 +523,7 @@ DeclarationExp(Loc loc, Dsymbol *declaration); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); @@ -572,6 +584,7 @@ Expression *optimize(int result); void dump(int indent); void scanForNestedRef(Scope *sc); + Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *)); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -600,6 +613,9 @@ void incompatibleTypes(); void dump(int indent); void scanForNestedRef(Scope *sc); + Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *)); + Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *)); + Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *)); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -639,6 +655,7 @@ AssertExp(Loc loc, Expression *e, Expression *msg = NULL); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -727,6 +744,8 @@ Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *optimize(int result); + Expression *interpret(InterState *istate); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); @@ -764,7 +783,8 @@ { NegExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -785,7 +805,8 @@ { ComExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -797,7 +818,8 @@ { NotExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); int isBit(); elem *toElem(IRState *irs); }; @@ -806,7 +828,8 @@ { BoolExp(Loc loc, Expression *e, Type *type); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); int isBit(); elem *toElem(IRState *irs); }; @@ -830,10 +853,10 @@ Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *optimize(int result); + Expression *interpret(InterState *istate); int checkSideEffect(int flag); void checkEscape(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Expression *constFold(); elem *toElem(IRState *irs); // For operator overloading @@ -855,6 +878,7 @@ Expression *modifiableLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result); + Expression *interpret(InterState *istate); void dump(int indent); elem *toElem(IRState *irs); void scanForNestedRef(Scope *sc); @@ -869,6 +893,7 @@ ArrayLengthExp(Loc loc, Expression *e1); Expression *semantic(Scope *sc); Expression *optimize(int result); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); }; @@ -912,6 +937,7 @@ int isBool(int result); int checkSideEffect(int flag); Expression *optimize(int result); + Expression *interpret(InterState *istate); elem *toElem(IRState *irs); }; @@ -926,25 +952,20 @@ Expression *modifiableLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result); + Expression *interpret(InterState *istate); Expression *doInline(InlineDoState *ids); void scanForNestedRef(Scope *sc); elem *toElem(IRState *irs); }; -struct PostIncExp : BinExp +/* For both i++ and i-- + */ +struct PostExp : BinExp { - PostIncExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Identifier *opId(); // For operator overloading - elem *toElem(IRState *irs); -}; - -struct PostDecExp : BinExp -{ - PostDecExp(Loc loc, Expression *e); + PostExp(enum TOK op, Loc loc, Expression *e); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Identifier *opId(); // For operator overloading elem *toElem(IRState *irs); @@ -955,147 +976,44 @@ AssignExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *checkToBoolean(); + Expression *interpret(InterState *istate); Identifier *opId(); // For operator overloading elem *toElem(IRState *irs); }; -struct AddAssignExp : BinExp -{ - AddAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - Identifier *opId(); // For operator overloading - - elem *toElem(IRState *irs); -}; - -struct MinAssignExp : BinExp -{ - MinAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); +#define ASSIGNEXP(op) \ +struct op##AssignExp : BinExp \ +{ \ + op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ + Expression *semantic(Scope *sc); \ + Expression *interpret(InterState *istate); \ + \ + Identifier *opId(); /* For operator overloading */ \ + \ + elem *toElem(IRState *irs); \ +}; + +ASSIGNEXP(Add) +ASSIGNEXP(Min) +ASSIGNEXP(Cat) +ASSIGNEXP(Mul) +ASSIGNEXP(Div) +ASSIGNEXP(Mod) +ASSIGNEXP(Shl) +ASSIGNEXP(Shr) +ASSIGNEXP(Ushr) +ASSIGNEXP(And) +ASSIGNEXP(Or) +ASSIGNEXP(Xor) - elem *toElem(IRState *irs); -}; - -struct CatAssignExp : BinExp -{ - CatAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct MulAssignExp : BinExp -{ - MulAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct DivAssignExp : BinExp -{ - DivAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct ModAssignExp : BinExp -{ - ModAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct ShlAssignExp : BinExp -{ - ShlAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct ShrAssignExp : BinExp -{ - ShrAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct UshrAssignExp : BinExp -{ - UshrAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct AndAssignExp : BinExp -{ - AndAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct OrAssignExp : BinExp -{ - OrAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct XorAssignExp : BinExp -{ - XorAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; +#undef ASSIGNEXP struct AddExp : BinExp { AddExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading int isCommutative(); @@ -1109,8 +1027,8 @@ { MinExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1124,6 +1042,7 @@ CatExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1136,7 +1055,8 @@ { MulExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading int isCommutative(); @@ -1150,7 +1070,8 @@ { DivExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1163,7 +1084,8 @@ { ModExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1176,8 +1098,8 @@ { ShlExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1190,7 +1112,8 @@ { ShrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1203,7 +1126,8 @@ { UshrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading Identifier *opId(); @@ -1216,7 +1140,8 @@ { AndExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading int isCommutative(); @@ -1230,7 +1155,8 @@ { OrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading int isCommutative(); @@ -1244,7 +1170,8 @@ { XorExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); // For operator overloading int isCommutative(); @@ -1260,8 +1187,8 @@ Expression *semantic(Scope *sc); Expression *checkToBoolean(); int isBit(); - Expression *constFold(); Expression *optimize(int result); + Expression *interpret(InterState *istate); int checkSideEffect(int flag); elem *toElem(IRState *irs); }; @@ -1272,8 +1199,8 @@ Expression *semantic(Scope *sc); Expression *checkToBoolean(); int isBit(); - Expression *constFold(); Expression *optimize(int result); + Expression *interpret(InterState *istate); int checkSideEffect(int flag); elem *toElem(IRState *irs); }; @@ -1282,7 +1209,8 @@ { CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); int isBit(); // For operator overloading @@ -1317,8 +1245,8 @@ { EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *constFold(); Expression *optimize(int result); + Expression *interpret(InterState *istate); int isBit(); // For operator overloading @@ -1335,7 +1263,8 @@ IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); int isBit(); - Expression *constFold(); + Expression *optimize(int result); + Expression *interpret(InterState *istate); elem *toElem(IRState *irs); }; @@ -1349,7 +1278,7 @@ Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *constFold(); + Expression *interpret(InterState *istate); void checkEscape(); Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); @@ -1367,4 +1296,41 @@ elem *toElem(IRState *irs); }; + +/****************************************************************/ + +/* Special values used by the interpreter + */ +#define EXP_CANT_INTERPRET ((Expression *)1) +#define EXP_CONTINUE_INTERPRET ((Expression *)2) +#define EXP_BREAK_INTERPRET ((Expression *)3) +#define EXP_GOTO_INTERPRET ((Expression *)4) + +Expression *Neg(Type *type, Expression *e1); +Expression *Com(Type *type, Expression *e1); +Expression *Not(Type *type, Expression *e1); +Expression *Bool(Type *type, Expression *e1); +Expression *Cast(Type *type, Type *to, Expression *e1); +Expression *ArrayLength(Type *type, Expression *e1); + +Expression *Add(Type *type, Expression *e1, Expression *e2); +Expression *Min(Type *type, Expression *e1, Expression *e2); +Expression *Mul(Type *type, Expression *e1, Expression *e2); +Expression *Div(Type *type, Expression *e1, Expression *e2); +Expression *Mod(Type *type, Expression *e1, Expression *e2); +Expression *Shl(Type *type, Expression *e1, Expression *e2); +Expression *Shr(Type *type, Expression *e1, Expression *e2); +Expression *Ushr(Type *type, Expression *e1, Expression *e2); +Expression *And(Type *type, Expression *e1, Expression *e2); +Expression *Or(Type *type, Expression *e1, Expression *e2); +Expression *Xor(Type *type, Expression *e1, Expression *e2); +Expression *Index(Type *type, Expression *e1, Expression *e2); +Expression *Cat(Type *type, Expression *e1, Expression *e2); + +Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2); +Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2); +Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2); + +Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr); + #endif /* DMD_EXPRESSION_H */ diff -uNr dmd-1.005/dmd/src/dmd/func.c dmd-1.006/dmd/src/dmd/func.c --- dmd-1.005/dmd/src/dmd/func.c 2007-02-02 20:18:06.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/func.c 2007-02-14 20:47:00.000000000 +0100 @@ -61,12 +61,14 @@ inlineStatus = ILSuninitialized; inlineNest = 0; inlineAsm = 0; + cantInterpret = 0; semanticRun = 0; nestedFrameRef = 0; fes = NULL; introducing = 0; tintro = NULL; inferRetType = (type && type->next == NULL); + scope = NULL; hasReturnExp = 0; nrvo_can = 1; nrvo_var = NULL; @@ -525,6 +527,15 @@ error("identity assignment operator overload is illegal"); } +void FuncDeclaration::semantic2(Scope *sc) +{ + /* Save scope for possible later use (if we need the + * function internals) + */ + scope = new Scope(*sc); + scope->setNoFree(); +} + // Do the semantic analysis on the internals of the function. void FuncDeclaration::semantic3(Scope *sc) @@ -691,7 +702,7 @@ if (nparams) { // parameters[] has all the tuples removed, as the back end // doesn't know about tuples - parameters = new Array(); + parameters = new Dsymbols(); parameters->reserve(nparams); for (size_t i = 0; i < nparams; i++) { @@ -1013,7 +1024,7 @@ // Merge in initialization of 'out' parameters if (parameters) - { for (int i = 0; i < parameters->dim; i++) + { for (size_t i = 0; i < parameters->dim; i++) { VarDeclaration *v; v = (VarDeclaration *)parameters->data[i]; @@ -1146,6 +1157,7 @@ sc2->callSuper = 0; sc2->pop(); } + semanticRun = 2; } void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff -uNr dmd-1.005/dmd/src/dmd/init.c dmd-1.006/dmd/src/dmd/init.c --- dmd-1.005/dmd/src/dmd/init.c 2006-12-30 11:42:56.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/init.c 2007-02-13 23:27:24.000000000 +0100 @@ -332,7 +332,7 @@ idx = (Expression *)index.data[i]; if (idx) { idx = idx->semantic(sc); - idx = idx->optimize(WANTvalue); + idx = idx->optimize(WANTvalue | WANTinterpret); index.data[i] = (void *)idx; length = idx->toInteger(); } @@ -475,7 +475,7 @@ exp = exp->implicitCastTo(sc, t); L1: - exp = exp->optimize(WANTvalue); + exp = exp->optimize(WANTvalue | WANTinterpret); //printf("-ExpInitializer::semantic(): "); exp->print(); return this; } diff -uNr dmd-1.005/dmd/src/dmd/interpret.c dmd-1.006/dmd/src/dmd/interpret.c --- dmd-1.005/dmd/src/dmd/interpret.c 1970-01-01 01:00:00.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/interpret.c 2007-02-14 22:16:02.000000000 +0100 @@ -0,0 +1,1345 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2007 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 + +#include "mem.h" + +#include "statement.h" +#include "expression.h" +#include "cond.h" +#include "init.h" +#include "staticassert.h" +#include "mtype.h" +#include "scope.h" +#include "declaration.h" +#include "aggregate.h" +#include "id.h" + +#define LOG 0 + +struct InterState +{ + Dsymbols vars; // variables used in this function + Statement *start; // if !=NULL, start execution at this statement + Statement *gotoTarget; // target of EXP_GOTO_INTERPRET result + + InterState(); +}; + +InterState::InterState() +{ + memset(this, 0, sizeof(InterState)); +} + +/************************************* + * Attempt to interpret a function given the arguments. + * Return result expression if successful, NULL if not. + */ + +Expression *FuncDeclaration::interpret(Expressions *arguments) +{ +#if LOG + printf("FuncDeclaration::interpret() %s\n", toChars()); + printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); +#endif + if (cantInterpret || semanticRun == 1) + return NULL; + + if (needThis() || isNested() || !fbody) + { cantInterpret = 1; + return NULL; + } + + if (semanticRun == 0 && scope) + { + semantic3(scope); + } + if (semanticRun < 2) + return NULL; + + Type *tb = type->toBasetype(); + assert(tb->ty == Tfunction); + TypeFunction *tf = (TypeFunction *)tb; + Type *tret = tf->next->toBasetype(); + if (tf->varargs || tret->ty == Tvoid) + { cantInterpret = 1; + return NULL; + } + + if (tf->parameters) + { size_t dim = Argument::dim(tf->parameters); + for (size_t i = 0; i < dim; i++) + { Argument *arg = Argument::getNth(tf->parameters, i); + if (arg->inout == Out || arg->inout == InOut || arg->inout == Lazy) + { cantInterpret = 1; + return NULL; + } + } + } + + InterState istate; + Expressions vsave; + size_t dim = 0; + if (arguments) + { + dim = arguments->dim; + assert(parameters && parameters->dim == dim); + for (size_t i = 0; i < dim; i++) + { Expression *earg = (Expression *)arguments->data[i]; +#if LOG + printf("arg[%d] = %s\n", i, earg->toChars()); +#endif + earg = earg->interpret(&istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; +#if LOG + printf("interpreted arg[%d] = %s\n", i, earg->toChars()); +#endif + } + + vsave.setDim(dim); + + for (size_t i = 0; i < dim; i++) + { Expression *earg = (Expression *)arguments->data[i]; + earg = earg->interpret(&istate); + VarDeclaration *v = (VarDeclaration *)parameters->data[i]; + vsave.data[i] = v->value; + v->value = earg; + } + } + + Expression *e = NULL; + + while (1) + { + e = fbody->interpret(&istate); + if (e == EXP_CANT_INTERPRET) + { +#if LOG + printf("function body failed to interpret\n"); +#endif + e = NULL; + } + + /* This is how we deal with a recursive statement AST + * that has arbitrary goto statements in it. + * Bubble up a 'result' which is the target of the goto + * statement, then go recursively down the AST looking + * for that statement, then execute starting there. + */ + if (e == EXP_GOTO_INTERPRET) + { + istate.start = istate.gotoTarget; // set starting statement + istate.gotoTarget = NULL; + } + else + break; + } + + for (size_t i = 0; i < dim; i++) + { + VarDeclaration *v = (VarDeclaration *)parameters->data[i]; + v->value = (Expression *)vsave.data[i]; + } + return e; +} + +/******************************** Statement ***************************/ + +#define START() \ + if (istate->start) \ + { if (istate->start != this) \ + return NULL; \ + istate->start = NULL; \ + } + +/*********************************** + * Interpret the statement. + * Returns: + * NULL continue to next statement + * EXP_CANT_INTERPRET cannot interpret statement at compile time + * !NULL expression from return statement + */ + +Expression *Statement::interpret(InterState *istate) +{ +#if LOG + printf("Statement::interpret()\n"); +#endif + START() + return EXP_CANT_INTERPRET; +} + +Expression *ExpStatement::interpret(InterState *istate) +{ +#if LOG + printf("ExpStatement::interpret()\n"); +#endif + START() + if (exp) + { + Expression *e = exp->interpret(istate); + if (e == EXP_CANT_INTERPRET) + { + //printf("cannot interpret %s\n", exp->toChars()); + return EXP_CANT_INTERPRET; + } + } + return NULL; +} + +Expression *CompoundStatement::interpret(InterState *istate) +{ Expression *e = NULL; + +#if LOG + printf("CompoundStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + if (statements) + { + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (Statement *)statements->data[i]; + + e = s->interpret(istate); + if (e) + break; + } + } + return e; +} + +Expression *UnrolledLoopStatement::interpret(InterState *istate) +{ Expression *e = NULL; + +#if LOG + printf("UnrolledLoopStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + if (statements) + { + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (Statement *)statements->data[i]; + + e = s->interpret(istate); + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_CONTINUE_INTERPRET) + { e = NULL; + continue; + } + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + if (e) + break; + } + } + return e; +} + +Expression *IfStatement::interpret(InterState *istate) +{ +#if LOG + printf("IfStatement::interpret(%s)\n", condition->toChars()); +#endif + + if (istate->start == this) + istate->start = NULL; + if (istate->start) + { + Expression *e = NULL; + if (ifbody) + e = ifbody->interpret(istate); + if (istate->start && elsebody) + e = elsebody->interpret(istate); + return e; + } + + Expression *e = condition->interpret(istate); + assert(e); + //if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n"); + if (e != EXP_CANT_INTERPRET) + { + if (!e->isConst()) + { + e = EXP_CANT_INTERPRET; + } + else + { + if (e->isBool(TRUE)) + e = ifbody ? ifbody->interpret(istate) : NULL; + else if (e->isBool(FALSE)) + e = elsebody ? elsebody->interpret(istate) : NULL; + else + { + e = EXP_CANT_INTERPRET; + } + } + } + return e; +} + +Expression *ScopeStatement::interpret(InterState *istate) +{ +#if LOG + printf("ScopeStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + return statement ? statement->interpret(istate) : NULL; +} + +Expression *ReturnStatement::interpret(InterState *istate) +{ +#if LOG + printf("ReturnStatement::interpret()\n"); +#endif + START() + assert(exp); + return exp->interpret(istate); +} + +Expression *BreakStatement::interpret(InterState *istate) +{ +#if LOG + printf("BreakStatement::interpret()\n"); +#endif + START() + if (ident) + return EXP_CANT_INTERPRET; + else + return EXP_BREAK_INTERPRET; +} + +Expression *ContinueStatement::interpret(InterState *istate) +{ +#if LOG + printf("ContinueStatement::interpret()\n"); +#endif + START() + if (ident) + return EXP_CANT_INTERPRET; + else + return EXP_CONTINUE_INTERPRET; +} + +Expression *WhileStatement::interpret(InterState *istate) +{ +#if LOG + printf("WhileStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + Expression *e; + + if (istate->start) + { + e = body ? body->interpret(istate) : NULL; + if (istate->start) + return NULL; + if (e == EXP_CANT_INTERPRET) + return e; + if (e == EXP_BREAK_INTERPRET) + return NULL; + if (e != EXP_CONTINUE_INTERPRET) + return e; + } + + while (1) + { + e = condition->interpret(istate); + if (e == EXP_CANT_INTERPRET) + break; + if (!e->isConst()) + { e = EXP_CANT_INTERPRET; + break; + } + if (e->isBool(TRUE)) + { e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_CONTINUE_INTERPRET) + continue; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + if (e) + break; + } + else if (e->isBool(FALSE)) + { e = NULL; + break; + } + else + assert(0); + } + return e; +} + +Expression *DoStatement::interpret(InterState *istate) +{ +#if LOG + printf("DoStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + Expression *e; + + if (istate->start) + { + e = body ? body->interpret(istate) : NULL; + if (istate->start) + return NULL; + if (e == EXP_CANT_INTERPRET) + return e; + if (e == EXP_BREAK_INTERPRET) + return NULL; + if (e == EXP_CONTINUE_INTERPRET) + goto Lcontinue; + if (e) + return e; + } + + while (1) + { + e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + if (e && e != EXP_CONTINUE_INTERPRET) + break; + + Lcontinue: + e = condition->interpret(istate); + if (e == EXP_CANT_INTERPRET) + break; + if (!e->isConst()) + { e = EXP_CANT_INTERPRET; + break; + } + if (e->isBool(TRUE)) + { + } + else if (e->isBool(FALSE)) + { e = NULL; + break; + } + else + assert(0); + } + return e; +} + +Expression *ForStatement::interpret(InterState *istate) +{ +#if LOG + printf("ForStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + Expression *e; + + if (init) + { + e = init->interpret(istate); + if (e == EXP_CANT_INTERPRET) + return e; + assert(!e); + } + + if (istate->start) + { + e = body ? body->interpret(istate) : NULL; + if (istate->start) + return NULL; + if (e == EXP_CANT_INTERPRET) + return e; + if (e == EXP_BREAK_INTERPRET) + return NULL; + if (e == EXP_CONTINUE_INTERPRET) + goto Lcontinue; + if (e) + return e; + } + + while (1) + { + e = condition->interpret(istate); + if (e == EXP_CANT_INTERPRET) + break; + if (!e->isConst()) + { e = EXP_CANT_INTERPRET; + break; + } + if (e->isBool(TRUE)) + { e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + if (e && e != EXP_CONTINUE_INTERPRET) + break; + Lcontinue: + e = increment->interpret(istate); + if (e == EXP_CANT_INTERPRET) + break; + } + else if (e->isBool(FALSE)) + { e = NULL; + break; + } + else + assert(0); + } + return e; +} + +Expression *ForeachStatement::interpret(InterState *istate) +{ +#if LOG + printf("ForeachStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + if (istate->start) + return NULL; + + Expression *e = NULL; + Expression *eaggr; + + if (value->isOut()) + return EXP_CANT_INTERPRET; + + eaggr = aggr->interpret(istate); + if (eaggr == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + Expression *dim = ArrayLength(Type::tsize_t, eaggr); + if (dim == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + uinteger_t d = dim->toUInteger(); + uinteger_t index; + + if (op == TOKforeach) + { + for (index = 0; index < d; index++) + { + Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); + if (key) + key->value = ekey; + value->value = Index(value->type, eaggr, ekey); + if (value->value == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + if (e == EXP_CONTINUE_INTERPRET) + e = NULL; + else if (e) + break; + } + } + else // TOKforeach_reverse + { + for (index = d; index-- != 0;) + { + Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); + if (key) + key->value = ekey; + value->value = Index(value->type, eaggr, ekey); + if (value->value == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + if (e == EXP_CONTINUE_INTERPRET) + e = NULL; + else if (e) + break; + } + } + return e; +} + +Expression *SwitchStatement::interpret(InterState *istate) +{ +#if LOG + printf("SwitchStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + Expression *e = NULL; + + if (istate->start) + { + e = body ? body->interpret(istate) : NULL; + if (istate->start) + return NULL; + if (e == EXP_CANT_INTERPRET) + return e; + if (e == EXP_BREAK_INTERPRET) + return NULL; + return e; + } + + + Expression *econdition = condition->interpret(istate); + if (econdition == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + Statement *s = NULL; + if (cases) + { + for (size_t i = 0; i < cases->dim; i++) + { + CaseStatement *cs = (CaseStatement *)cases->data[i]; + e = Equal(TOKequal, Type::tint32, econdition, cs->exp); + if (e == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + if (e->isBool(TRUE)) + { s = cs; + break; + } + } + } + if (!s) + { if (hasNoDefault) + error("no default or case for %s in switch statement", econdition->toChars()); + s = sdefault; + } + + assert(s); + istate->start = s; + e = body ? body->interpret(istate) : NULL; + assert(!istate->start); + if (e == EXP_BREAK_INTERPRET) + return NULL; + return e; +} + +Expression *CaseStatement::interpret(InterState *istate) +{ +#if LOG + printf("CaseStatement::interpret(%s) this = %p\n", exp->toChars(), this); +#endif + if (istate->start == this) + istate->start = NULL; + if (statement) + return statement->interpret(istate); + else + return NULL; +} + +Expression *DefaultStatement::interpret(InterState *istate) +{ +#if LOG + printf("DefaultStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + if (statement) + return statement->interpret(istate); + else + return NULL; +} + +Expression *GotoStatement::interpret(InterState *istate) +{ +#if LOG + printf("GotoStatement::interpret()\n"); +#endif + START() + assert(label && label->statement); + istate->gotoTarget = label->statement; + return EXP_GOTO_INTERPRET; +} + +Expression *GotoCaseStatement::interpret(InterState *istate) +{ +#if LOG + printf("GotoCaseStatement::interpret()\n"); +#endif + START() + assert(cs); + istate->gotoTarget = cs; + return EXP_GOTO_INTERPRET; +} + +Expression *GotoDefaultStatement::interpret(InterState *istate) +{ +#if LOG + printf("GotoDefaultStatement::interpret()\n"); +#endif + START() + assert(sw && sw->sdefault); + istate->gotoTarget = sw->sdefault; + return EXP_GOTO_INTERPRET; +} + +Expression *LabelStatement::interpret(InterState *istate) +{ +#if LOG + printf("LabelStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + return statement ? statement->interpret(istate) : NULL; +} + +/******************************** Expression ***************************/ + +Expression *Expression::interpret(InterState *istate) +{ +#if LOG + printf("Expression::interpret() %s\n", toChars()); +#endif + return EXP_CANT_INTERPRET; +} + +Expression *NullExp::interpret(InterState *istate) +{ + return this; +} + +Expression *IntegerExp::interpret(InterState *istate) +{ +#if LOG + printf("IntegerExp::interpret() %s\n", toChars()); +#endif + return this; +} + +Expression *RealExp::interpret(InterState *istate) +{ + return this; +} + +Expression *ComplexExp::interpret(InterState *istate) +{ + return this; +} + +Expression *StringExp::interpret(InterState *istate) +{ +#if LOG + printf("StringExp::interpret() %s\n", toChars()); +#endif + return this; +} + +Expression *VarExp::interpret(InterState *istate) +{ Expression *e = EXP_CANT_INTERPRET; + VarDeclaration *v = var->isVarDeclaration(); + if (v) + { + if (v->isConst() && v->init) + e = v->init->toExpression(); + else + e = v->value; + if (!e) + e = EXP_CANT_INTERPRET; + } + return e; +} + +Expression *DeclarationExp::interpret(InterState *istate) +{ Expression *e = EXP_CANT_INTERPRET; + VarDeclaration *v = declaration->isVarDeclaration(); + if (v) + { + Dsymbol *s = v->toAlias(); + if (s == v && !v->isStatic() && v->init) + { + ExpInitializer *ie = v->init->isExpInitializer(); + if (ie) + e = ie->exp->interpret(istate); + } + } + return e; +} + +Expression *TupleExp::interpret(InterState *istate) +{ Expressions *expsx = NULL; + + for (size_t i = 0; i < exps->dim; i++) + { Expression *e = (Expression *)exps->data[i]; + Expression *ex; + + ex = e->interpret(istate); + if (ex == EXP_CANT_INTERPRET) + { delete expsx; + return ex; + } + + /* If any changes, do Copy On Write + */ + if (ex != e) + { + if (!expsx) + { expsx = new Expressions(); + expsx->setDim(exps->dim); + for (size_t j = 0; j < i; j++) + { + expsx->data[j] = exps->data[j]; + } + } + expsx->data[i] = (void *)ex; + } + } + if (expsx) + { TupleExp *te = new TupleExp(loc, expsx); + expandTuples(te->exps); + te->type = new TypeTuple(te->exps); + return te; + } + return this; +} + +Expression *ArrayLiteralExp::interpret(InterState *istate) +{ Expressions *expsx = NULL; + + if (elements) + { + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + Expression *ex; + + ex = e->interpret(istate); + if (ex == EXP_CANT_INTERPRET) + { delete expsx; + return EXP_CANT_INTERPRET; + } + + /* If any changes, do Copy On Write + */ + if (ex != e) + { + if (!expsx) + { expsx = new Expressions(); + expsx->setDim(elements->dim); + for (size_t j = 0; j < i; j++) + { + expsx->data[j] = elements->data[j]; + } + } + expsx->data[i] = (void *)ex; + } + } + } + if (elements && expsx) + { + expandTuples(expsx); + if (expsx->dim != elements->dim) + { delete expsx; + return EXP_CANT_INTERPRET; + } + ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx); + ae->type = type; + return ae; + } + return this; +} + +Expression *UnaExp::interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *)) +{ Expression *e; + Expression *e1; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + if (e1->isConst() != 1) + goto Lcant; + + e = (*fp)(type, e1); + return e; + +Lcant: + return EXP_CANT_INTERPRET; +} + +#define UNA_INTERPRET(op) \ +Expression *op##Exp::interpret(InterState *istate) \ +{ \ + return interpretCommon(istate, &op); \ +} + +UNA_INTERPRET(Neg) +UNA_INTERPRET(Com) +UNA_INTERPRET(Not) +UNA_INTERPRET(Bool) + + +typedef Expression *(*fp_t)(Type *, Expression *, Expression *); + +Expression *BinExp::interpretCommon(InterState *istate, fp_t fp) +{ Expression *e; + Expression *e1; + Expression *e2; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + if (e1->isConst() != 1) + goto Lcant; + + e2 = this->e2->interpret(istate); + if (e2 == EXP_CANT_INTERPRET) + goto Lcant; + if (e2->isConst() != 1) + goto Lcant; + + e = (*fp)(type, e1, e2); + return e; + +Lcant: + return EXP_CANT_INTERPRET; +} + +#define BIN_INTERPRET(op) \ +Expression *op##Exp::interpret(InterState *istate) \ +{ \ + return interpretCommon(istate, &op); \ +} + +BIN_INTERPRET(Add) +BIN_INTERPRET(Min) +BIN_INTERPRET(Mul) +BIN_INTERPRET(Div) +BIN_INTERPRET(Mod) +BIN_INTERPRET(Shl) +BIN_INTERPRET(Shr) +BIN_INTERPRET(Ushr) +BIN_INTERPRET(And) +BIN_INTERPRET(Or) +BIN_INTERPRET(Xor) + + +typedef Expression *(*fp2_t)(enum TOK, Type *, Expression *, Expression *); + +Expression *BinExp::interpretCommon2(InterState *istate, fp2_t fp) +{ Expression *e; + Expression *e1; + Expression *e2; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + if (e1->isConst() != 1) + goto Lcant; + + e2 = this->e2->interpret(istate); + if (e2 == EXP_CANT_INTERPRET) + goto Lcant; + if (e2->isConst() != 1) + goto Lcant; + + e = (*fp)(op, type, e1, e2); + return e; + +Lcant: + return EXP_CANT_INTERPRET; +} + +#define BIN_INTERPRET2(op) \ +Expression *op##Exp::interpret(InterState *istate) \ +{ \ + return interpretCommon2(istate, &op); \ +} + +BIN_INTERPRET2(Equal) +BIN_INTERPRET2(Identity) +BIN_INTERPRET2(Cmp) + +Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp) +{ + Expression *e = EXP_CANT_INTERPRET; + + if (e1->op == TOKvar) + { + VarExp *ve = (VarExp *)e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (v && !v->isDataseg() && (!fp || v->value)) + { + Expression *e2 = this->e2->interpret(istate); + if (e2 != EXP_CANT_INTERPRET) + { + if (fp) + e2 = (*fp)(v->type, v->value, e2); + else + e2 = Cast(v->type, v->type, e2); + if (e2 != EXP_CANT_INTERPRET) + { + if (v->isAuto()) + { + for (size_t i = 0; 1; i++) + { + if (i == istate->vars.dim) + { istate->vars.push(v); + break; + } + if (v == (VarDeclaration *)istate->vars.data[i]) + break; + } + } + v->value = e2; + e = Cast(type, type, e2); + } + } + } + } + return e; +} + +Expression *AssignExp::interpret(InterState *istate) +{ + return interpretAssignCommon(istate, NULL); +} + +#define BIN_ASSIGN_INTERPRET(op) \ +Expression *op##AssignExp::interpret(InterState *istate) \ +{ \ + return interpretAssignCommon(istate, &op); \ +} + +BIN_ASSIGN_INTERPRET(Add) +BIN_ASSIGN_INTERPRET(Min) +BIN_ASSIGN_INTERPRET(Cat) +BIN_ASSIGN_INTERPRET(Mul) +BIN_ASSIGN_INTERPRET(Div) +BIN_ASSIGN_INTERPRET(Mod) +BIN_ASSIGN_INTERPRET(Shl) +BIN_ASSIGN_INTERPRET(Shr) +BIN_ASSIGN_INTERPRET(Ushr) +BIN_ASSIGN_INTERPRET(And) +BIN_ASSIGN_INTERPRET(Or) +BIN_ASSIGN_INTERPRET(Xor) + +Expression *PostExp::interpret(InterState *istate) +{ + Expression *e = EXP_CANT_INTERPRET; + + if (e1->op == TOKvar) + { + VarExp *ve = (VarExp *)e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (v && !v->isDataseg() && v->value) + { + Expression *e2 = this->e2->interpret(istate); + if (e2 != EXP_CANT_INTERPRET) + { + e = ((op == TOKplusplus) ? &Add : &Min)(v->type, v->value, e2); + if (e != EXP_CANT_INTERPRET) + { + if (v->isAuto()) + { + for (size_t i = 0; 1; i++) + { + if (i == istate->vars.dim) + { istate->vars.push(v); + break; + } + if (v == (VarDeclaration *)istate->vars.data[i]) + break; + } + } + v->value = e; + e = Cast(type, type, e2); + } + } + } + } + return e; +} + +Expression *AndAndExp::interpret(InterState *istate) +{ + Expression *e = e1->interpret(istate); + if (e != EXP_CANT_INTERPRET) + { + if (e->isBool(FALSE)) + e = new IntegerExp(e1->loc, 0, type); + else if (e->isBool(TRUE)) + { + e = e2->interpret(istate); + if (e != EXP_CANT_INTERPRET) + { + if (e->isBool(FALSE)) + e = new IntegerExp(e1->loc, 0, type); + else if (e->isBool(TRUE)) + e = new IntegerExp(e1->loc, 1, type); + else + e = EXP_CANT_INTERPRET; + } + } + else + e = EXP_CANT_INTERPRET; + } + return e; +} + +Expression *OrOrExp::interpret(InterState *istate) +{ + Expression *e = e1->interpret(istate); + if (e != EXP_CANT_INTERPRET) + { + if (e->isBool(TRUE)) + e = new IntegerExp(e1->loc, 1, type); + else if (e->isBool(FALSE)) + { + e = e2->interpret(istate); + if (e != EXP_CANT_INTERPRET) + { + if (e->isBool(FALSE)) + e = new IntegerExp(e1->loc, 0, type); + else if (e->isBool(TRUE)) + e = new IntegerExp(e1->loc, 1, type); + else + e = EXP_CANT_INTERPRET; + } + } + else + e = EXP_CANT_INTERPRET; + } + return e; +} + + +Expression *CallExp::interpret(InterState *istate) +{ Expression *e = EXP_CANT_INTERPRET; + + if (e1->op == TOKvar) + { + FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); + if (fd) + { + /* Save the values of the variables used + */ + Expressions valueSaves; + valueSaves.setDim(istate->vars.dim); + for (size_t i = 0; i < istate->vars.dim; i++) + { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; + valueSaves.data[i] = v->value; + v->value = NULL; + } + + Expression *eresult = fd->interpret(arguments); + if (eresult) + e = eresult; + else + error("cannot evaluate %s at compile time", toChars()); + + /* Restore the variable values + */ + for (size_t i = 0; i < istate->vars.dim; i++) + { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; + v->value = (Expression *)valueSaves.data[i]; + } + } + } + return e; +} + +Expression *CommaExp::interpret(InterState *istate) +{ + Expression *e = e1->interpret(istate); + if (e != EXP_CANT_INTERPRET) + e = e2->interpret(istate); + return e; +} + +Expression *CondExp::interpret(InterState *istate) +{ + Expression *e = econd->interpret(istate); + if (e != EXP_CANT_INTERPRET) + { + if (e->isBool(TRUE)) + e = e1->interpret(istate); + else if (e->isBool(FALSE)) + e = e2->interpret(istate); + else + e = EXP_CANT_INTERPRET; + } + return e; +} + +Expression *ArrayLengthExp::interpret(InterState *istate) +{ Expression *e; + Expression *e1; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + if (e1->op == TOKstring || e1->op == TOKarrayliteral) + { + e = ArrayLength(type, e1); + } + else + goto Lcant; + return e; + +Lcant: + return EXP_CANT_INTERPRET; +} + +Expression *IndexExp::interpret(InterState *istate) +{ Expression *e; + Expression *e1; + Expression *e2; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + + /* Set the $ variable + */ + e = ArrayLength(Type::tsize_t, e1); + if (e == EXP_CANT_INTERPRET) + goto Lcant; + if (lengthVar) + lengthVar->value = e; + + e2 = this->e2->interpret(istate); + if (e2 == EXP_CANT_INTERPRET) + goto Lcant; + return Index(type, e1, e2); + +Lcant: + return EXP_CANT_INTERPRET; +} + + +Expression *SliceExp::interpret(InterState *istate) +{ Expression *e; + Expression *e1; + Expression *lwr; + Expression *upr; + +#if LOG + printf("SliceExp::interpret() %s\n", toChars()); +#endif + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + if (!lwr) + { + e = e1->castTo(NULL, type); + return e->interpret(istate); + } + + /* Set the $ variable + */ + e = ArrayLength(Type::tsize_t, e1); + if (e == EXP_CANT_INTERPRET) + goto Lcant; + if (lengthVar) + lengthVar->value = e; + + /* Evaluate lower and upper bounds of slice + */ + lwr = this->lwr->interpret(istate); + if (lwr == EXP_CANT_INTERPRET) + goto Lcant; + upr = this->upr->interpret(istate); + if (upr == EXP_CANT_INTERPRET) + goto Lcant; + + return Slice(type, e1, lwr, upr); + +Lcant: + return EXP_CANT_INTERPRET; +} + + +Expression *CatExp::interpret(InterState *istate) +{ Expression *e; + Expression *e1; + Expression *e2; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + e2 = this->e2->interpret(istate); + if (e2 == EXP_CANT_INTERPRET) + goto Lcant; + return Cat(type, e1, e2); + +Lcant: + return EXP_CANT_INTERPRET; +} + + +Expression *CastExp::interpret(InterState *istate) +{ Expression *e; + Expression *e1; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + return Cast(type, to, e1); + +Lcant: + return EXP_CANT_INTERPRET; +} + + +Expression *AssertExp::interpret(InterState *istate) +{ Expression *e; + Expression *e1; + + e1 = this->e1->interpret(istate); + if (e1 == EXP_CANT_INTERPRET) + goto Lcant; + if (e1->isBool(TRUE)) + { + } + else if (e1->isBool(FALSE)) + { + if (msg) + { + e = msg->interpret(istate); + if (e == EXP_CANT_INTERPRET) + goto Lcant; + error("%s", e->toChars()); + } + else + error("%s failed", toChars()); + } + else + goto Lcant; + return e1; + +Lcant: + return EXP_CANT_INTERPRET; +} + + diff -uNr dmd-1.005/dmd/src/dmd/lexer.c dmd-1.006/dmd/src/dmd/lexer.c --- dmd-1.005/dmd/src/dmd/lexer.c 2007-02-03 21:20:44.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/lexer.c 2007-02-09 00:18:40.000000000 +0100 @@ -2644,6 +2644,7 @@ Token::tochars[TOKxor] = "^"; Token::tochars[TOKxorass] = "^="; Token::tochars[TOKassign] = "="; + Token::tochars[TOKconstruct] = "="; Token::tochars[TOKlt] = "<"; Token::tochars[TOKgt] = ">"; Token::tochars[TOKle] = "<="; diff -uNr dmd-1.005/dmd/src/dmd/lexer.h dmd-1.006/dmd/src/dmd/lexer.h --- dmd-1.005/dmd/src/dmd/lexer.h 2007-02-03 20:57:06.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/lexer.h 2007-02-09 00:18:24.000000000 +0100 @@ -91,7 +91,7 @@ TOKand, TOKor, TOKxor, TOKandass, TOKorass, TOKxorass, TOKassign, TOKnot, TOKtilde, - TOKplusplus, TOKminusminus, + TOKplusplus, TOKminusminus, TOKconstruct, TOKdot, TOKarrow, TOKcomma, TOKquestion, TOKandand, TOKoror, diff -uNr dmd-1.005/dmd/src/dmd/mars.c dmd-1.006/dmd/src/dmd/mars.c --- dmd-1.005/dmd/src/dmd/mars.c 2007-02-03 21:03:16.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/mars.c 2007-02-14 22:17:28.000000000 +0100 @@ -60,7 +60,7 @@ copyright = "Copyright (c) 1999-2007 by Digital Mars"; written = "written by Walter Bright"; - version = "v1.005"; + version = "v1.006"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -171,6 +171,7 @@ -Hffilename write 'header' file to filename\n\ --help print help\n\ -Ipath where to look for imports\n\ + -Jpath where to look for string imports\n\ -inline do function inlining\n\ -Llinkerflag pass linkerflag to link\n\ -nofloat do not emit reference to floating point\n\ @@ -414,6 +415,12 @@ global.params.imppath = new Array(); global.params.imppath->push(p + 2); } + else if (p[1] == 'J') + { + if (!global.params.fileImppath) + global.params.fileImppath = new Array(); + global.params.fileImppath->push(p + 2); + } else if (memcmp(p + 1, "debug", 5) == 0) { // Parse: @@ -582,6 +589,23 @@ } } + // Build string import search path + if (global.params.fileImppath) + { + for (i = 0; i < global.params.fileImppath->dim; i++) + { + char *path = (char *)global.params.fileImppath->data[i]; + Array *a = FileName::splitPath(path); + + if (a) + { + if (!global.filePath) + global.filePath = new Array(); + global.filePath->append(a); + } + } + } + // Create Modules Array modules; modules.reserve(files.dim); diff -uNr dmd-1.005/dmd/src/dmd/mars.h dmd-1.006/dmd/src/dmd/mars.h --- dmd-1.005/dmd/src/dmd/mars.h 2007-01-09 13:34:04.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/mars.h 2007-02-08 16:11:02.000000000 +0100 @@ -60,6 +60,7 @@ char *argv0; // program name Array *imppath; // array of char*'s of where to look for import modules + Array *fileImppath; // array of char*'s of where to look for file import modules char *objdir; // .obj file output directory char *objname; // .obj file output name @@ -114,6 +115,7 @@ char *copyright; char *written; Array *path; // Array of char*'s which form the import lookup path + Array *filePath; // Array of char*'s which form the file import lookup path int structalign; char *version; diff -uNr dmd-1.005/dmd/src/dmd/module.c dmd-1.006/dmd/src/dmd/module.c --- dmd-1.005/dmd/src/dmd/module.c 2007-02-04 19:38:56.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/module.c 2007-02-14 22:08:26.000000000 +0100 @@ -233,19 +233,6 @@ //printf("Module::load(ident = '%s')\n", ident->toChars()); - if (global.params.verbose) - { - printf("import "); - if (packages) - { - for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = (Identifier *)packages->data[i]; - printf("%s.", pid->toChars()); - } - } - printf("%s\n", ident->toChars()); - } - // Build module filename by turning: // foo.bar.baz // into: @@ -312,6 +299,19 @@ if (result) m->srcfile = new File(result); + if (global.params.verbose) + { + printf("import "); + if (packages) + { + for (size_t i = 0; i < packages->dim; i++) + { Identifier *pid = (Identifier *)packages->data[i]; + printf("%s.", pid->toChars()); + } + } + printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); + } + m->read(loc); m->parse(); diff -uNr dmd-1.005/dmd/src/dmd/mtype.c dmd-1.006/dmd/src/dmd/mtype.c --- dmd-1.005/dmd/src/dmd/mtype.c 2007-02-05 00:26:18.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/mtype.c 2007-02-14 02:00:22.000000000 +0100 @@ -607,7 +607,7 @@ error(e->loc, "%s.init is void", v->toChars()); else { e = v->init->toExpression(); - if (e->op == TOKassign) + if (e->op == TOKassign || e->op == TOKconstruct) { e = ((AssignExp *)e)->e2; @@ -1688,7 +1688,7 @@ sc = sc->push(sym); dim = dim->semantic(sc); - dim = dim->constFold(); + dim = dim->optimize(WANTvalue | WANTinterpret); uinteger_t d = dim->toUInteger(); sc = sc->pop(); @@ -1732,10 +1732,9 @@ dim = semanticLength(sc, tbn, dim); dim = dim->optimize(WANTvalue); - dim = dim->constFold(); integer_t d1 = dim->toInteger(); dim = dim->castTo(sc, tsize_t); - dim = dim->constFold(); + dim = dim->optimize(WANTvalue); integer_t d2 = dim->toInteger(); if (d1 != d2) @@ -4810,11 +4809,11 @@ TypeTuple *tt = (TypeTuple *)tbn; lwr = semanticLength(sc, tbn, lwr); - lwr = lwr->constFold(); + lwr = lwr->optimize(WANTvalue); uinteger_t i1 = lwr->toUInteger(); upr = semanticLength(sc, tbn, upr); - upr = upr->constFold(); + upr = upr->optimize(WANTvalue); uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) @@ -4853,11 +4852,11 @@ sc = sc->push(sym); lwr = lwr->semantic(sc); - lwr = lwr->constFold(); + lwr = lwr->optimize(WANTvalue); uinteger_t i1 = lwr->toUInteger(); upr = upr->semantic(sc); - upr = upr->constFold(); + upr = upr->optimize(WANTvalue); uinteger_t i2 = upr->toUInteger(); sc = sc->pop(); diff -uNr dmd-1.005/dmd/src/dmd/opover.c dmd-1.006/dmd/src/dmd/opover.c --- dmd-1.005/dmd/src/dmd/opover.c 2006-12-07 01:59:50.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/opover.c 2007-02-13 13:08:44.000000000 +0100 @@ -86,9 +86,9 @@ Identifier *InExp::opId() { return Id::opIn; } Identifier *InExp::opId_r() { return Id::opIn_r; } -Identifier *PostIncExp::opId() { return Id::postinc; } - -Identifier *PostDecExp::opId() { return Id::postdec; } +Identifier *PostExp::opId() { return (op == TOKplusplus) + ? Id::postinc + : Id::postdec; } int AddExp::isCommutative() { return TRUE; } Identifier *AddExp::opId() { return Id::add; } diff -uNr dmd-1.005/dmd/src/dmd/optimize.c dmd-1.006/dmd/src/dmd/optimize.c --- dmd-1.005/dmd/src/dmd/optimize.c 2007-02-04 16:43:14.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/optimize.c 2007-02-13 20:53:14.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -11,9 +11,11 @@ #include #include #include +#include -#include "mem.h" -#include "root.h" +#if __DMC__ +#include +#endif #include "lexer.h" #include "mtype.h" @@ -23,6 +25,16 @@ #include "init.h" +#ifdef IN_GCC +#include "d-gcc-real.h" + +/* %% fix? */ +extern "C" bool real_isnan (const real_t *); +#endif + +static real_t zero; // work around DMC bug for now + + /************************************* * If expression is a variable with a const initializer, * return that initializer. @@ -45,7 +57,7 @@ Expression *Expression::optimize(int result) { - //printf("Expression::optimize(result = %d) %s\n", result, toChars()); + //printf("Expression::optimize(result = x%x) %s\n", result, toChars()); return this; } @@ -54,7 +66,7 @@ for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; - e = e->optimize(WANTvalue); + e = e->optimize(WANTvalue | (result & WANTinterpret)); exps->data[i] = (void *)e; } return this; @@ -67,7 +79,7 @@ for (size_t i = 0; i < elements->dim; i++) { Expression *e = (Expression *)elements->data[i]; - e = e->optimize(WANTvalue); + e = e->optimize(WANTvalue | (result & WANTinterpret)); elements->data[i] = (void *)e; } } @@ -80,11 +92,58 @@ } Expression *UnaExp::optimize(int result) +{ + e1 = e1->optimize(result); + return this; +} + +Expression *NegExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Neg(type, e1); + } + else + e = this; + return e; +} + +Expression *ComExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); if (e1->isConst() == 1) - e = constFold(); + { + e = Com(type, e1); + } + else + e = this; + return e; +} + +Expression *NotExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Not(type, e1); + } + else + e = this; + return e; +} + +Expression *BoolExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Bool(type, e1); + } else e = this; return e; @@ -163,9 +222,34 @@ return this; } +Expression *CallExp::optimize(int result) +{ Expression *e = this; + + e1 = e1->optimize(result); + if (e1->op == TOKvar && result & WANTinterpret) + { + FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); + if (fd) + { + Expression *eresult = fd->interpret(arguments); + if (eresult) + e = eresult; + else if (result & WANTinterpret) + error("cannot evaluate %s at compile time", toChars()); + } + } + return e; +} + + Expression *CastExp::optimize(int result) { //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); + //printf("from %s to %s\n", type->toChars(), to->toChars()); + //printf("type = %p\n", type); + assert(type); + + e1 = e1->optimize(result); if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && type->next->equals(e1->type->next) @@ -181,7 +265,7 @@ return e1; } - if (result == WANTflags && type->ty == Tclass && e1->type->ty == Tclass) + if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) { // See if we can remove an unnecessary cast ClassDeclaration *cdfrom; @@ -199,22 +283,108 @@ Expression *e; - e1 = e1->optimize(result); if (e1->isConst()) - e = constFold(); + { + if (e1->op == TOKsymoff) + { + if (type->size() == e1->type->size() && + type->toBasetype()->ty != Tsarray) + { + e1->type = type; + return e1; + } + return this; + } + if (to->toBasetype()->ty == Tvoid) + e = this; + else + e = Cast(type, to, e1); + } else e = this; return e; } Expression *BinExp::optimize(int result) +{ + //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + return this; +} + +Expression *AddExp::optimize(int result) +{ Expression *e; + + //printf("AddExp::optimize(%s)\n", toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() && e2->isConst()) + { + if (e1->op == TOKsymoff && e2->op == TOKsymoff) + return this; + e = Add(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *MinExp::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() && e2->isConst()) + { + if (e2->op == TOKsymoff) + return this; + e = Min(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *MulExp::optimize(int result) +{ Expression *e; + + //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) - e = constFold(); + { + e = Mul(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *DivExp::optimize(int result) +{ Expression *e; + + //printf("DivExp::optimize(%s)\n", toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Div(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *ModExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Mod(type, e1, e2); + } else e = this; return e; @@ -229,37 +399,79 @@ e = this; if (e2->isConst() == 1) { - e2 = e2->constFold(); integer_t i2 = e2->toInteger(); if (i2 < 0 || i2 > e1->type->size() * 8) { error("shift left by %jd exceeds %zu", i2, e2->type->size() * 8); e2 = new IntegerExp(0); } if (e1->isConst() == 1) - e = constFold(); + e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); } return e; } -Expression *AddExp::optimize(int result) +Expression *ShrExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); e2 = e2->optimize(result); - if (e1->isConst() && e2->isConst()) - e = constFold(); + + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Shr(type, e1, e2); + } else e = this; return e; } -Expression *MinExp::optimize(int result) +Expression *UshrExp::optimize(int result) { Expression *e; + //printf("UshrExp::optimize() %s\n", toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); - if (e1->isConst() && e2->isConst()) - e = constFold(); + + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Ushr(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *AndExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + e = And(type, e1, e2); + else + e = this; + return e; +} + +Expression *OrExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + e = Or(type, e1, e2); + else + e = this; + return e; +} + +Expression *XorExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + e = Xor(type, e1, e2); else e = this; return e; @@ -269,7 +481,7 @@ { Expression *e; //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(0); + e1 = e1->optimize(result & WANTinterpret); e2 = e2->optimize(result); if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) { @@ -287,19 +499,11 @@ { Expression *e; //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e = this; - if (e1->op == TOKstring) - { StringExp *es1 = (StringExp *)e1; - - e = new IntegerExp(loc, es1->len, type); - } - else if (e1->op == TOKarrayliteral) - { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; - size_t dim; - - dim = ale->elements ? ale->elements->dim : 0; - e = new IntegerExp(loc, dim, type); + if (e1->op == TOKstring || e1->op == TOKarrayliteral) + { + e = ArrayLength(type, e1); } return e; } @@ -307,124 +511,46 @@ Expression *EqualExp::optimize(int result) { Expression *e; - //printf("EqualExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue); - e2 = e2->optimize(WANTvalue); + //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); + e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = this; Expression *e1 = fromConstInitializer(this->e1); Expression *e2 = fromConstInitializer(this->e2); - if (e1->op == TOKstring && e2->op == TOKstring) - { StringExp *es1 = (StringExp *)e1; - StringExp *es2 = (StringExp *)e2; - int value; - - assert(es1->sz == es2->sz); - if (es1->len == es2->len && - memcmp(es1->string, es2->string, es1->sz * es1->len) == 0) - value = 1; - else - value = 0; - if (op == TOKnotequal) - value ^= 1; - e = new IntegerExp(loc, value, type); - } - else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral) - { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; - ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; - int value; - - if ((!es1->elements || !es1->elements->dim) && - (!es2->elements || !es2->elements->dim)) - value = 1; // both arrays are empty - else if (!es1->elements || !es2->elements) - value = 0; - else if (es1->elements->dim != es2->elements->dim) - value = 0; - else - { - for (size_t i = 0; i < es1->elements->dim; i++) - { Expression *ee1 = (Expression *)es1->elements->data[i]; - Expression *ee2 = (Expression *)es2->elements->data[i]; - - if (!ee1->isConst() || !ee2->isConst()) - return e; - - EqualExp eq(TOKequal, 0, ee1, ee2); - Expression *v = eq.constFold(); - value = v->toInteger(); - if (value == 0) - break; - } - } - if (op == TOKnotequal) - value ^= 1; - e = new IntegerExp(loc, value, type); - } -#if 0 // Should handle this - else if (e1->op == TOKarrayliteral && e2->op == TOKstring) - { - } -#endif - else if (this->e1->isConst() == 1 && this->e2->isConst() == 1) - { - e = constFold(); - } + e = Equal(op, type, e1, e2); + if (e == EXP_CANT_INTERPRET) + e = this; return e; } -Expression *IndexExp::optimize(int result) +Expression *IdentityExp::optimize(int result) { Expression *e; - //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue); - e2 = e2->optimize(WANTvalue); + //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); + e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = this; - if (e1->op == TOKstring && e2->op == TOKint64) - { StringExp *es1 = (StringExp *)e1; - uinteger_t i = e2->toInteger(); - if (i >= es1->len) - error("string index %ju is out of bounds [0 .. %ju]", i, es1->len); - else - { integer_t value; - - switch (es1->sz) - { - case 1: - value = ((unsigned char *)es1->string)[i]; - break; - - case 2: - value = ((unsigned short *)es1->string)[i]; - break; - - case 4: - value = ((unsigned int *)es1->string)[i]; - break; - - default: - assert(0); - break; - } - e = new IntegerExp(loc, value, type); - } + if (this->e1->isConst() && this->e2->isConst()) + { + e = Identity(op, type, this->e1, this->e2); } - else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64) - { TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype(); - uinteger_t length = tsa->dim->toInteger(); - uinteger_t i = e2->toInteger(); + return e; +} - if (i >= length) - { error("array index %ju is out of bounds [0 .. %ju]", i, length); - } - else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) - { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; - e = (Expression *)ale->elements->data[i]; - e->type = type; - } - } +Expression *IndexExp::optimize(int result) +{ Expression *e; + + //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); + Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); + if (result & WANTinterpret) + e1 = fromConstInitializer(e1); + e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); + e = Index(type, e1, e2); + if (e == EXP_CANT_INTERPRET) + e = this; return e; } @@ -433,7 +559,7 @@ //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); e = this; - e1 = e1->optimize(WANTvalue); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); if (!lwr) { if (e1->op == TOKstring) { // Convert slice of string literal into dynamic array @@ -443,51 +569,13 @@ } return e; } - lwr = lwr->optimize(WANTvalue); - upr = upr->optimize(WANTvalue); - if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64) - { StringExp *es1 = (StringExp *)e1; - uinteger_t ilwr = lwr->toInteger(); - uinteger_t iupr = upr->toInteger(); - - if (iupr > es1->len || ilwr > iupr) - error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); - else - { integer_t value; - void *s; - size_t len = iupr - ilwr; - int sz = es1->sz; - StringExp *es; - - s = mem.malloc((len + 1) * sz); - memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz); - memset((unsigned char *)s + len * sz, 0, sz); - - es = new StringExp(loc, s, len, es1->postfix); - es->sz = sz; - es->committed = 1; - es->type = type; - e = es; - } - } - else if (e1->op == TOKarrayliteral && - lwr->op == TOKint64 && upr->op == TOKint64 && - !e1->checkSideEffect(2)) - { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; - uinteger_t ilwr = lwr->toInteger(); - uinteger_t iupr = upr->toInteger(); - - if (iupr > es1->elements->dim || ilwr > iupr) - error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); - else - { - memmove(es1->elements->data, - es1->elements->data + ilwr, - (iupr - ilwr) * sizeof(es1->elements->data[0])); - es1->elements->dim = iupr - ilwr; - e = es1; - } - } + if (result & WANTinterpret) + e1 = fromConstInitializer(e1); + lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); + upr = upr->optimize(WANTvalue | (result & WANTinterpret)); + e = Slice(type, e1, lwr, upr); + if (e == EXP_CANT_INTERPRET) + e = this; return e; } @@ -495,7 +583,7 @@ { Expression *e; //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); - e1 = e1->optimize(WANTflags); + e1 = e1->optimize(WANTflags | (result & WANTinterpret)); e = this; if (e1->isBool(FALSE)) { @@ -505,13 +593,17 @@ } else { - e2 = e2->optimize(WANTflags); + e2 = e2->optimize(WANTflags | (result & WANTinterpret)); if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) error("void has no value"); if (e1->isConst()) { if (e2->isConst()) - e = constFold(); + { int n1 = e1->isBool(1); + int n2 = e2->isBool(1); + + e = new IntegerExp(loc, n1 && n2, type); + } else if (e1->isBool(TRUE)) e = new BoolExp(loc, e2, type); } @@ -522,7 +614,7 @@ Expression *OrOrExp::optimize(int result) { Expression *e; - e1 = e1->optimize(WANTflags); + e1 = e1->optimize(WANTflags | (result & WANTinterpret)); e = this; if (e1->isBool(TRUE)) { // Replace with (e1, 1) @@ -532,13 +624,17 @@ } else { - e2 = e2->optimize(WANTflags); + e2 = e2->optimize(WANTflags | (result & WANTinterpret)); if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) error("void has no value"); if (e1->isConst()) { if (e2->isConst()) - e = constFold(); + { int n1 = e1->isBool(1); + int n2 = e2->isBool(1); + + e = new IntegerExp(loc, n1 || n2, type); + } else if (e1->isBool(FALSE)) e = new BoolExp(loc, e2, type); } @@ -546,159 +642,29 @@ return e; } -Expression *CatExp::optimize(int result) +Expression *CmpExp::optimize(int result) { Expression *e; - //printf("CatExp::optimize(%d) %s\n", result, toChars()); + //printf("CmpExp::optimize() %s\n", toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); - if (e1->op == TOKstring && e2->op == TOKstring) - { - // Concatenate the strings - void *s; - StringExp *es1 = (StringExp *)e1; - StringExp *es2 = (StringExp *)e2; - StringExp *es; - Type *t; - size_t len = es1->len + es2->len; - int sz = es1->sz; - - assert(sz == es2->sz); - s = mem.malloc((len + 1) * sz); - memcpy(s, es1->string, es1->len * sz); - memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz); - - // Add terminating 0 - memset((unsigned char *)s + len * sz, 0, sz); - - es = new StringExp(loc, s, len); - es->sz = sz; - es->committed = es1->committed | es2->committed; - if (es1->committed) - t = es1->type; - else - t = es2->type; - //es->type = new TypeSArray(t->next, new IntegerExp(0, len, Type::tindex)); - //es->type = es->type->semantic(loc, NULL); - es->type = type; - e = es; - } - else if (e1->op == TOKstring && e2->op == TOKint64) - { - // Concatenate the strings - void *s; - StringExp *es1 = (StringExp *)e1; - StringExp *es; - Type *t; - size_t len = es1->len + 1; - int sz = es1->sz; - integer_t v = e2->toInteger(); - - s = mem.malloc((len + 1) * sz); - memcpy(s, es1->string, es1->len * sz); - memcpy((unsigned char *)s + es1->len * sz, &v, sz); - - // Add terminating 0 - memset((unsigned char *)s + len * sz, 0, sz); - - es = new StringExp(loc, s, len); - es->sz = sz; - es->committed = es1->committed; - t = es1->type; - //es->type = new TypeSArray(t->next, new IntegerExp(0, len, Type::tindex)); - //es->type = es->type->semantic(loc, NULL); - es->type = type; - e = es; - } - else if (e1->op == TOKint64 && e2->op == TOKstring) - { - // Concatenate the strings - void *s; - StringExp *es2 = (StringExp *)e2; - StringExp *es; - Type *t; - size_t len = 1 + es2->len; - int sz = es2->sz; - integer_t v = e1->toInteger(); - - s = mem.malloc((len + 1) * sz); - memcpy((unsigned char *)s, &v, sz); - memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); - - // Add terminating 0 - memset((unsigned char *)s + len * sz, 0, sz); - - es = new StringExp(loc, s, len); - es->sz = sz; - es->committed = es2->committed; - t = es2->type; - //es->type = new TypeSArray(t->next, new IntegerExp(0, len, Type::tindex)); - //es->type = es->type->semantic(loc, NULL); - es->type = type; - e = es; - } - else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral && - e1->type->equals(e2->type)) - { - // Concatenate the arrays - ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; - ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; - - es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); - es1->elements->insert(es1->elements->dim, es2->elements); - e = es1; - - if (type->toBasetype()->ty == Tsarray) - { - e->type = new TypeSArray(e1->type->toBasetype()->next, new IntegerExp(0, es1->elements->dim, Type::tindex)); - e->type = e->type->semantic(loc, NULL); - } - else - e->type = type; - } - else if (e1->op == TOKarrayliteral && - e1->type->toBasetype()->next->equals(e2->type)) + if (e1->isConst() == 1 && e2->isConst() == 1) { - ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; - - es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); - es1->elements->push(e2); - e = es1; - - if (type->toBasetype()->ty == Tsarray) - { - e->type = new TypeSArray(e2->type, new IntegerExp(0, es1->elements->dim, Type::tindex)); - e->type = e->type->semantic(loc, NULL); - } - else - e->type = type; + e = Cmp(op, type, this->e1, this->e2); } - else if (e2->op == TOKarrayliteral && - e2->type->toBasetype()->next->equals(e1->type)) - { - ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + else + e = this; + return e; +} - es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy()); - es2->elements->shift(e1); - e = es2; +Expression *CatExp::optimize(int result) +{ Expression *e; - if (type->toBasetype()->ty == Tsarray) - { - e->type = new TypeSArray(e1->type, new IntegerExp(0, es2->elements->dim, Type::tindex)); - e->type = e->type->semantic(loc, NULL); - } - else - e->type = type; - } - else if (e1->op == TOKnull && e2->op == TOKstring) - { - e = e2->castTo(NULL, type); - } - else if (e1->op == TOKstring && e2->op == TOKnull) - { - e = e1->castTo(NULL, type); - } - else + //printf("CatExp::optimize(%d) %s\n", result, toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + e = Cat(type, e1, e2); + if (e == EXP_CANT_INTERPRET) e = this; return e; } @@ -707,7 +673,7 @@ Expression *CondExp::optimize(int result) { Expression *e; - econd = econd->optimize(WANTflags); + econd = econd->optimize(WANTflags | (result & WANTinterpret)); if (econd->isBool(TRUE)) e = e1->optimize(result); else if (econd->isBool(FALSE)) diff -uNr dmd-1.005/dmd/src/dmd/parse.c dmd-1.006/dmd/src/dmd/parse.c --- dmd-1.005/dmd/src/dmd/parse.c 2007-02-04 19:49:02.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/parse.c 2007-02-13 13:04:28.000000000 +0100 @@ -4057,11 +4057,11 @@ break; case TOKplusplus: - e = new PostIncExp(loc, e); + e = new PostExp(TOKplusplus, loc, e); break; case TOKminusminus: - e = new PostDecExp(loc, e); + e = new PostExp(TOKminusminus, loc, e); break; case TOKlparen: diff -uNr dmd-1.005/dmd/src/dmd/statement.c dmd-1.006/dmd/src/dmd/statement.c --- dmd-1.005/dmd/src/dmd/statement.c 2007-02-04 00:18:54.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/statement.c 2007-02-14 19:18:10.000000000 +0100 @@ -158,6 +158,7 @@ return NULL; } + /******************************** ExpStatement ***************************/ ExpStatement::ExpStatement(Loc loc, Expression *exp) @@ -1939,6 +1940,7 @@ body = b; sdefault = NULL; cases = NULL; + hasNoDefault = 0; } Statement *SwitchStatement::syntaxCopy() @@ -2009,7 +2011,8 @@ } if (!sc->sw->sdefault) - { + { hasNoDefault = 1; + if (global.params.warnings) { fprintf(stdmsg, "warning - "); error("switch statement has no default"); @@ -2102,7 +2105,7 @@ { int i; exp = exp->implicitCastTo(sc, sw->condition->type); - exp = exp->constFold(); + exp = exp->optimize(WANTvalue); if (exp->op != TOKstring && exp->op != TOKint64) { error("case must be a string or an integral constant, not %s", exp->toChars()); @@ -2287,7 +2290,7 @@ if (exp) { exp = exp->implicitCastTo(sc, sc->sw->condition->type); - exp = exp->constFold(); + exp = exp->optimize(WANTvalue); } } return this; diff -uNr dmd-1.005/dmd/src/dmd/statement.h dmd-1.006/dmd/src/dmd/statement.h --- dmd-1.005/dmd/src/dmd/statement.h 2007-02-03 23:26:36.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/statement.h 2007-02-14 19:30:44.000000000 +0100 @@ -43,6 +43,7 @@ struct ScopeStatement; struct TryCatchStatement; struct HdrGenState; +struct InterState; enum TOK; @@ -86,6 +87,7 @@ virtual int comeFrom(); virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); virtual Statements *flatten(Scope *sc); + virtual Expression *interpret(InterState *istate); virtual int inlineCost(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); @@ -108,6 +110,7 @@ Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); int fallOffEnd(); int inlineCost(InlineCostState *ics); @@ -155,6 +158,7 @@ int comeFrom(); Statements *flatten(Scope *sc); ReturnStatement *isReturnStatement(); + Expression *interpret(InterState *istate); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -180,6 +184,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int inlineCost(InlineCostState *ics); @@ -203,6 +208,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -222,6 +228,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -242,6 +249,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -265,6 +273,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -295,6 +304,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -314,6 +324,7 @@ IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); int fallOffEnd(); @@ -374,6 +385,7 @@ Array gotoCases; // array of unresolved GotoCaseStatement's Array *cases; // array of CaseStatement's + int hasNoDefault; // !=0 if no default statement SwitchStatement(Loc loc, Expression *c, Statement *b); Statement *syntaxCopy(); @@ -381,6 +393,7 @@ int hasBreak(); int usesEH(); int fallOffEnd(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -402,6 +415,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -422,6 +436,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -436,6 +451,7 @@ GotoDefaultStatement(Loc loc); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); int fallOffEnd(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -450,6 +466,7 @@ GotoCaseStatement(Loc loc, Expression *exp); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); int fallOffEnd(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -474,6 +491,7 @@ void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); int fallOffEnd(); + Expression *interpret(InterState *istate); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -491,6 +509,7 @@ BreakStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); int fallOffEnd(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -504,6 +523,7 @@ ContinueStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); int fallOffEnd(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -658,6 +678,7 @@ Statement *syntaxCopy(); Statement *semantic(Scope *sc); int fallOffEnd(); + Expression *interpret(InterState *istate); void toIR(IRState *irs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -679,6 +700,7 @@ int usesEH(); int fallOffEnd(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); diff -uNr dmd-1.005/dmd/src/dmd/template.c dmd-1.006/dmd/src/dmd/template.c --- dmd-1.005/dmd/src/dmd/template.c 2007-02-04 16:39:16.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/template.c 2007-02-14 21:20:56.000000000 +0100 @@ -1981,7 +1981,7 @@ e = e->semantic(sc); e = e->implicitCastTo(sc, valType); - e = e->constFold(); + e = e->optimize(WANTvalue | WANTinterpret); if (e->op == TOKint64 || e->op == TOKfloat64 || e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring) specValue = e; @@ -1994,7 +1994,7 @@ e = e->semantic(sc); e = e->implicitCastTo(sc, valType); - e = e->constFold(); + e = e->optimize(WANTvalue | WANTinterpret); if (e->op == TOKint64) defaultValue = e; //e->toInteger(); @@ -2061,11 +2061,11 @@ e = e->semantic(sc); e = e->implicitCastTo(sc, valType); - e = e->constFold(); + e = e->optimize(WANTvalue | WANTinterpret); ei = ei->syntaxCopy(); ei = ei->semantic(sc); - ei = ei->constFold(); + ei = ei->optimize(WANTvalue | WANTinterpret); //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars()); //printf("e : %s, %s\n", e->toChars(), e->type->toChars()); if (!ei->equals(e)) @@ -2687,8 +2687,7 @@ if (ea) { ea = ea->semantic(sc); - ea = ea->optimize(WANTvalue); - ea = ea->constFold(); + ea = ea->optimize(WANTvalue | WANTinterpret); tiargs->data[j] = ea; } else if (sa) @@ -2735,8 +2734,7 @@ } assert(ea); ea = ea->semantic(sc); - ea = ea->optimize(WANTvalue); - //ea = ea->constFold(); + ea = ea->optimize(WANTvalue | WANTinterpret); tiargs->data[j] = ea; } else if (sa) @@ -2977,7 +2975,7 @@ { assert(ea); ea = ea->castTo(tvp->valType); - ea = ea->optimize(WANTvalue); + ea = ea->optimize(WANTvalue | WANTinterpret); tiargs->data[i] = (Object *)ea; } } diff -uNr dmd-1.005/dmd/src/dmd/typinf.c dmd-1.006/dmd/src/dmd/typinf.c --- dmd-1.005/dmd/src/dmd/typinf.c 2007-01-31 23:48:54.000000000 +0100 +++ dmd-1.006/dmd/src/dmd/typinf.c 2007-02-09 00:13:28.000000000 +0100 @@ -368,6 +368,8 @@ { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); + unsigned offset = Type::typeinfostruct->structsize; + dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct dtdword(pdt, 0); // monitor @@ -384,12 +386,16 @@ * int function(void*,void*) xopCmp; * char[] function(void*) xtoString; * uint m_flags; + * + * name[] */ char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtdword(pdt, namelen); - dtabytes(pdt, TYnptr, 0, namelen + 1, name); + //dtabytes(pdt, TYnptr, 0, namelen + 1, name); + dtxoff(pdt, toSymbol(), offset, TYnptr); + offset += namelen + 1; // void[] init; dtdword(pdt, sd->structsize); // init.length @@ -489,6 +495,9 @@ // uint m_flags; dtdword(pdt, tc->hasPointers()); + + // name[] + dtnbytes(pdt, namelen + 1, name); } void TypeInfoClassDeclaration::toDt(dt_t **pdt) diff -uNr dmd-1.005/dmd/src/phobos/std/c/time.d dmd-1.006/dmd/src/phobos/std/c/time.d --- dmd-1.005/dmd/src/phobos/std/c/time.d 2007-02-05 18:37:56.000000000 +0100 +++ dmd-1.006/dmd/src/phobos/std/c/time.d 2007-02-15 02:03:28.000000000 +0100 @@ -37,7 +37,11 @@ else version (linux) { extern (C) int sysconf(int); - const clock_t CLK_TCK = cast(clock_t) sysconf(2); + extern clock_t CLK_TCK; + /*static this() + { + CLK_TCK = cast(clock_t) sysconf(2); + }*/ } else {