diff --git a/dmd/constfold.c b/dmd/constfold.c index 2454ed41..12f928ce 100644 --- a/dmd/constfold.c +++ b/dmd/constfold.c @@ -863,7 +863,7 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) } Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) -{ Expression *e; +{ Loc loc = e1->loc; int cmp; @@ -1055,12 +1055,12 @@ Expression *Cast(Type *type, Type *to, Expression *e1) return e1; Type *tb = to->toBasetype(); + Type *typeb = type->toBasetype(); /* Allow casting from one string type to another */ if (e1->op == TOKstring) { - Type *typeb = type->toBasetype(); if (tb->ty == Tarray && typeb->ty == Tarray && tb->nextOf()->size() == typeb->nextOf()->size()) { @@ -1068,8 +1068,15 @@ Expression *Cast(Type *type, Type *to, Expression *e1) } } + if (e1->op == TOKarrayliteral && typeb == tb) + { + return e1; + } + if (e1->isConst() != 1) + { return EXP_CANT_INTERPRET; + } if (tb->ty == Tbool) e = new IntegerExp(loc, e1->toInteger() != 0, type); diff --git a/dmd/declaration.c b/dmd/declaration.c index b3521187..28b9ff2d 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -309,6 +309,9 @@ void TypedefDeclaration::semantic(Scope *sc) { sem = 1; basetype = basetype->semantic(loc, sc); sem = 2; +#if DMDV2 + type = type->addStorageClass(storage_class); +#endif type = type->semantic(loc, sc); if (sc->parent->isFuncDeclaration() && init) semantic2(sc); @@ -441,8 +444,10 @@ void AliasDeclaration::semantic(Scope *sc) } this->inSemantic = 1; +#if DMDV1 // don't really know why this is here if (storage_class & STCconst) error("cannot be const"); +#endif storage_class |= sc->stc & STCdeprecated; @@ -473,11 +478,12 @@ void AliasDeclaration::semantic(Scope *sc) goto L2; // it's a symbolic alias #if DMDV2 + type = type->addStorageClass(storage_class); if (storage_class & (STCref | STCnothrow | STCpure)) { // For 'ref' to be attached to function types, and picked // up by Type::resolve(), it has to go into sc. sc = sc->push(); - sc->stc |= storage_class & (STCref | STCnothrow | STCpure); + sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); type->resolve(loc, sc, &e, &t, &s); sc = sc->pop(); } @@ -1341,7 +1347,7 @@ int VarDeclaration::isDataseg() { #if 0 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); - printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); + printf("%llx, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); printf("parent = '%s'\n", parent->toChars()); #endif Dsymbol *parent = this->toParent(); @@ -1364,6 +1370,17 @@ int VarDeclaration::isThreadlocal() return 0; } +/******************************************** + * Can variable be read and written by CTFE? + */ + +int VarDeclaration::isCTFE() +{ + //printf("VarDeclaration::isCTFE(%p, '%s')\n", this, toChars()); + //printf("%llx\n", storage_class); + return (storage_class & STCctfe) || !isDataseg(); +} + int VarDeclaration::hasPointers() { //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); diff --git a/dmd/declaration.h b/dmd/declaration.h index 8258afc6..6a04d7c9 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -79,9 +79,16 @@ enum STC STCshared = 0x20000000, // accessible from multiple threads STCgshared = 0x40000000, // accessible from multiple threads // but not typed as "shared" - STC_TYPECTOR = (STCconst | STCimmutable | STCshared), + STCwild = 0x80000000, // for "wild" type constructor + STC_TYPECTOR = (STCconst | STCimmutable | STCshared | STCwild), }; +#define STCproperty 0x100000000LL +#define STCsafe 0x200000000LL +#define STCtrusted 0x400000000LL +#define STCsystem 0x800000000LL +#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static + struct Match { int count; // number of matches found @@ -290,6 +297,7 @@ struct VarDeclaration : Declaration int isImportedSymbol(); int isDataseg(); int isThreadlocal(); + int isCTFE(); int hasPointers(); #if DMDV2 int canTakeAddressOf(); diff --git a/dmd/expression.c b/dmd/expression.c index 1458c96d..a8fa267a 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -711,6 +711,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); t = t->semantic(loc, sc); VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); + v->storage_class |= STCctfe; v->semantic(sc); v->parent = sc->parent; //sc->insert(v); diff --git a/dmd/interpret.c b/dmd/interpret.c index 903309dd..79d0dc07 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -48,6 +48,10 @@ Expression *interpret_aaLen(InterState *istate, Expressions *arguments); Expression *interpret_aaKeys(InterState *istate, Expressions *arguments); Expression *interpret_aaValues(InterState *istate, Expressions *arguments); +Expression *interpret_length(InterState *istate, Expression *earg); +Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd); +Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd); + /************************************* * Attempt to interpret a function given the arguments. * Input: @@ -66,12 +70,27 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument #endif if (global.errors) return NULL; + +#if DMDV1 if (ident == Id::aaLen) return interpret_aaLen(istate, arguments); else if (ident == Id::aaKeys) return interpret_aaKeys(istate, arguments); else if (ident == Id::aaValues) return interpret_aaValues(istate, arguments); +#endif +#if DMDV2 + if (thisarg && + (!arguments || arguments->dim == 0)) + { + if (ident == Id::length) + return interpret_length(istate, thisarg); + else if (ident == Id::keys) + return interpret_keys(istate, thisarg, this); + else if (ident == Id::values) + return interpret_values(istate, thisarg, this); + } +#endif if (cantInterpret || semanticRun == 3) return NULL; @@ -94,9 +113,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument assert(tb->ty == Tfunction); TypeFunction *tf = (TypeFunction *)tb; Type *tret = tf->next->toBasetype(); - if (tf->varargs) + if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim) { cantInterpret = 1; - error("Variadic functions are not yet implemented in CTFE"); + error("C-style variadic functions are not yet implemented in CTFE"); return NULL; } @@ -1004,7 +1023,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) } else { e = v->value; - if (v->isDataseg()) + if (!v->isCTFE()) { error(loc, "static variable %s cannot be read at compile time", v->toChars()); e = EXP_CANT_INTERPRET; } @@ -1136,9 +1155,7 @@ Expression *ArrayLiteralExp::interpret(InterState *istate) ex = e->interpret(istate); if (ex == EXP_CANT_INTERPRET) - { delete expsx; - return EXP_CANT_INTERPRET; - } + goto Lerror; /* If any changes, do Copy On Write */ @@ -1160,14 +1177,18 @@ Expression *ArrayLiteralExp::interpret(InterState *istate) { expandTuples(expsx); if (expsx->dim != elements->dim) - { delete expsx; - return EXP_CANT_INTERPRET; - } + goto Lerror; ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx); ae->type = type; return ae; } return this; + +Lerror: + if (expsx) + delete expsx; + error("cannot interpret array literal"); + return EXP_CANT_INTERPRET; } Expression *AssocArrayLiteralExp::interpret(InterState *istate) @@ -1594,12 +1615,12 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); assert(v); - if (v && v->isDataseg()) + if (v && !v->isCTFE()) { // Can't modify global or static data error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; } - if (v && !v->isDataseg()) + if (v && v->isCTFE()) { Expression *ev = v->value; if (fp && !ev) @@ -1635,7 +1656,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) else if (e1->op == TOKdotvar && aggregate->op == TOKvar) { VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); - if (v->isDataseg()) + if (!v->isCTFE()) { // Can't modify global or static data error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; @@ -1707,7 +1728,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; VarDeclaration *v = soe->var->isVarDeclaration(); - if (v->isDataseg()) + if (!v->isCTFE()) { error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; @@ -1753,7 +1774,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) { IndexExp *ie = (IndexExp *)e1; VarExp *ve = (VarExp *)ie->e1; VarDeclaration *v = ve->var->isVarDeclaration(); - if (!v || v->isDataseg()) + if (!v || !v->isCTFE()) { error("%s cannot be modified at compile time", v ? v->toChars(): "void"); return EXP_CANT_INTERPRET; @@ -1916,7 +1937,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) IndexExp * ie = (IndexExp *)aggregate; VarExp *ve = (VarExp *)(ie->e1); VarDeclaration *v = ve->var->isVarDeclaration(); - if (!v || v->isDataseg()) + if (!v || !v->isCTFE()) { error("%s cannot be modified at compile time", v ? v->toChars(): "void"); return EXP_CANT_INTERPRET; @@ -2008,7 +2029,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) SliceExp * sexp = (SliceExp *)e1; VarExp *ve = (VarExp *)(sexp->e1); VarDeclaration *v = ve->var->isVarDeclaration(); - if (!v || v->isDataseg()) + if (!v || !v->isCTFE()) { error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; @@ -2636,6 +2657,8 @@ Expression *DotVarExp::interpret(InterState *istate) /******************************* Special Functions ***************************/ +#if DMDV1 + Expression *interpret_aaLen(InterState *istate, Expressions *arguments) { if (!arguments || arguments->dim != 1) @@ -2690,3 +2713,59 @@ Expression *interpret_aaValues(InterState *istate, Expressions *arguments) return e; } +#endif + +#if DMDV2 + +Expression *interpret_length(InterState *istate, Expression *earg) +{ + //printf("interpret_length()\n"); + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; + if (earg->op != TOKassocarrayliteral) + return NULL; + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; + Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); + return e; +} + +Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd) +{ +#if LOG + printf("interpret_keys()\n"); +#endif + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; + if (earg->op != TOKassocarrayliteral) + return NULL; + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; + Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); + assert(fd->type->ty == Tfunction); + assert(fd->type->nextOf()->ty == Tarray); + Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); + e->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim)); + return e; +} + +Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd) +{ + //printf("interpret_values()\n"); + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; + if (earg->op != TOKassocarrayliteral) + return NULL; + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; + Expression *e = new ArrayLiteralExp(aae->loc, aae->values); + assert(fd->type->ty == Tfunction); + assert(fd->type->nextOf()->ty == Tarray); + Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); + e->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim)); + //printf("result is %s\n", e->toChars()); + return e; +} + +#endif + diff --git a/dmd/mars.h b/dmd/mars.h index 33730c5a..9734fa99 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -417,7 +417,7 @@ enum MATCH MATCHexact // exact match }; -typedef unsigned StorageClass; +typedef uint64_t StorageClass; void warning(Loc loc, const char *format, ...) IS_PRINTF(2); diff --git a/dmd/mtype.c b/dmd/mtype.c index 2bc4c7b1..1906a4fe 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -5466,7 +5466,7 @@ void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) /***************************** Parameter *****************************/ -Parameter::Parameter(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg) +Parameter::Parameter(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg) { this->type = type; this->ident = ident;