Skip to content

Commit

Permalink
CTFE: Refactor array length assignment into a new function
Browse files Browse the repository at this point in the history
  • Loading branch information
don-clugston-sociomantic committed Oct 26, 2012
1 parent caef8ad commit 89fce80
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 57 deletions.
6 changes: 6 additions & 0 deletions src/ctfe.h
Expand Up @@ -144,6 +144,12 @@ Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset,
Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
Expression *index, Expression *newval);

/// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
/// oldlen, change its length to newlen. If the newlen is longer than oldlen,
/// all new elements will be set to the default initializer for the element type.
Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
Expression *oldval, size_t oldlen, size_t newlen);



/// Return true if t is a pointer (not a function pointer)
Expand Down
64 changes: 64 additions & 0 deletions src/ctfeexpr.c
Expand Up @@ -1314,6 +1314,70 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
return newval;
}

/// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
/// oldlen, change its length to newlen. If the newlen is longer than oldlen,
/// all new elements will be set to the default initializer for the element type.
Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
Expression *oldval, size_t oldlen, size_t newlen)
{
Type *elemType = elemType = arrayType->next;
assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral(loc);
Expressions *elements = new Expressions();
elements->setDim(newlen);
if (oldval->op == TOKslice)
oldval = resolveSlice(oldval);
size_t copylen = oldlen < newlen ? oldlen : newlen;
if (oldval->op == TOKstring)
{
StringExp *oldse = (StringExp *)oldval;
unsigned char *s = (unsigned char *)mem.calloc(newlen + 1, oldse->sz);
memcpy(s, oldse->string, copylen * oldse->sz);
unsigned defaultValue = (unsigned)(defaultElem->toInteger());
for (size_t elemi = copylen; elemi < newlen; ++elemi)
{
switch (oldse->sz)
{
case 1: s[elemi] = defaultValue; break;
case 2: ((unsigned short *)s)[elemi] = defaultValue; break;
case 4: ((unsigned *)s)[elemi] = defaultValue; break;
default: assert(0);
}
}
StringExp *se = new StringExp(loc, s, newlen);
se->type = arrayType;
se->sz = oldse->sz;
se->committed = oldse->committed;
se->ownedByCtfe = true;
return se;
}
else
{
if (oldlen !=0)
assert(oldval->op == TOKarrayliteral);
ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval;
for (size_t i = 0; i < copylen; i++)
(*elements)[i] = ae->elements->tdata()[i];
if (elemType->ty == Tstruct || elemType->ty == Tsarray)
{ /* If it is an aggregate literal representing a value type,
* we need to create a unique copy for each element
*/
for (size_t i = copylen; i < newlen; i++)
(*elements)[i] = copyLiteral(defaultElem);
}
else
{
for (size_t i = copylen; i < newlen; i++)
(*elements)[i] = defaultElem;
}
ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements);
aae->type = arrayType;
aae->ownedByCtfe = true;
return aae;
}
}


/*************************** CTFE Sanity Checks ***************************/


Expand Down
59 changes: 2 additions & 57 deletions src/interpret.c
Expand Up @@ -2725,66 +2725,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
oldval = oldval->interpret(istate);
}
}
if (oldval->op == TOKslice)
oldval = resolveSlice(oldval);
Type *t = e1->type->toBasetype();
if (t->ty == Tarray)
{
Type *elemType= NULL;
elemType = ((TypeArray *)t)->next;
assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral(loc);

Expressions *elements = new Expressions();
elements->setDim(newlen);
size_t copylen = oldlen < newlen ? oldlen : newlen;
if (oldval->op == TOKstring)
{
StringExp *oldse = (StringExp *)oldval;
unsigned char *s = (unsigned char *)mem.calloc(newlen + 1, oldse->sz);
memcpy(s, oldse->string, copylen * oldse->sz);
unsigned defaultValue = (unsigned)(defaultElem->toInteger());
for (size_t elemi = copylen; elemi < newlen; ++elemi)
{
switch (oldse->sz)
{
case 1: s[elemi] = defaultValue; break;
case 2: ((unsigned short *)s)[elemi] = defaultValue; break;
case 4: ((unsigned *)s)[elemi] = defaultValue; break;
default: assert(0);
}
}
StringExp *se = new StringExp(loc, s, newlen);
se->type = t;
se->sz = oldse->sz;
se->committed = oldse->committed;
se->ownedByCtfe = true;
newval = se;
}
else
{
if (oldlen !=0)
assert(oldval->op == TOKarrayliteral);
ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval;
for (size_t i = 0; i < copylen; i++)
(*elements)[i] = ae->elements->tdata()[i];
if (elemType->ty == Tstruct || elemType->ty == Tsarray)
{ /* If it is an aggregate literal representing a value type,
* we need to create a unique copy for each element
*/
for (size_t i = copylen; i < newlen; i++)
(*elements)[i] = copyLiteral(defaultElem);
}
else
{
for (size_t i = copylen; i < newlen; i++)
(*elements)[i] = defaultElem;
}
ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements);
aae->type = t;
newval = aae;
aae->ownedByCtfe = true;
}
newval = changeArrayLiteralLength(loc, (TypeArray *)t, oldval,
oldlen, newlen);
// We have changed it into a reference assignment
// Note that returnValue is still the new length.
wantRef = true;
Expand Down

0 comments on commit 89fce80

Please sign in to comment.