diff --git a/src/interpret.c b/src/interpret.c index 41ace30132bd..69f3888f7699 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -1491,12 +1491,22 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) { // Check for unsupported type painting operations Type *elemtype = ((TypeArray *)(val->type))->next; + + // It's OK to cast from fixed length to dynamic array, eg &int[3] to int[]* + if (val->type->ty == Tsarray && pointee->ty == Tarray + && elemtype->size() == pointee->nextOf()->size()) + { + Expression *e = new AddrExp(loc, val); + e->type = type; + return e; + } if ( #if DMDV2 elemtype->castMod(0) != pointee->castMod(0) #else elemtype != pointee #endif + // It's OK to cast from int[] to uint* && !(elemtype->isintegral() && pointee->isintegral() && elemtype->size() == pointee->size())) { @@ -5150,55 +5160,6 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) /******************************* Special Functions ***************************/ -#if DMDV1 - -Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) -{ -#if LOG - printf("interpret_aaKeys()\n"); -#endif - if (!arguments || arguments->dim != 2) - return NULL; - Expression *earg = arguments->tdata()[0]; - earg = earg->interpret(istate); - if (earg == EXP_CANT_INTERPRET) - return NULL; - if (earg->op == TOKnull) - return new NullExp(earg->loc); - if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) - return NULL; - AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; - Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); - Type *elemType = ((TypeAArray *)aae->type)->index; - e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); - return copyLiteral(e); -} - -Expression *interpret_aaValues(InterState *istate, Expressions *arguments) -{ -#if LOG - printf("interpret_aaValues()\n"); -#endif - if (!arguments || arguments->dim != 3) - return NULL; - Expression *earg = arguments->tdata()[0]; - earg = earg->interpret(istate); - if (earg == EXP_CANT_INTERPRET) - return NULL; - if (earg->op == TOKnull) - return new NullExp(earg->loc); - if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) - return NULL; - AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; - Expression *e = new ArrayLiteralExp(aae->loc, aae->values); - Type *elemType = ((TypeAArray *)aae->type)->next; - e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); - //printf("result is %s\n", e->toChars()); - return copyLiteral(e); -} - -#endif - Expression *interpret_length(InterState *istate, Expression *earg) { //printf("interpret_length()\n"); @@ -5213,9 +5174,7 @@ Expression *interpret_length(InterState *istate, Expression *earg) return e; } -#if DMDV2 - -Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd) +Expression *interpret_keys(InterState *istate, Expression *earg, Type *elemType) { #if LOG printf("interpret_keys()\n"); @@ -5230,14 +5189,11 @@ Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration assert(earg->op == TOKassocarrayliteral); 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 copyLiteral(e); } -Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd) +Expression *interpret_values(InterState *istate, Expression *earg, Type *elemType) { #if LOG printf("interpret_values()\n"); @@ -5252,16 +5208,11 @@ Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclarati assert(earg->op == TOKassocarrayliteral); 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 copyLiteral(e); } -#endif - #if DMDV2 // Return true if t is an AA, or AssociativeArray!(key, value) bool isAssocArray(Type *t) @@ -5276,8 +5227,31 @@ bool isAssocArray(Type *t) return true; return false; } + +// Given a template AA type, extract the corresponding built-in AA type +TypeAArray *toBuiltinAAType(Type *t) +{ + t = t->toBasetype(); + if (t->ty == Taarray) + return (TypeAArray *)t; + assert(t->ty == Tstruct); + StructDeclaration *sym = ((TypeStruct *)t)->sym; + assert(sym->ident == Id::AssociativeArray); + TemplateInstance *tinst = sym->parent->isTemplateInstance(); + assert(tinst); + return new TypeAArray((Type *)(tinst->tiargs->tdata()[1]), (Type *)(tinst->tiargs->tdata()[0])); +} #endif +// Helper function: given a function of type A[] f(...), +// return A. +Type *returnedArrayElementType(FuncDeclaration *fd) +{ + assert(fd->type->ty == Tfunction); + assert(fd->type->nextOf()->ty == Tarray); + return ((TypeFunction *)fd->type)->nextOf()->nextOf(); +} + /* Decoding UTF strings for foreach loops. Duplicates the functionality of * the twelve _aApplyXXn functions in aApply.d in the runtime. */ @@ -5539,9 +5513,9 @@ bool evaluateIfBuiltin(Expression **result, InterState *istate, if (fd->ident == Id::length) e = interpret_length(istate, pthis); else if (fd->ident == Id::keys) - e = interpret_keys(istate, pthis, fd); + e = interpret_keys(istate, pthis, returnedArrayElementType(fd)); else if (fd->ident == Id::values) - e = interpret_values(istate, pthis, fd); + e = interpret_values(istate, pthis, returnedArrayElementType(fd)); else if (fd->ident == Id::rehash) e = pthis; // rehash is a no-op } @@ -5567,20 +5541,53 @@ bool evaluateIfBuiltin(Expression **result, InterState *istate, e = EXP_CANT_INTERPRET; } } + /* Horrid hack to retrieve the builtin AA functions after they've been + * mashed by the inliner. + */ + if (!pthis) + { + Expression *firstarg = nargs > 0 ? (Expression *)(arguments->data[0]) : NULL; + // Check for the first parameter being a templatized AA. Hack: we assume that + // template AA.var is always the AA data itself. + Expression *firstdotvar = (firstarg && firstarg->op == TOKdotvar) + ? ((DotVarExp *)firstarg)->e1 : NULL; + if (firstdotvar && isAssocArray(firstdotvar->type)) + { if (fd->ident == Id::aaLen && nargs == 1) + e = interpret_length(istate, firstdotvar->interpret(istate)); + else if (fd->ident == Id::aaKeys && nargs == 2) + { + Expression *trueAA = firstdotvar->interpret(istate); + e = interpret_keys(istate, trueAA, toBuiltinAAType(trueAA->type)->index); + } + else if (fd->ident == Id::aaValues && nargs == 3) + { + Expression *trueAA = firstdotvar->interpret(istate); + e = interpret_values(istate, trueAA, toBuiltinAAType(trueAA->type)->nextOf()); + } + else if (fd->ident == Id::aaRehash && nargs == 2) + { + return firstdotvar->interpret(istate, ctfeNeedLvalue); + } + } + } #endif #if DMDV1 if (!pthis) { Expression *firstarg = nargs > 0 ? (Expression *)(arguments->data[0]) : NULL; - if (fd->ident == Id::aaLen && nargs == 1 && firstarg->type->toBasetype()->ty == Taarray) - e = interpret_length(istate, firstarg); - else if (fd->ident == Id::aaKeys) - e = interpret_aaKeys(istate, arguments); - else if (fd->ident == Id::aaValues) - e = interpret_aaValues(istate, arguments); - else if (fd->ident == Id::aaRehash && nargs == 2) - { // rehash is a no-op - return firstarg->interpret(istate, ctfeNeedLvalue); + if (firstarg && firstarg->type->toBasetype()->ty == Taarray) + { + TypeAArray *firstAAtype = (TypeAArray *)firstarg->type; + if (fd->ident == Id::aaLen && nargs == 1) + e = interpret_length(istate, firstarg); + else if (fd->ident == Id::aaKeys) + e = interpret_keys(istate, firstarg, firstAAtype->index); + else if (fd->ident == Id::aaValues) + e = interpret_values(istate, firstarg, firstAAtype->nextOf()); + else if (fd->ident == Id::aaRehash && nargs == 2) + { // rehash is a no-op + return firstarg->interpret(istate, ctfeNeedLvalue); + } } } #endif diff --git a/test/compilable/interpret3.d b/test/compilable/interpret3.d index 3515455ec720..5eb02fa70f9e 100644 --- a/test/compilable/interpret3.d +++ b/test/compilable/interpret3.d @@ -2599,6 +2599,7 @@ static assert({ assert(s.aa[7][56] == 57); bug6751c(s.aa); assert(s.aa.keys.length==1); + assert(s.aa.values.length==1); return true; }()); @@ -2623,3 +2624,13 @@ static assert({ int[int] w; return w.length; }()==0); + +/************************************************** + 6769 AA.keys, AA.values with -inline +**************************************************/ + +static assert({ + double[char[3]] w = ["abc" : 2.3]; + double[] z = w.values; + return w.keys.length; +}() == 1);