Skip to content

Commit

Permalink
Add assignToLvalue() to extract common part
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Jan 24, 2015
1 parent bd44bb2 commit b4829a9
Showing 1 changed file with 90 additions and 218 deletions.
308 changes: 90 additions & 218 deletions src/interpret.c
Expand Up @@ -3647,91 +3647,24 @@ class Interpreter : public Visitor

assert(result);

Type *t1b = e1->type->toBasetype();
bool wantCopy = (t1b->baseElemOf()->ty == Tstruct);

/* Assignment to a CTFE reference.
*/
if (e1->op == TOKvar)
{
VarExp *ve = (VarExp *)e1;
VarDeclaration *v = ve->var->isVarDeclaration();

oldval = getValue(v);

if (newval->op == TOKstructliteral && oldval)
{
newval = copyLiteral(newval).copy();

assignInPlace(oldval, newval);
}
else if (wantCopy && e->op == TOKassign)
{
// Currently postblit/destructor calls on static array are done
// in the druntime internal functions so they don't appear in AST.
// Therefore interpreter should handle them specially.

assert(oldval);

newval = resolveSlice(newval);
if (CTFEExp::isCantExp(newval))
{
e->error("CTFE internal error: var assignment %s", e->toChars());
result = CTFEExp::cantexp;
return;
}
assert(oldval->op == TOKarrayliteral);
assert(newval->op == TOKarrayliteral);

Expressions *oldelems = ((ArrayLiteralExp *)oldval)->elements;
Expressions *newelems = ((ArrayLiteralExp *)newval)->elements;
assert(oldelems->dim == newelems->dim);

Type *elemtype = oldval->type->nextOf();
for (size_t i = 0; i < newelems->dim; i++)
{
Expression *oldelem = (*oldelems)[i];
Expression *newelem = paintTypeOntoLiteral(elemtype, (*newelems)[i]);
// Bugzilla 9245
if (e->e2->isLvalue())
{
if (Expression *x = evaluatePostblit(istate, newelem))
{
result = x;
return;
}
}
// Bugzilla 13661
if (Expression *x = evaluateDtor(istate, oldelem))
{
result = x;
return;
}
(*oldelems)[i] = newelem;
}
}
else
{
// e1 has its own payload, so we have to create a new literal.
if (wantCopy)
newval = copyLiteral(newval).copy();
if (Expression *ex = assignToLvalue(e, e1, newval))
result = ex;

setValue(v, newval);
return;
}

if (t1b->ty == Tsarray && e->op == TOKconstruct && e->e2->isLvalue())
{
// Bugzilla 9245
if (Expression *x = evaluatePostblit(istate, newval))
{
result = x;
return;
}
}
Expression *assignToLvalue(BinExp *e, Expression *e1, Expression *newval)
{
VarDeclaration *vd = NULL;
Expression **payload;
Expression *oldval;

// Blit assignment should return the newly created value.
if (e->op == TOKblit)
result = newval;
}
if (e1->op == TOKvar)
{
vd = ((VarExp *)e1)->var->isVarDeclaration();
oldval = getValue(vd);
}
else if (e1->op == TOKdotvar)
{
Expand All @@ -3746,8 +3679,7 @@ class Interpreter : public Visitor
if (!sle || !v)
{
e->error("CTFE internal error: dotvar assignment");
result = CTFEExp::cantexp;
return;
return CTFEExp::cantexp;
}

int fieldi = ex->op == TOKstructliteral
Expand All @@ -3756,8 +3688,7 @@ class Interpreter : public Visitor
if (fieldi == -1)
{
e->error("CTFE internal error: cannot find field %s in %s", v->toChars(), ex->toChars());
result = CTFEExp::cantexp;
return;
return CTFEExp::cantexp;
}
assert(0 <= fieldi && fieldi < sle->elements->dim);

Expand All @@ -3777,73 +3708,8 @@ class Interpreter : public Visitor
}
}

oldval = (*sle->elements)[fieldi];

if (newval->op == TOKstructliteral)
{
newval = copyLiteral(newval).copy();

assignInPlace(oldval, newval);
}
else if (wantCopy && e->op == TOKassign)
{
newval = resolveSlice(newval);
if (CTFEExp::isCantExp(newval))
{
e->error("CTFE internal error: dotvar assignment %s", e->toChars());
result = CTFEExp::cantexp;
return;
}
assert(oldval->op == TOKarrayliteral);
assert(newval->op == TOKarrayliteral);

Expressions *oldelems = ((ArrayLiteralExp *)oldval)->elements;
Expressions *newelems = ((ArrayLiteralExp *)newval)->elements;
assert(oldelems->dim == newelems->dim);

Type *elemtype = oldval->type->nextOf();
for (size_t i = 0; i < newelems->dim; i++)
{
Expression *oldelem = (*oldelems)[i];
Expression *newelem = paintTypeOntoLiteral(elemtype, (*newelems)[i]);
if (e->e2->isLvalue())
{
if (Expression *x = evaluatePostblit(istate, newelem))
{
result = x;
return;
}
}
if (Expression *x = evaluateDtor(istate, oldelem))
{
result = x;
return;
}
(*oldelems)[i] = newelem;
}
}
else
{
// e1 has its own payload, so we have to create a new literal.
if (wantCopy)
newval = copyLiteral(newval).copy();

(*sle->elements)[fieldi] = newval;

if (t1b->ty == Tsarray && e->op == TOKconstruct && e->e2->isLvalue())
{
// Bugzilla 9245
if (Expression *x = evaluatePostblit(istate, newval))
{
result = x;
return;
}
}

// Blit assignment should return the newly created value.
if (e->op == TOKblit)
result = newval;
}
payload = &(*sle->elements)[fieldi];
oldval = *payload;
}
else if (e1->op == TOKindex)
{
Expand All @@ -3854,8 +3720,7 @@ class Interpreter : public Visitor
uinteger_t indexToModify;
if (!resolveIndexing(ie, istate, &aggregate, &indexToModify, true))
{
result = CTFEExp::cantexp;
return;
return CTFEExp::cantexp;
}
size_t index = (size_t)indexToModify;

Expand All @@ -3865,8 +3730,7 @@ class Interpreter : public Visitor
if (!existingSE->ownedByCtfe)
{
e->error("cannot modify read-only string literal %s", ie->e1->toChars());
result = CTFEExp::cantexp;
return;
return CTFEExp::cantexp;
}
void *s = existingSE->string;
dinteger_t value = newval->toInteger();
Expand All @@ -3877,90 +3741,98 @@ class Interpreter : public Visitor
case 4: ((utf32_t *)s)[index] = (utf32_t)value; break;
default: assert(0); break;
}
return;
return NULL;
}
if (aggregate->op != TOKarrayliteral)
{
e->error("index assignment %s is not yet supported in CTFE ", e->toChars());
result = CTFEExp::cantexp;
return;
return CTFEExp::cantexp;
}

