Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 79 additions & 72 deletions src/interpret.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
{
Expand Down Expand Up @@ -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");
Expand All @@ -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");
Expand All @@ -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");
Expand All @@ -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)
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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
}
Expand All @@ -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
Expand Down
11 changes: 11 additions & 0 deletions test/compilable/interpret3.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}());

Expand All @@ -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);