Mercurial > projects > ldc
diff dmd/init.c @ 336:aaade6ded589 trunk
[svn r357] Merged DMD 1.033
author | lindquist |
---|---|
date | Sat, 12 Jul 2008 19:38:31 +0200 |
parents | 2b72433d5c8c |
children | eeb8b95ea92e |
line wrap: on
line diff
--- a/dmd/init.c Sat Jul 12 17:04:36 2008 +0200 +++ b/dmd/init.c Sat Jul 12 19:38:31 2008 +0200 @@ -1,584 +1,586 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include <stdio.h> -#include <assert.h> - -#include "mars.h" -#include "init.h" -#include "expression.h" -#include "statement.h" -#include "identifier.h" -#include "declaration.h" -#include "aggregate.h" -#include "scope.h" -#include "mtype.h" -#include "hdrgen.h" - -/********************************** Initializer *******************************/ - -Initializer::Initializer(Loc loc) -{ - this->loc = loc; -} - -Initializer *Initializer::syntaxCopy() -{ - return this; -} - -Initializer *Initializer::semantic(Scope *sc, Type *t) -{ - return this; -} - -Type *Initializer::inferType(Scope *sc) -{ - error(loc, "cannot infer type from initializer"); - return Type::terror; -} - -Initializers *Initializer::arraySyntaxCopy(Initializers *ai) -{ Initializers *a = NULL; - - if (ai) - { - a = new Initializers(); - a->setDim(ai->dim); - for (int i = 0; i < a->dim; i++) - { Initializer *e = (Initializer *)ai->data[i]; - - e = e->syntaxCopy(); - a->data[i] = e; - } - } - return a; -} - -char *Initializer::toChars() -{ OutBuffer *buf; - HdrGenState hgs; - - memset(&hgs, 0, sizeof(hgs)); - buf = new OutBuffer(); - toCBuffer(buf, &hgs); - return buf->toChars(); -} - -/********************************** VoidInitializer ***************************/ - -VoidInitializer::VoidInitializer(Loc loc) - : Initializer(loc) -{ - type = NULL; -} - - -Initializer *VoidInitializer::syntaxCopy() -{ - return new VoidInitializer(loc); -} - - -Initializer *VoidInitializer::semantic(Scope *sc, Type *t) -{ - //printf("VoidInitializer::semantic(t = %p)\n", t); - type = t; - return this; -} - - -Expression *VoidInitializer::toExpression() -{ - error(loc, "void initializer has no value"); - return new IntegerExp(0); -} - - -void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("void"); -} - - -/********************************** StructInitializer *************************/ - -StructInitializer::StructInitializer(Loc loc) - : Initializer(loc) -{ - ad = NULL; -} - -Initializer *StructInitializer::syntaxCopy() -{ - StructInitializer *ai = new StructInitializer(loc); - - assert(field.dim == value.dim); - ai->field.setDim(field.dim); - ai->value.setDim(value.dim); - for (int i = 0; i < field.dim; i++) - { - ai->field.data[i] = field.data[i]; - - Initializer *init = (Initializer *)value.data[i]; - init = init->syntaxCopy(); - ai->value.data[i] = init; - } - return ai; -} - -void StructInitializer::addInit(Identifier *field, Initializer *value) -{ - //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value); - this->field.push(field); - this->value.push(value); -} - -Initializer *StructInitializer::semantic(Scope *sc, Type *t) -{ - TypeStruct *ts; - int errors = 0; - - //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); - vars.setDim(field.dim); - t = t->toBasetype(); - if (t->ty == Tstruct) - { unsigned i; - unsigned fieldi = 0; - - ts = (TypeStruct *)t; - ad = ts->sym; - for (i = 0; i < field.dim; i++) - { - Identifier *id = (Identifier *)field.data[i]; - Initializer *val = (Initializer *)value.data[i]; - Dsymbol *s; - VarDeclaration *v; - - if (id == NULL) - { - if (fieldi >= ad->fields.dim) - { error(loc, "too many initializers for %s", ad->toChars()); - continue; - } - else - { - s = (Dsymbol *)ad->fields.data[fieldi]; - } - } - else - { - //s = ad->symtab->lookup(id); - s = ad->search(loc, id, 0); - if (!s) - { - error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); - continue; - } - - // Find out which field index it is - for (fieldi = 0; 1; fieldi++) - { - if (fieldi >= ad->fields.dim) - { - s->error("is not a per-instance initializable field"); - break; - } - if (s == (Dsymbol *)ad->fields.data[fieldi]) - break; - } - } - if (s && (v = s->isVarDeclaration()) != NULL) - { - val = val->semantic(sc, v->type); - value.data[i] = (void *)val; - vars.data[i] = (void *)v; - } - else - { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); - errors = 1; - } - fieldi++; - } - } - else if (t->ty == Tdelegate && value.dim == 0) - { /* Rewrite as empty delegate literal { } - */ - Arguments *arguments = new Arguments; - Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); - FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); - fd->fbody = new CompoundStatement(loc, new Statements()); - fd->endloc = loc; - Expression *e = new FuncExp(loc, fd); - ExpInitializer *ie = new ExpInitializer(loc, e); - return ie->semantic(sc, t); - } - else - { - error(loc, "a struct is not a valid initializer for a %s", t->toChars()); - errors = 1; - } - if (errors) - { - field.setDim(0); - value.setDim(0); - vars.setDim(0); - } - return this; -} - - -/*************************************** - * This works by transforming a struct initializer into - * a struct literal. In the future, the two should be the - * same thing. - */ -Expression *StructInitializer::toExpression() -{ Expression *e; - - //printf("StructInitializer::toExpression() %s\n", toChars()); - if (!ad) // if fwd referenced - { - return NULL; - } - StructDeclaration *sd = ad->isStructDeclaration(); - if (!sd) - return NULL; - Expressions *elements = new Expressions(); - for (size_t i = 0; i < value.dim; i++) - { - if (field.data[i]) - goto Lno; - Initializer *iz = (Initializer *)value.data[i]; - if (!iz) - goto Lno; - Expression *ex = iz->toExpression(); - if (!ex) - goto Lno; - elements->push(ex); - } - e = new StructLiteralExp(loc, sd, elements); - e->type = sd->type; - return e; - -Lno: - delete elements; - //error(loc, "struct initializers as expressions are not allowed"); - return NULL; -} - - -void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - //printf("StructInitializer::toCBuffer()\n"); - buf->writebyte('{'); - for (int i = 0; i < field.dim; i++) - { - if (i > 0) - buf->writebyte(','); - Identifier *id = (Identifier *)field.data[i]; - if (id) - { - buf->writestring(id->toChars()); - buf->writebyte(':'); - } - Initializer *iz = (Initializer *)value.data[i]; - if (iz) - iz->toCBuffer(buf, hgs); - } - buf->writebyte('}'); -} - -/********************************** ArrayInitializer ************************************/ - -ArrayInitializer::ArrayInitializer(Loc loc) - : Initializer(loc) -{ - dim = 0; - type = NULL; - sem = 0; -} - -Initializer *ArrayInitializer::syntaxCopy() -{ - //printf("ArrayInitializer::syntaxCopy()\n"); - - ArrayInitializer *ai = new ArrayInitializer(loc); - - assert(index.dim == value.dim); - ai->index.setDim(index.dim); - ai->value.setDim(value.dim); - for (int i = 0; i < ai->value.dim; i++) - { Expression *e = (Expression *)index.data[i]; - if (e) - e = e->syntaxCopy(); - ai->index.data[i] = e; - - Initializer *init = (Initializer *)value.data[i]; - init = init->syntaxCopy(); - ai->value.data[i] = init; - } - return ai; -} - -void ArrayInitializer::addInit(Expression *index, Initializer *value) -{ - this->index.push(index); - this->value.push(value); - dim = 0; - type = NULL; -} - -Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) -{ unsigned i; - unsigned length; - - //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); - if (sem) // if semantic() already run - return this; - sem = 1; - type = t; - t = t->toBasetype(); - switch (t->ty) - { - case Tpointer: - case Tsarray: - case Tarray: - break; - - default: - error(loc, "cannot use array to initialize %s", type->toChars()); - return this; - } - - length = 0; - for (i = 0; i < index.dim; i++) - { Expression *idx; - Initializer *val; - - idx = (Expression *)index.data[i]; - if (idx) - { idx = idx->semantic(sc); - idx = idx->optimize(WANTvalue | WANTinterpret); - index.data[i] = (void *)idx; - length = idx->toInteger(); - } - - val = (Initializer *)value.data[i]; - val = val->semantic(sc, t->next); - value.data[i] = (void *)val; - length++; - if (length == 0) - error("array dimension overflow"); - if (length > dim) - dim = length; - } - unsigned long amax = 0x80000000; - if ((unsigned long) dim * t->next->size() >= amax) - error(loc, "array dimension %u exceeds max of %llu", dim, amax / t->next->size()); - return this; -} - -/******************************** - * If possible, convert array initializer to array literal. - */ - -Expression *ArrayInitializer::toExpression() -{ Expressions *elements; - Expression *e; - - //printf("ArrayInitializer::toExpression()\n"); - //static int i; if (++i == 2) halt(); - elements = new Expressions(); - for (size_t i = 0; i < value.dim; i++) - { - if (index.data[i]) - goto Lno; - Initializer *iz = (Initializer *)value.data[i]; - if (!iz) - goto Lno; - Expression *ex = iz->toExpression(); - if (!ex) - goto Lno; - elements->push(ex); - } - e = new ArrayLiteralExp(loc, elements); - e->type = type; - return e; - -Lno: - delete elements; - error(loc, "array initializers as expressions are not allowed"); - return NULL; -} - - -/******************************** - * If possible, convert array initializer to associative array initializer. - */ - -Initializer *ArrayInitializer::toAssocArrayInitializer() -{ Expressions *keys; - Expressions *values; - Expression *e; - - //printf("ArrayInitializer::toAssocArrayInitializer()\n"); - //static int i; if (++i == 2) halt(); - keys = new Expressions(); - keys->setDim(value.dim); - values = new Expressions(); - values->setDim(value.dim); - - for (size_t i = 0; i < value.dim; i++) - { - e = (Expression *)index.data[i]; - if (!e) - goto Lno; - keys->data[i] = (void *)e; - - Initializer *iz = (Initializer *)value.data[i]; - if (!iz) - goto Lno; - e = iz->toExpression(); - if (!e) - goto Lno; - values->data[i] = (void *)e; - } - e = new AssocArrayLiteralExp(loc, keys, values); - return new ExpInitializer(loc, e); - -Lno: - delete keys; - delete values; - error(loc, "not an associative array initializer"); - return this; -} - - -Type *ArrayInitializer::inferType(Scope *sc) -{ - for (size_t i = 0; i < value.dim; i++) - { - if (index.data[i]) - goto Lno; - } - if (value.dim) - { - Initializer *iz = (Initializer *)value.data[0]; - if (iz) - { Type *t = iz->inferType(sc); - t = new TypeSArray(t, new IntegerExp(value.dim)); - t = t->semantic(loc, sc); - return t; - } - } - -Lno: - error(loc, "cannot infer type from this array initializer"); - return Type::terror; -} - - -void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writebyte('['); - for (int i = 0; i < index.dim; i++) - { - if (i > 0) - buf->writebyte(','); - Expression *ex = (Expression *)index.data[i]; - if (ex) - { - ex->toCBuffer(buf, hgs); - buf->writebyte(':'); - } - Initializer *iz = (Initializer *)value.data[i]; - if (iz) - iz->toCBuffer(buf, hgs); - } - buf->writebyte(']'); -} - - -/********************************** ExpInitializer ************************************/ - -ExpInitializer::ExpInitializer(Loc loc, Expression *exp) - : Initializer(loc) -{ - this->exp = exp; -} - -Initializer *ExpInitializer::syntaxCopy() -{ - return new ExpInitializer(loc, exp->syntaxCopy()); -} - -Initializer *ExpInitializer::semantic(Scope *sc, Type *t) -{ - //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); - exp = exp->semantic(sc); - Type *tb = t->toBasetype(); - - /* Look for case of initializing a static array with a too-short - * string literal, such as: - * char[5] foo = "abc"; - * Allow this by doing an explicit cast, which will lengthen the string - * literal. - */ - if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray) - { StringExp *se = (StringExp *)exp; - - if (!se->committed && se->type->ty == Tsarray && - ((TypeSArray *)se->type)->dim->toInteger() < - ((TypeSArray *)t)->dim->toInteger()) - { - exp = se->castTo(sc, t); - goto L1; - } - } - - // Look for the case of statically initializing an array - // with a single member. - if (tb->ty == Tsarray && - !tb->next->equals(exp->type->toBasetype()->next) && - exp->implicitConvTo(tb->next) - ) - { - t = tb->next; - } - - exp = exp->implicitCastTo(sc, t); -L1: - exp = exp->optimize(WANTvalue | WANTinterpret); - //printf("-ExpInitializer::semantic(): "); exp->print(); - return this; -} - -Type *ExpInitializer::inferType(Scope *sc) -{ - //printf("ExpInitializer::inferType() %s\n", toChars()); - exp = exp->semantic(sc); - exp = resolveProperties(sc, exp); - return exp->type; -} - -Expression *ExpInitializer::toExpression() -{ - return exp; -} - - -void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - exp->toCBuffer(buf, hgs); -} - - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include <stdio.h> +#include <assert.h> + +#include "mars.h" +#include "init.h" +#include "expression.h" +#include "statement.h" +#include "identifier.h" +#include "declaration.h" +#include "aggregate.h" +#include "scope.h" +#include "mtype.h" +#include "hdrgen.h" + +/********************************** Initializer *******************************/ + +Initializer::Initializer(Loc loc) +{ + this->loc = loc; +} + +Initializer *Initializer::syntaxCopy() +{ + return this; +} + +Initializer *Initializer::semantic(Scope *sc, Type *t) +{ + return this; +} + +Type *Initializer::inferType(Scope *sc) +{ + error(loc, "cannot infer type from initializer"); + return Type::terror; +} + +Initializers *Initializer::arraySyntaxCopy(Initializers *ai) +{ Initializers *a = NULL; + + if (ai) + { + a = new Initializers(); + a->setDim(ai->dim); + for (int i = 0; i < a->dim; i++) + { Initializer *e = (Initializer *)ai->data[i]; + + e = e->syntaxCopy(); + a->data[i] = e; + } + } + return a; +} + +char *Initializer::toChars() +{ OutBuffer *buf; + HdrGenState hgs; + + memset(&hgs, 0, sizeof(hgs)); + buf = new OutBuffer(); + toCBuffer(buf, &hgs); + return buf->toChars(); +} + +/********************************** VoidInitializer ***************************/ + +VoidInitializer::VoidInitializer(Loc loc) + : Initializer(loc) +{ + type = NULL; +} + + +Initializer *VoidInitializer::syntaxCopy() +{ + return new VoidInitializer(loc); +} + + +Initializer *VoidInitializer::semantic(Scope *sc, Type *t) +{ + //printf("VoidInitializer::semantic(t = %p)\n", t); + type = t; + return this; +} + + +Expression *VoidInitializer::toExpression() +{ + error(loc, "void initializer has no value"); + return new IntegerExp(0); +} + + +void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("void"); +} + + +/********************************** StructInitializer *************************/ + +StructInitializer::StructInitializer(Loc loc) + : Initializer(loc) +{ + ad = NULL; +} + +Initializer *StructInitializer::syntaxCopy() +{ + StructInitializer *ai = new StructInitializer(loc); + + assert(field.dim == value.dim); + ai->field.setDim(field.dim); + ai->value.setDim(value.dim); + for (int i = 0; i < field.dim; i++) + { + ai->field.data[i] = field.data[i]; + + Initializer *init = (Initializer *)value.data[i]; + init = init->syntaxCopy(); + ai->value.data[i] = init; + } + return ai; +} + +void StructInitializer::addInit(Identifier *field, Initializer *value) +{ + //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value); + this->field.push(field); + this->value.push(value); +} + +Initializer *StructInitializer::semantic(Scope *sc, Type *t) +{ + TypeStruct *ts; + int errors = 0; + + //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); + vars.setDim(field.dim); + t = t->toBasetype(); + if (t->ty == Tstruct) + { unsigned i; + unsigned fieldi = 0; + + ts = (TypeStruct *)t; + ad = ts->sym; + for (i = 0; i < field.dim; i++) + { + Identifier *id = (Identifier *)field.data[i]; + Initializer *val = (Initializer *)value.data[i]; + Dsymbol *s; + VarDeclaration *v; + + if (id == NULL) + { + if (fieldi >= ad->fields.dim) + { error(loc, "too many initializers for %s", ad->toChars()); + field.remove(i); + i--; + continue; + } + else + { + s = (Dsymbol *)ad->fields.data[fieldi]; + } + } + else + { + //s = ad->symtab->lookup(id); + s = ad->search(loc, id, 0); + if (!s) + { + error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); + continue; + } + + // Find out which field index it is + for (fieldi = 0; 1; fieldi++) + { + if (fieldi >= ad->fields.dim) + { + s->error("is not a per-instance initializable field"); + break; + } + if (s == (Dsymbol *)ad->fields.data[fieldi]) + break; + } + } + if (s && (v = s->isVarDeclaration()) != NULL) + { + val = val->semantic(sc, v->type); + value.data[i] = (void *)val; + vars.data[i] = (void *)v; + } + else + { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); + errors = 1; + } + fieldi++; + } + } + else if (t->ty == Tdelegate && value.dim == 0) + { /* Rewrite as empty delegate literal { } + */ + Arguments *arguments = new Arguments; + Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); + FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); + fd->fbody = new CompoundStatement(loc, new Statements()); + fd->endloc = loc; + Expression *e = new FuncExp(loc, fd); + ExpInitializer *ie = new ExpInitializer(loc, e); + return ie->semantic(sc, t); + } + else + { + error(loc, "a struct is not a valid initializer for a %s", t->toChars()); + errors = 1; + } + if (errors) + { + field.setDim(0); + value.setDim(0); + vars.setDim(0); + } + return this; +} + + +/*************************************** + * This works by transforming a struct initializer into + * a struct literal. In the future, the two should be the + * same thing. + */ +Expression *StructInitializer::toExpression() +{ Expression *e; + + //printf("StructInitializer::toExpression() %s\n", toChars()); + if (!ad) // if fwd referenced + { + return NULL; + } + StructDeclaration *sd = ad->isStructDeclaration(); + if (!sd) + return NULL; + Expressions *elements = new Expressions(); + for (size_t i = 0; i < value.dim; i++) + { + if (field.data[i]) + goto Lno; + Initializer *iz = (Initializer *)value.data[i]; + if (!iz) + goto Lno; + Expression *ex = iz->toExpression(); + if (!ex) + goto Lno; + elements->push(ex); + } + e = new StructLiteralExp(loc, sd, elements); + e->type = sd->type; + return e; + +Lno: + delete elements; + //error(loc, "struct initializers as expressions are not allowed"); + return NULL; +} + + +void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + //printf("StructInitializer::toCBuffer()\n"); + buf->writebyte('{'); + for (int i = 0; i < field.dim; i++) + { + if (i > 0) + buf->writebyte(','); + Identifier *id = (Identifier *)field.data[i]; + if (id) + { + buf->writestring(id->toChars()); + buf->writebyte(':'); + } + Initializer *iz = (Initializer *)value.data[i]; + if (iz) + iz->toCBuffer(buf, hgs); + } + buf->writebyte('}'); +} + +/********************************** ArrayInitializer ************************************/ + +ArrayInitializer::ArrayInitializer(Loc loc) + : Initializer(loc) +{ + dim = 0; + type = NULL; + sem = 0; +} + +Initializer *ArrayInitializer::syntaxCopy() +{ + //printf("ArrayInitializer::syntaxCopy()\n"); + + ArrayInitializer *ai = new ArrayInitializer(loc); + + assert(index.dim == value.dim); + ai->index.setDim(index.dim); + ai->value.setDim(value.dim); + for (int i = 0; i < ai->value.dim; i++) + { Expression *e = (Expression *)index.data[i]; + if (e) + e = e->syntaxCopy(); + ai->index.data[i] = e; + + Initializer *init = (Initializer *)value.data[i]; + init = init->syntaxCopy(); + ai->value.data[i] = init; + } + return ai; +} + +void ArrayInitializer::addInit(Expression *index, Initializer *value) +{ + this->index.push(index); + this->value.push(value); + dim = 0; + type = NULL; +} + +Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) +{ unsigned i; + unsigned length; + + //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); + if (sem) // if semantic() already run + return this; + sem = 1; + type = t; + t = t->toBasetype(); + switch (t->ty) + { + case Tpointer: + case Tsarray: + case Tarray: + break; + + default: + error(loc, "cannot use array to initialize %s", type->toChars()); + return this; + } + + length = 0; + for (i = 0; i < index.dim; i++) + { Expression *idx; + Initializer *val; + + idx = (Expression *)index.data[i]; + if (idx) + { idx = idx->semantic(sc); + idx = idx->optimize(WANTvalue | WANTinterpret); + index.data[i] = (void *)idx; + length = idx->toInteger(); + } + + val = (Initializer *)value.data[i]; + val = val->semantic(sc, t->next); + value.data[i] = (void *)val; + length++; + if (length == 0) + error(loc, "array dimension overflow"); + if (length > dim) + dim = length; + } + unsigned long amax = 0x80000000; + if ((unsigned long) dim * t->next->size() >= amax) + error(loc, "array dimension %u exceeds max of %llu", dim, amax / t->next->size()); + return this; +} + +/******************************** + * If possible, convert array initializer to array literal. + */ + +Expression *ArrayInitializer::toExpression() +{ Expressions *elements; + Expression *e; + + //printf("ArrayInitializer::toExpression()\n"); + //static int i; if (++i == 2) halt(); + elements = new Expressions(); + for (size_t i = 0; i < value.dim; i++) + { + if (index.data[i]) + goto Lno; + Initializer *iz = (Initializer *)value.data[i]; + if (!iz) + goto Lno; + Expression *ex = iz->toExpression(); + if (!ex) + goto Lno; + elements->push(ex); + } + e = new ArrayLiteralExp(loc, elements); + e->type = type; + return e; + +Lno: + delete elements; + error(loc, "array initializers as expressions are not allowed"); + return NULL; +} + + +/******************************** + * If possible, convert array initializer to associative array initializer. + */ + +Initializer *ArrayInitializer::toAssocArrayInitializer() +{ Expressions *keys; + Expressions *values; + Expression *e; + + //printf("ArrayInitializer::toAssocArrayInitializer()\n"); + //static int i; if (++i == 2) halt(); + keys = new Expressions(); + keys->setDim(value.dim); + values = new Expressions(); + values->setDim(value.dim); + + for (size_t i = 0; i < value.dim; i++) + { + e = (Expression *)index.data[i]; + if (!e) + goto Lno; + keys->data[i] = (void *)e; + + Initializer *iz = (Initializer *)value.data[i]; + if (!iz) + goto Lno; + e = iz->toExpression(); + if (!e) + goto Lno; + values->data[i] = (void *)e; + } + e = new AssocArrayLiteralExp(loc, keys, values); + return new ExpInitializer(loc, e); + +Lno: + delete keys; + delete values; + error(loc, "not an associative array initializer"); + return this; +} + + +Type *ArrayInitializer::inferType(Scope *sc) +{ + for (size_t i = 0; i < value.dim; i++) + { + if (index.data[i]) + goto Lno; + } + if (value.dim) + { + Initializer *iz = (Initializer *)value.data[0]; + if (iz) + { Type *t = iz->inferType(sc); + t = new TypeSArray(t, new IntegerExp(value.dim)); + t = t->semantic(loc, sc); + return t; + } + } + +Lno: + error(loc, "cannot infer type from this array initializer"); + return Type::terror; +} + + +void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writebyte('['); + for (int i = 0; i < index.dim; i++) + { + if (i > 0) + buf->writebyte(','); + Expression *ex = (Expression *)index.data[i]; + if (ex) + { + ex->toCBuffer(buf, hgs); + buf->writebyte(':'); + } + Initializer *iz = (Initializer *)value.data[i]; + if (iz) + iz->toCBuffer(buf, hgs); + } + buf->writebyte(']'); +} + + +/********************************** ExpInitializer ************************************/ + +ExpInitializer::ExpInitializer(Loc loc, Expression *exp) + : Initializer(loc) +{ + this->exp = exp; +} + +Initializer *ExpInitializer::syntaxCopy() +{ + return new ExpInitializer(loc, exp->syntaxCopy()); +} + +Initializer *ExpInitializer::semantic(Scope *sc, Type *t) +{ + //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); + exp = exp->semantic(sc); + Type *tb = t->toBasetype(); + + /* Look for case of initializing a static array with a too-short + * string literal, such as: + * char[5] foo = "abc"; + * Allow this by doing an explicit cast, which will lengthen the string + * literal. + */ + if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray) + { StringExp *se = (StringExp *)exp; + + if (!se->committed && se->type->ty == Tsarray && + ((TypeSArray *)se->type)->dim->toInteger() < + ((TypeSArray *)t)->dim->toInteger()) + { + exp = se->castTo(sc, t); + goto L1; + } + } + + // Look for the case of statically initializing an array + // with a single member. + if (tb->ty == Tsarray && + !tb->next->equals(exp->type->toBasetype()->next) && + exp->implicitConvTo(tb->next) + ) + { + t = tb->next; + } + + exp = exp->implicitCastTo(sc, t); +L1: + exp = exp->optimize(WANTvalue | WANTinterpret); + //printf("-ExpInitializer::semantic(): "); exp->print(); + return this; +} + +Type *ExpInitializer::inferType(Scope *sc) +{ + //printf("ExpInitializer::inferType() %s\n", toChars()); + exp = exp->semantic(sc); + exp = resolveProperties(sc, exp); + return exp->type; +} + +Expression *ExpInitializer::toExpression() +{ + return exp; +} + + +void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + exp->toCBuffer(buf, hgs); +} + + +