ArrayLiteralExp *existingAE = (ArrayLiteralExp *)aggregate;

oldval = (*existingAE->elements)[index];

if (newval->op == TOKstructliteral)
{
newval = copyLiteral(newval).copy();
payload = &(*existingAE->elements)[index];
oldval = *payload;
}
else
{
e->error("%s cannot be evaluated at compile time", e->toChars());
return CTFEExp::cantexp;
}

assignInPlace(oldval, newval);
}
else if (wantCopy && e->op == TOKassign)
{
newval = resolveSlice(newval);
if (CTFEExp::isCantExp(newval))
{
e->error("CTFE internal error: index assignment %s", e->toChars());
result = CTFEExp::cantexp;
return;
}
assert(oldval->op == TOKarrayliteral);
assert(newval->op == TOKarrayliteral);
Type *t1b = e1->type->toBasetype();
bool wantCopy = t1b->baseElemOf()->ty == Tstruct;

Expressions *oldelems = ((ArrayLiteralExp *)oldval)->elements;
Expressions *newelems = ((ArrayLiteralExp *)newval)->elements;
assert(oldelems->dim == newelems->dim);
if (newval->op == TOKstructliteral && oldval)
{
newval = copyLiteral(newval).copy();
assignInPlace(oldval, newval);
}
else if (wantCopy && e->op == TOKassign)
{
// Currently postblit/destructor calls on static array are done
// in the druntime internal functions so they don't appear in AST.
// Therefore interpreter should handle them specially.

Type *elemtype = oldval->type->nextOf();
for (size_t i = 0; i < newelems->dim; i++)
{
Expression *oldelem = (*oldelems)[i];
Expression *newelem = paintTypeOntoLiteral(elemtype, (*newelems)[i]);
if (e->e2->isLvalue())
{
if (Expression *x = evaluatePostblit(istate, newelem))
{
result = x;
return;
}
}
if (Expression *x = evaluateDtor(istate, oldelem))
{
result = x;
return;
}
(*oldelems)[i] = newelem;
}
}
else
assert(oldval);
#if 1 // todo: instead we can directly access to each elements of the slice
newval = resolveSlice(newval);
if (CTFEExp::isCantExp(newval))
{
// e1 has its own payload, so we have to create a new literal.
if (wantCopy)
newval = copyLiteral(newval).copy();
e->error("CTFE internal error: assignment %s", e->toChars());
return CTFEExp::cantexp;
}
#endif
assert(oldval->op == TOKarrayliteral);
assert(newval->op == TOKarrayliteral);

(*existingAE->elements)[index] = newval;
Expressions *oldelems = ((ArrayLiteralExp *)oldval)->elements;
Expressions *newelems = ((ArrayLiteralExp *)newval)->elements;
assert(oldelems->dim == newelems->dim);

if (t1b->ty == Tsarray && e->op == TOKconstruct && e->e2->isLvalue())
Type *elemtype = oldval->type->nextOf();
for (size_t i = 0; i < newelems->dim; i++)
{
Expression *oldelem = (*oldelems)[i];
Expression *newelem = paintTypeOntoLiteral(elemtype, (*newelems)[i]);
// Bugzilla 9245
if (e->e2->isLvalue())
{
// Bugzilla 9245
if (Expression *x = evaluatePostblit(istate, newval))
{
result = x;
return;
}
if (Expression *ex = evaluatePostblit(istate, newelem))
return ex;
}

// Blit assignment should return the newly created value.
if (e->op == TOKblit)
result = newval;
// Bugzilla 13661
if (Expression *ex = evaluateDtor(istate, oldelem))
return ex;
(*oldelems)[i] = newelem;
}
}
else
{
e->error("%s cannot be evaluated at compile time", e->toChars());
result = CTFEExp::cantexp;
// e1 has its own payload, so we have to create a new literal.
if (wantCopy)
newval = copyLiteral(newval).copy();

if (t1b->ty == Tsarray && e->op == TOKconstruct && e->e2->isLvalue())
{
// Bugzilla 9245
if (Expression *ex = evaluatePostblit(istate, newval))
return ex;
}

oldval = newval;
}

if (vd)
setValue(vd, oldval);
else
*payload = oldval;

// Blit assignment should return the newly created value.
if (e->op == TOKblit)
return oldval;

return NULL;
}

/*************
Expand Down

0 comments on commit b4829a9

Please sign in to comment.