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; }
static void TestClass() { Initializer i; i.check(); }
Expression *ArrayInitializer::toExpression() { Expressions *elements; //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); //static int i; if (++i == 2) halt(); size_t edim; Type *t = NULL; if (type) { if (type == Type::terror) return new ErrorExp(); t = type->toBasetype(); switch (t->ty) { case Tsarray: edim = ((TypeSArray *)t)->dim->toInteger(); break; case Tpointer: case Tarray: edim = dim; break; default: assert(0); } } else { edim = value.dim; for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) j = index[i]->toInteger(); if (j >= edim) edim = j + 1; } } elements = new Expressions(); elements->setDim(edim); elements->zero(); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) j = (index[i])->toInteger(); assert(j < edim); Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) { goto Lno; } (*elements)[j] = ex; } /* Fill in any missing elements with the default initializer */ { Expression *init = NULL; for (size_t i = 0; i < edim; i++) { if (!(*elements)[i]) { if (!type) goto Lno; if (!init) init = ((TypeNext *)t)->next->defaultInit(); (*elements)[i] = init; } } Expression *e = new ArrayLiteralExp(loc, elements); e->type = type; return e; } Lno: return NULL; }
Expression *StructInitializer::fill(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("StructInitializer::fill(sc = %p, '%s')\n", sc, toChars()); assert(t->ty == Tstruct); StructDeclaration *sd = ((TypeStruct *)t)->sym; sd->size(loc); if (sd->sizeok != SIZEOKdone) return new ErrorExp(); size_t nfields = sd->fields.dim - sd->isNested(); Expressions *elements = new Expressions(); elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) (*elements)[i] = NULL; // Run semantic for explicitly given initializers bool errors = false; for (size_t fieldi = 0, i = 0; i < field.dim; i++) { if (Identifier *id = field[i]) { Dsymbol *s = sd->search(loc, id, 0); if (!s) { s = sd->search_correct(id); if (s) error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", id->toChars(), sd->toChars(), s->kind(), s->toChars()); else error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); return new ErrorExp(); } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { error(loc, "%s.%s is not a per-instance initializable field", sd->toChars(), s->toChars()); return new ErrorExp(); } if (s == sd->fields[fieldi]) break; } } else if (fieldi >= nfields) { error(loc, "too many initializers for %s", sd->toChars()); return new ErrorExp(); } VarDeclaration *vd = sd->fields[fieldi]; if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", vd->toChars()); errors = true; continue; } for (size_t j = 0; j < nfields; j++) { VarDeclaration *v2 = sd->fields[j]; bool overlap = (vd->offset < v2->offset + v2->type->size() && v2->offset < vd->offset + vd->type->size()); if (overlap && (*elements)[j]) { error(loc, "overlapping initialization for field %s and %s", v2->toChars(), vd->toChars()); errors = true; continue; } } assert(sc); Initializer *iz = value[i]; iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret); Expression *ex = iz->toExpression(); if (ex->op == TOKerror) { errors = true; continue; } value[i] = iz; (*elements)[fieldi] = ex; ++fieldi; } if (errors) return new ErrorExp(); // Fill in missing any elements with default initializers for (size_t i = 0; i < elements->dim; i++) { if ((*elements)[i]) continue; VarDeclaration *vd = sd->fields[i]; VarDeclaration *vx = vd; if (vd->init && vd->init->isVoidInitializer()) vx = NULL; // Find overlapped fields with the hole [vd->offset .. vd->offset->size()]. size_t fieldi = i; for (size_t j = 0; j < nfields; j++) { if (i == j) continue; VarDeclaration *v2 = sd->fields[j]; if (v2->init && v2->init->isVoidInitializer()) continue; bool overlap = (vd->offset < v2->offset + v2->type->size() && v2->offset < vd->offset + vd->type->size()); if (!overlap) continue; if ((*elements)[j]) { vx = NULL; break; } #if 1 /* Prefer first found non-void-initialized field * union U { int a; int b = 2; } * U u; // Error: overlapping initialization for field a and b */ if (!vx) vx = v2, fieldi = j; else if (v2->init) { error(loc, "overlapping initialization for field %s and %s", v2->toChars(), vd->toChars()); } #else // fix Bugzilla 1432 /* Prefer explicitly initialized field * union U { int a; int b = 2; } * U u; // OK (u.b == 2) */ if (!vx || !vx->init && v2->init) vx = v2, fieldi = j; else if (vx->init && v2->init) { error(loc, "overlapping default initialization for field %s and %s", v2->toChars(), vd->toChars()); } else assert(vx->init || !vx->init && !v2->init); #endif } if (vx) { if (vx->init) { assert(!vx->init->isVoidInitializer()); if (vx->scope) { // Do deferred semantic analysis Initializer *i2 = vx->init->syntaxCopy(); i2 = i2->semantic(vx->scope, vx->type, INITinterpret); (*elements)[fieldi] = i2->toExpression(); if (!global.gag) { vx->scope = NULL; vx->init = i2; // save result } } else (*elements)[fieldi] = vx->init->toExpression(); } else (*elements)[fieldi] = vx->type->defaultInit(); } } for (size_t i = 0; i < elements->dim; i++) { Expression *e = (*elements)[i]; if (e && e->op == TOKerror) return e; } Expression *e = new StructLiteralExp(loc, sd, elements, t); if (sc) e = e->semantic(sc); else e->type = sd->type; // from glue layer return e; }
dt_t *ArrayInitializer::toDtBit() { #if DMDV1 unsigned size; unsigned length; unsigned tadim; dt_t *d; dt_t **pdtend; Type *tb = type->toBasetype(); //printf("ArrayInitializer::toDtBit('%s')\n", toChars()); Bits databits; Bits initbits; if (tb->ty == Tsarray) { /* The 'dim' for ArrayInitializer is only the maximum dimension * seen in the initializer, not the type. So, for static arrays, * use instead the dimension of the type in order * to get the whole thing. */ dinteger_t value = ((TypeSArray*)tb)->dim->toInteger(); tadim = value; assert(tadim == value); // truncation overflow should already be checked databits.resize(tadim); initbits.resize(tadim); } else { databits.resize(dim); initbits.resize(dim); } /* The default initializer may be something other than zero. */ if (tb->next->defaultInit()->toInteger()) databits.set(); size = sizeof(databits.data[0]); length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; Expression *eval; idx = (Expression *)index.data[i]; if (idx) { dinteger_t value; value = idx->toInteger(); length = value; if (length != value) { error(loc, "index overflow %llu", value); length = 0; } } assert(length < dim); val = (Initializer *)value.data[i]; eval = val->toExpression(); if (initbits.test(length)) error(loc, "duplicate initializations for index %d", length); initbits.set(length); if (eval->toInteger()) // any non-zero value is boolean 'true' databits.set(length); else databits.clear(length); // boolean 'false' length++; } d = NULL; #ifdef IN_GCC pdtend = dtnbits(&d, databits.allocdim * size, (char *)databits.data, sizeof(databits.data[0])); #else pdtend = dtnbytes(&d, databits.allocdim * size, (char *)databits.data); #endif switch (tb->ty) { case Tsarray: { if (dim > tadim) { error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } else { tadim = (tadim + 31) / 32; if (databits.allocdim < tadim) pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim)); // pad out end of array } break; } case Tpointer: case Tarray: // Create symbol, and then refer to it Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); break; default: assert(0); } return d; #else return NULL; #endif }
/*************************************** * 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; size_t offset; //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(); size_t nfields = ad->fields.dim; #if DMDV2 if (sd->isnested) nfields--; #endif elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) { (*elements)[i] = NULL; } unsigned fieldi = 0; for (size_t i = 0; i < value.dim; i++) { Identifier *id = field[i]; if (id) { Dsymbol * s = ad->search(loc, id, 0); if (!s) { error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); goto Lno; } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { s->error("is not a per-instance initializable field"); goto Lno; } if (s == ad->fields[fieldi]) break; } } else if (fieldi >= nfields) { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; } Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", ad->fields[fieldi]->toChars()); goto Lno; } (*elements)[fieldi] = ex; ++fieldi; } // Now, fill in any missing elements with default initializers. // We also need to validate any anonymous unions offset = 0; for (size_t i = 0; i < elements->dim; ) { VarDeclaration * vd = ad->fields[i]->isVarDeclaration(); //printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset); if (vd->offset < offset) { // Only the first field of a union can have an initializer if ((*elements)[i]) goto Lno; } else { if (!(*elements)[i]) { // Default initialize if (vd->init) (*elements)[i] = vd->init->toExpression(); else (*elements)[i] = vd->type->defaultInit(); } } offset = vd->offset + vd->type->size(); i++; #if 0 int unionSize = ad->numFieldsInUnion(i); if (unionSize == 1) { // Not a union -- default initialize if missing if (!(*elements)[i]) (*elements)[i] = vd->type->defaultInit(); } else { // anonymous union -- check for errors int found = -1; // index of the first field with an initializer for (size_t j = i; j < i + unionSize; ++j) { if (!(*elements)[j]) continue; if (found >= 0) { VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration(); VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration(); error(loc, "%s cannot have initializers for fields %s and %s in same union", ad->toChars(), v1->toChars(), v->toChars()); goto Lno; } found = j; } if (found == -1) { error(loc, "no initializer for union that contains field %s", vd->toChars()); goto Lno; } } i += unionSize; #endif } e = new StructLiteralExp(loc, sd, elements); e->type = sd->type; return e; Lno: delete elements; return NULL; }
Expression *ArrayInitializer::toExpression(Type *tx) { //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); //static int i; if (++i == 2) halt(); Expressions *elements; size_t edim; Type *t = NULL; if (type) { if (type == Type::terror) return new ErrorExp(); t = type->toBasetype(); switch (t->ty) { case Tsarray: edim = (size_t)((TypeSArray *)t)->dim->toInteger(); break; case Tvector: t = ((TypeVector *)t)->basetype; edim = (size_t)((TypeSArray *)t)->dim->toInteger(); break; case Tpointer: case Tarray: edim = dim; break; default: assert(0); } } else { edim = value.dim; for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) { if (index[i]->op == TOKint64) j = (size_t)index[i]->toInteger(); else goto Lno; } if (j >= edim) edim = j + 1; } } elements = new Expressions(); elements->setDim(edim); elements->zero(); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) j = (size_t)(index[i])->toInteger(); assert(j < edim); Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) { goto Lno; } (*elements)[j] = ex; } /* Fill in any missing elements with the default initializer */ { Expression *init = NULL; for (size_t i = 0; i < edim; i++) { if (!(*elements)[i]) { if (!type) goto Lno; if (!init) init = ((TypeNext *)t)->next->defaultInit(); (*elements)[i] = init; } } /* Expand any static array initializers that are a single expression * into an array of them */ if (t) { Type *tn = t->nextOf()->toBasetype(); if (tn->ty == Tsarray) { size_t dim = ((TypeSArray *)tn)->dim->toInteger(); Type *te = tn->nextOf()->toBasetype(); for (size_t i = 0; i < elements->dim; i++) { Expression *e = (*elements)[i]; if (te->equals(e->type)) { Expressions *elements2 = new Expressions(); elements2->setDim(dim); for (size_t j = 0; j < dim; j++) (*elements2)[j] = e; e = new ArrayLiteralExp(e->loc, elements2); e->type = tn; (*elements)[i] = e; } } } } /* If any elements are errors, then the whole thing is an error */ for (size_t i = 0; i < edim; i++) { Expression *e = (*elements)[i]; if (e->op == TOKerror) return e; } Expression *e = new ArrayLiteralExp(loc, elements); e->type = type; return e; } Lno: return NULL; }
dt_t *StructInitializer::toDt() { Array dts; dt_t *dt; dt_t *d; dt_t **pdtend; unsigned offset; //printf("StructInitializer::toDt('%s')\n", toChars()); dts.setDim(ad->fields.dim); dts.zero(); for (size_t i = 0; i < vars.dim; i++) { VarDeclaration *v = (VarDeclaration *)vars.data[i]; Initializer *val = (Initializer *)value.data[i]; //printf("vars[%d] = %s\n", i, v->toChars()); for (size_t j = 0; 1; j++) { assert(j < dts.dim); //printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad->fields.data[j])->toChars()); if ((VarDeclaration *)ad->fields.data[j] == v) { if (dts.data[j]) error(loc, "field %s of %s already initialized", v->toChars(), ad->toChars()); dts.data[j] = (void *)val->toDt(); break; } } } dt = NULL; pdtend = &dt; offset = 0; for (size_t j = 0; j < dts.dim; j++) { VarDeclaration *v = (VarDeclaration *)ad->fields.data[j]; d = (dt_t *)dts.data[j]; if (!d) { // An instance specific initializer was not provided. // Look to see if there's a default initializer from the // struct definition if (v->init) { d = v->init->toDt(); } else if (v->offset >= offset) { unsigned k; unsigned offset2 = v->offset + v->type->size(); // Make sure this field does not overlap any explicitly // initialized field. for (k = j + 1; 1; k++) { if (k == dts.dim) // didn't find any overlap { v->type->toDt(&d); break; } VarDeclaration *v2 = (VarDeclaration *)ad->fields.data[k]; if (v2->offset < offset2 && dts.data[k]) break; // overlap } } } if (d) { if (v->offset < offset) error(loc, "duplicate union initialization for %s", v->toChars()); else { size_t sz = dt_size(d); size_t vsz = v->type->size(); size_t voffset = v->offset; if (sz > vsz) { assert(v->type->ty == Tsarray && vsz == 0); error(loc, "zero length array %s has non-zero length initializer", v->toChars()); } unsigned dim = 1; for (Type *vt = v->type->toBasetype(); vt->ty == Tsarray; vt = vt->next->toBasetype()) { TypeSArray *tsa = (TypeSArray *)vt; dim *= tsa->dim->toInteger(); } //printf("sz = %d, dim = %d, vsz = %d\n", sz, dim, vsz); assert(sz == vsz || sz * dim <= vsz); for (size_t i = 0; i < dim; i++) { if (offset < voffset) pdtend = dtnzeros(pdtend, voffset - offset); if (!d) { if (v->init) d = v->init->toDt(); else v->type->toDt(&d); } pdtend = dtcat(pdtend, d); d = NULL; offset = voffset + sz; voffset += vsz / dim; if (sz == vsz) break; } } } } if (offset < ad->structsize) dtnzeros(pdtend, ad->structsize - offset); #ifdef IN_GCC dt_t * cdt = NULL; dtcontainer(&cdt, ad->type, dt); dt = cdt; #endif return dt; }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); Type *tn = tb->nextOf()->toBasetype(); Dts dts; unsigned size; unsigned length; unsigned i; dt_t *dt; dt_t *d; dt_t **pdtend; //printf("\tdim = %d\n", dim); dts.setDim(dim); dts.zero(); size = tn->size(); length = 0; for (i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = index.tdata()[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = value.tdata()[i]; dt = val->toDt(); if (dts.tdata()[length]) error(loc, "duplicate initializations for index %d", length); dts.tdata()[length] = dt; length++; } Expression *edefault = tb->nextOf()->defaultInit(); unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } d = NULL; pdtend = &d; for (i = 0; i < dim; i++) { dt = dts.tdata()[i]; if (dt) pdtend = dtcat(pdtend, dt); else { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } switch (tb->ty) { case Tsarray: { unsigned tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { if (edefault->isBool(FALSE)) // pad out end of array pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (i = dim; i < tadim; i++) { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } } else if (dim > tadim) { #ifdef DEBUG printf("1: "); #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } break; } case Tpointer: case Tarray: // Create symbol, and then refer to it Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); break; default: assert(0); } return d; }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) { unsigned i; unsigned length; const unsigned amax = 0x80000000; //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()); goto Lerr; } length = 0; for (i = 0; i < index.dim; i++) { Expression *idx = index.tdata()[i]; if (idx) { idx = idx->semantic(sc); idx = idx->optimize(WANTvalue | WANTinterpret); index.tdata()[i] = idx; length = idx->toInteger(); } Initializer *val = value.tdata()[i]; val = val->semantic(sc, t->nextOf(), needInterpret); value.tdata()[i] = val; length++; if (length == 0) { error(loc, "array dimension overflow"); goto Lerr; } if (length > dim) dim = length; } if (t->ty == Tsarray) { dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { error(loc, "array initializer has %u elements, but array length is %jd", dim, edim); goto Lerr; } } if ((unsigned long) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size()); goto Lerr; } return this; Lerr: return new ExpInitializer(loc, new ErrorExp()); }
/*************************************** * 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(); elements->setDim(ad->fields.dim); for (int i = 0; i < elements->dim; i++) { elements->data[i] = NULL; } unsigned fieldi = 0; for (int i = 0; i < value.dim; i++) { Identifier *id = (Identifier *)field.data[i]; if (id) { Dsymbol * s = ad->search(loc, id, 0); if (!s) { error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); goto Lno; } // 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"); goto Lno; } if (s == (Dsymbol *)ad->fields.data[fieldi]) break; } } else if (fieldi >= ad->fields.dim) { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; } Initializer *iz = (Initializer *)value.data[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; if (elements->data[fieldi]) { error(loc, "duplicate initializer for field '%s'", ((Dsymbol *)ad->fields.data[fieldi])->toChars()); goto Lno; } elements->data[fieldi] = ex; ++fieldi; } // Now, fill in any missing elements with default initializers. // We also need to validate any anonymous unions for (int i = 0; i < elements->dim; ) { VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration(); int unionSize = ad->numFieldsInUnion(i); if (unionSize == 1) { // Not a union -- default initialize if missing if (!elements->data[i]) elements->data[i] = vd->type->defaultInit(); } else { // anonymous union -- check for errors int found = -1; // index of the first field with an initializer for (int j = i; j < i + unionSize; ++j) { if (!elements->data[j]) continue; if (found >= 0) { VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration(); VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration(); error(loc, "%s cannot have initializers for fields %s and %s in same union", ad->toChars(), v1->toChars(), v->toChars()); goto Lno; } found = j; } if (found == -1) { error(loc, "no initializer for union that contains field %s", vd->toChars()); goto Lno; } } i += unionSize; } e = new StructLiteralExp(loc, sd, elements); e->type = sd->type; return e; Lno: delete elements; return NULL; }
/** * Build an abstract type. * @param name Type name (full name path with namespaces). * @param base Base type for a class. */ AbstractType::AbstractType(CString name, AbstractType *base) : elm::AbstractClass(name, base) { initializer.record(this); }
namespace elm { namespace serial2 { /** * Storage of all available classes. */ static HashTable<CString, AbstractType *> types; /** * Initializer hook */ static Initializer<AbstractType> initializer; /** * @class AbstractType * Objects representing a type in the serialization module. * @ingroup serial */ /** * Build an abstract type. * @param name Type name (full name path with namespaces). * @param base Base type for a class. */ AbstractType::AbstractType(CString name, AbstractType *base) : elm::AbstractClass(name, base) { initializer.record(this); } /** * For internal use only. */ void AbstractType::initialize(void) { types.add(name(), this); } /** * Find a type by its name. * @param name Type name. * @return Found type or NULL. */ AbstractType *AbstractType::getType(CString name) { return types.get(name, 0); } /** */ class VoidType: public AbstractType { public: VoidType(void): AbstractType("<void>") { } virtual void *instantiate(void) { return 0; } virtual void unserialize(Unserializer& unserializer, void *object) { } virtual void serialize(Serializer& serializer, const void *object) { } }; static VoidType void_type; /** * Void type representation. */ AbstractType& AbstractType::T_VOID = void_type; } } // elm::serial2
void ParticleSystem::init(Initializer &I){ cout << "init particle system" << endl; // init variables name = I.getString("exptName"); N = I.getScalar("particles"); K = K0 = int(I.getScalar("fC0")*N); nStepsLifetime = I.getArray("nStepsLife")[0]; genMax = int(I.getScalar("genMax")); b_anim_on = bool(I.getScalar("b_anim_on")); // init movement params par.dt = I.getScalar("dt"); par.Rr = I.getScalar("Rr"); par.Rs = I.getArray("Rs0")[0]; // this is initial value of Rs. If baseline, this must not change par.kA = I.getScalar("kA"); par.kO = I.getScalar("kO"); par.speed = I.getScalar("speed"); par.copyErrSd = I.getScalar("copyErrSd"); par.turnRateMax = I.getScalar("turnRateMax")*pi/180; par.cosphi = cos(par.turnRateMax*par.dt); par.xmin = -I.getScalar("arenaSize")/2; par.xmax = I.getScalar("arenaSize")/2; par.ymin = -I.getScalar("arenaSize")/2; par.ymax = I.getScalar("arenaSize")/2; // grid properties par.N = N; par.cellSize = par.Rr; // this MUST BE equal to Rr. Otherwise code will fail. par.nCellsX = ceil((par.xmax-par.xmin)/(par.cellSize)); par.nCellsXY = par.nCellsX*par.nCellsX; blockDims.x = I.getScalar("blockSize"); gridDims.x = (N-1)/blockDims.x + 1; pvec.resize(N); // -------- INIT particles ------------------ for (int i=0; i<N; ++i){ pvec[i].pos = runif2(par.xmax, par.ymax); pvec[i].vel = runif2(1.0); // make_float2(0,1); // pvec[i].wA = (i< K0)? Cooperate:Defect; pvec[i].kA = par.kA; // runif(); // pvec[i].kO = par.kO; // runif(); // pvec[i].ancID = i; // each fish within a block gets unique ancestor ID pvec[i].fitness = 0; if (pvec[i].wA == Cooperate) pvec[i].Rs = 2; // par.Rs; // 1.3; else pvec[i].Rs = 3; // par.Rs; // 1.1; // pvec[i].Rs = 1+float(i)/(N-1)*(10-1); } // SimpleTimer T; T.start(); // updateGroupIndices_fast(); // T.stop(); T.printTime(); // pvec[0].pos = make_float2(0,0); // pvec[1].pos = make_float2(par.xmax,par.ymax); // pvec[2].pos = make_float2(par.xmin,par.ymin); printParticles(20); cout << "blocks: " << gridDims.x << ", threads: " << blockDims.x << ", Total threads: " << blockDims.x*gridDims.x << endl; // allocate memory for grid arrays on device cudaMalloc((void**)&cellIds_dev, par.N*sizeof(int)); cudaMalloc((void**)&cellParticles_dev, 4*par.nCellsXY*sizeof(int)); cudaMalloc((void**)&cellCounts_dev, par.nCellsXY*sizeof(int)); // // ~~~~~~~~~~~~~~~~~ EXPT DESC ~~~~~~~~~~~~~~~~~~~~ // stringstream sout; // sout << setprecision(3); // sout << I.getString("exptName"); // if (b_baseline) sout << "_base"; // sout << "_n(" << N // << ")_nm(" << I.getScalar("moveStepsPerGen") // << ")_rd(" << I.getScalar("rDisp") // << ")_mu(" << I.getScalar("mu")[0] // << ")_fb(" << I.getScalar("fitness_base") // << ")_as(" << I.getScalar("arenaSize") // << ")_rg("; // if (b_constRg) sout << I.getScalar("rGrp"); // else sout << "-1"; // if (b_baseline) sout << ")_Rs(" << I.getScalar(Rs_base; // sout << ")"; // exptDesc = sout.str(); sout.clear(); // ~~~~~~~~~~~~~~ initial state ~~~~~~~~~~~~~~~~~~~ // // copy arrays to device // // v dst v dst pitch v src v src pitch v bytes/elem v n_elem v direction // cudaMemcpy2D( (void*) pos_dev, sizeof(float2), (void*)&(animals[0].pos), sizeof(Particle), sizeof(float2), nFish, cudaMemcpyHostToDevice); // cudaMemcpy2D( (void*) vel_dev, sizeof(float2), (void*)&(animals[0].vel), sizeof(Particle), sizeof(float2), nFish, cudaMemcpyHostToDevice); // cudaMemcpy2D( (void*) Rs_dev, sizeof(float), (void*)&(animals[0].Rs), sizeof(Particle), sizeof(float), nFish, cudaMemcpyHostToDevice); // // grid // cellSize = 10; // nCellsX = int(arenaSize/(cellSize+1e-6))+1; // nCells = nCellsX * nCellsX; }
Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); t = t->toBasetype(); if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct) t = t->nextOf()->toBasetype(); if (t->ty == Tstruct) { StructDeclaration *sd = ((TypeStruct *)t)->sym; if (sd->ctor) { error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", sd->kind(), sd->toChars(), sd->toChars()); return new ErrorInitializer(); } sd->size(loc); if (sd->sizeok != SIZEOKdone) return new ErrorInitializer(); size_t nfields = sd->fields.dim - sd->isNested(); //expandTuples for non-identity arguments? Expressions *elements = new Expressions(); elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) (*elements)[i] = NULL; // Run semantic for explicitly given initializers // TODO: this part is slightly different from StructLiteralExp::semantic. bool errors = false; for (size_t fieldi = 0, i = 0; i < field.dim; i++) { if (Identifier *id = field[i]) { Dsymbol *s = sd->search(loc, id); if (!s) { s = sd->search_correct(id); if (s) error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", id->toChars(), sd->toChars(), s->kind(), s->toChars()); else error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); return new ErrorInitializer(); } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { error(loc, "%s.%s is not a per-instance initializable field", sd->toChars(), s->toChars()); return new ErrorInitializer(); } if (s == sd->fields[fieldi]) break; } } else if (fieldi >= nfields) { error(loc, "too many initializers for %s", sd->toChars()); return new ErrorInitializer(); } VarDeclaration *vd = sd->fields[fieldi]; if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", vd->toChars()); errors = true; continue; } for (size_t j = 0; j < nfields; j++) { VarDeclaration *v2 = sd->fields[j]; bool overlap = (vd->offset < v2->offset + v2->type->size() && v2->offset < vd->offset + vd->type->size()); if (overlap && (*elements)[j]) { error(loc, "overlapping initialization for field %s and %s", v2->toChars(), vd->toChars()); errors = true; continue; } } assert(sc); Initializer *iz = value[i]; iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret); Expression *ex = iz->toExpression(); if (ex->op == TOKerror) { errors = true; continue; } value[i] = iz; (*elements)[fieldi] = ex; ++fieldi; } if (errors) return new ErrorInitializer(); StructLiteralExp *sle = new StructLiteralExp(loc, sd, elements, t); if (!sd->fill(loc, elements, false)) return new ErrorInitializer(); sle->type = t; ExpInitializer *ie = new ExpInitializer(loc, sle); return ie->semantic(sc, t, needInterpret); } else if ((t->ty == Tdelegate || t->ty == Tpointer && t->nextOf()->ty == Tfunction) && value.dim == 0) { TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction; /* Rewrite as empty delegate literal { } */ Parameters *arguments = new Parameters; Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, 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, needInterpret); } error(loc, "a struct is not a valid initializer for a %s", t->toChars()); return new ErrorInitializer(); }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); if (tb->ty == Tvector) tb = ((TypeVector *)tb)->basetype; Type *tn = tb->nextOf()->toBasetype(); //printf("\tdim = %d\n", dim); Dts dts; dts.setDim(dim); dts.zero(); unsigned size = tn->size(); unsigned length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx = index[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); Initializer *val = value[i]; dt_t *dt = val->toDt(); if (dts[length]) error(loc, "duplicate initializations for index %d", length); dts[length] = dt; length++; } Expression *edefault = tb->nextOf()->defaultInit(); size_t n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } dt_t *d = NULL; dt_t **pdtend = &d; for (size_t i = 0; i < dim; i++) { dt_t *dt = dts[i]; if (dt) pdtend = dtcat(pdtend, dt); else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } switch (tb->ty) { case Tsarray: { size_t tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { if (edefault->isBool(false)) // pad out end of array pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (size_t i = dim; i < tadim; i++) { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } } else if (dim > tadim) { error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } break; } case Tpointer: case Tarray: { dt_t *dtarray = d; d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtdtoff(&d, dtarray, 0); break; } default: assert(0); } return d; }
Initializer *ArrayInitializer::inferType(Scope *sc) { //printf("ArrayInitializer::inferType() %s\n", toChars()); Expressions *keys = NULL; Expressions *values; if (isAssociativeArray()) { keys = new Expressions(); keys->setDim(value.dim); values = new Expressions(); values->setDim(value.dim); for (size_t i = 0; i < value.dim; i++) { Expression *e = index[i]; if (!e) goto Lno; (*keys)[i] = e; Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*values)[i] = ((ExpInitializer *)iz)->exp; assert((*values)[i]->op != TOKerror); } Expression *e = new AssocArrayLiteralExp(loc, keys, values); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc); } else { Expressions *elements = new Expressions(); elements->setDim(value.dim); elements->zero(); for (size_t i = 0; i < value.dim; i++) { assert(!index[i]); // already asserted by isAssociativeArray() Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*elements)[i] = ((ExpInitializer *)iz)->exp; assert((*elements)[i]->op != TOKerror); } Expression *e = new ArrayLiteralExp(loc, elements); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc); } Lno: if (keys) { delete keys; delete values; error(loc, "not an associative array initializer"); } else { error(loc, "cannot infer type from array initializer"); } return new ErrorInitializer(); }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); Type *tn = tb->next->toBasetype(); if (tn->ty == Tbit) return toDtBit(); Array dts; unsigned size; unsigned length; dt_t *dt; dt_t *d; dt_t **pdtend; //printf("\tdim = %d\n", dim); dts.setDim(dim); dts.zero(); size = tn->size(); length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = (Expression *)index.data[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = (Initializer *)value.data[i]; dt = val->toDt(); if (dts.data[length]) error(loc, "duplicate initializations for index %d", length); dts.data[length] = (void *)dt; length++; } Expression *edefault = tb->next->defaultInit(); #ifdef IN_GCC dt_t * sadefault = NULL; if (tn->ty == Tsarray) tn->toDt(& sadefault); else edefault->toDt(& sadefault); #else unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->next->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } #endif d = NULL; pdtend = &d; for (size_t i = 0; i < dim; i++) { dt = (dt_t *)dts.data[i]; #ifdef IN_GCC pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault); #else if (dt) pdtend = dtcat(pdtend, dt); else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } #endif } switch (tb->ty) { case Tsarray: { unsigned tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { if (edefault->isBool(FALSE)) // pad out end of array // (ok for GDC as well) pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (size_t i = dim; i < tadim; i++) #ifdef IN_GCC pdtend = dtcontainer(pdtend, NULL, sadefault); #else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } #endif } } else if (dim > tadim) { #ifdef DEBUG printf("1: "); #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } #ifdef IN_GCC dt_t * cdt = NULL; dtcontainer(& cdt, type, d); d = cdt; #endif break; } case Tpointer: case Tarray: { // Create symbol, and then refer to it Symbol *s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); #ifdef IN_GCC dt_t * cdt; cdt = NULL; if (tb->ty == Tarray) { dtcontainer(& cdt, type, d); d = cdt; } #endif break; } default: assert(0); } return d; }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { size_t length; const unsigned amax = 0x80000000; bool errors = false; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run return this; sem = true; t = t->toBasetype(); switch (t->ty) { case Tsarray: case Tarray: break; case Tvector: t = ((TypeVector *)t)->basetype; break; case Taarray: case Tstruct: // consider implicit constructor call { Expression *e; if (t->ty == Taarray || isAssociativeArray()) e = toAssocArrayLiteral(); else e = toExpression(); ExpInitializer *ei = new ExpInitializer(e->loc, e); return ei->semantic(sc, t, needInterpret); } case Tpointer: if (t->nextOf()->ty != Tfunction) break; default: error(loc, "cannot use array to initialize %s", t->toChars()); goto Lerr; } type = t; length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx = index[i]; if (idx) { sc = sc->startCTFE(); idx = idx->semantic(sc); sc = sc->endCTFE(); idx = idx->ctfeInterpret(); index[i] = idx; length = (size_t)idx->toInteger(); if (idx->op == TOKerror) errors = true; } Initializer *val = value[i]; ExpInitializer *ei = val->isExpInitializer(); if (ei && !idx) ei->expandTuples = true; val = val->semantic(sc, t->nextOf(), needInterpret); if (val->isErrorInitializer()) errors = true; ei = val->isExpInitializer(); // found a tuple, expand it if (ei && ei->exp->op == TOKtuple) { TupleExp *te = (TupleExp *)ei->exp; index.remove(i); value.remove(i); for (size_t j = 0; j < te->exps->dim; ++j) { Expression *e = (*te->exps)[j]; index.insert(i + j, (Expression *)NULL); value.insert(i + j, new ExpInitializer(e->loc, e)); } i--; continue; } else { value[i] = val; } length++; if (length == 0) { error(loc, "array dimension overflow"); goto Lerr; } if (length > dim) dim = length; } if (t->ty == Tsarray) { dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } if (errors) goto Lerr; if ((uinteger_t) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size())); goto Lerr; } return this; Lerr: return new ErrorInitializer(); }
void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) { unsigned offset; dt_t *dt; unsigned csymoffset; #define LOG 0 #if LOG printf("ClassDeclaration::toDt2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); #endif if (baseClass) { baseClass->toDt2(pdt, cd); offset = baseClass->structsize; } else { offset = PTRSIZE * 2; } // Note equivalence of this loop to struct's for (size_t i = 0; i < fields.dim; i++) { VarDeclaration *v = (VarDeclaration *)fields.data[i]; Initializer *init; //printf("\t\tv = '%s' v->offset = %2d, offset = %2d\n", v->toChars(), v->offset, offset); dt = NULL; init = v->init; if (init) { //printf("\t\t%s has initializer %s\n", v->toChars(), init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); } else if (v->offset >= offset) { //printf("\t\tdefault initializer\n"); v->type->toDt(&dt); } if (dt) { if (v->offset < offset) error("duplicated union initialization for %s", v->toChars()); else { if (offset < v->offset) dtnzeros(pdt, v->offset - offset); dtcat(pdt, dt); offset = v->offset + v->type->size(); } } } // Interface vptr initializations toSymbol(); // define csym for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; #if 1 || INTERFACE_VIRTUAL for (ClassDeclaration *cd2 = cd; 1; cd2 = cd2->baseClass) { assert(cd2); csymoffset = cd2->baseVtblOffset(b); if (csymoffset != ~0) { if (offset < b->offset) dtnzeros(pdt, b->offset - offset); dtxoff(pdt, cd2->toSymbol(), csymoffset, TYnptr); break; } } #else csymoffset = baseVtblOffset(b); assert(csymoffset != ~0); dtxoff(pdt, csym, csymoffset, TYnptr); #endif offset = b->offset + PTRSIZE; } if (offset < structsize) dtnzeros(pdt, structsize - offset); #undef LOG }
void StructDeclaration::toDt(dt_t **pdt) { if (zeroInit) { dtnzeros(pdt, structsize); return; } unsigned offset; dt_t *dt; dt_t *sdt = NULL; //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); offset = 0; // Note equivalence of this loop to class's for (size_t i = 0; i < fields.dim; i++) { VarDeclaration *v = fields[i]; //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); dt = NULL; int sz; if (v->storage_class & STCref) { sz = PTRSIZE; if (v->offset >= offset) dtnzeros(&dt, sz); } else { sz = v->type->size(); Initializer *init = v->init; if (init) { //printf("\t\thas initializer %s\n", init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (init->isVoidInitializer()) ; else if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); } else if (v->offset >= offset) v->type->toDt(&dt); } if (dt) { if (v->offset < offset) error("overlapping initialization for struct %s.%s", toChars(), v->toChars()); else { if (offset < v->offset) dtnzeros(&sdt, v->offset - offset); dtcat(&sdt, dt); offset = v->offset + sz; } } } if (offset < structsize) dtnzeros(&sdt, structsize - offset); #ifdef IN_GCC dtcontainer(pdt, type, sdt); #else dtcat(pdt, sdt); #endif dt_optimize(*pdt); }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { unsigned i; unsigned length; const unsigned amax = 0x80000000; //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; case Tvector: t = ((TypeVector *)t)->basetype; break; default: error(loc, "cannot use array to initialize %s", type->toChars()); goto Lerr; } length = 0; for (i = 0; i < index.dim; i++) { Expression *idx = index[i]; if (idx) { idx = idx->semantic(sc); idx = idx->ctfeInterpret(); index[i] = idx; length = idx->toInteger(); } Initializer *val = value[i]; ExpInitializer *ei = val->isExpInitializer(); if (ei && !idx) ei->expandTuples = 1; val = val->semantic(sc, t->nextOf(), needInterpret); ei = val->isExpInitializer(); // found a tuple, expand it if (ei && ei->exp->op == TOKtuple) { TupleExp *te = (TupleExp *)ei->exp; index.remove(i); value.remove(i); for (size_t j = 0; j < te->exps->dim; ++j) { Expression *e = (*te->exps)[j]; index.insert(i + j, (Expression *)NULL); value.insert(i + j, new ExpInitializer(e->loc, e)); } i--; continue; } else { value[i] = val; } length++; if (length == 0) { error(loc, "array dimension overflow"); goto Lerr; } if (length > dim) dim = length; } if (t->ty == Tsarray) { dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } if ((unsigned long) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size()); goto Lerr; } return this; Lerr: return new ExpInitializer(loc, new ErrorExp()); }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); if (tb->ty == Tvector) tb = ((TypeVector *)tb)->basetype; Type *tn = tb->nextOf()->toBasetype(); Dts dts; unsigned size; unsigned length; dt_t *dt; dt_t *d; dt_t **pdtend; //printf("\tdim = %d\n", dim); dts.setDim(dim); dts.zero(); size = tn->size(); length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = index[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = value[i]; dt = val->toDt(); if (dts[length]) error(loc, "duplicate initializations for index %d", length); if (tn->ty == Tsarray) dt = createTsarrayDt(dt, tb->nextOf()); dts[length] = dt; length++; } Expression *edefault = tb->nextOf()->defaultInit(); #ifdef IN_GCC dt_t * sadefault = NULL; if (tn->ty == Tsarray) tn->toDt(& sadefault); else edefault->toDt(& sadefault); #else unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } #endif d = NULL; pdtend = &d; for (size_t i = 0; i < dim; i++) { dt = dts[i]; #ifdef IN_GCC pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault); #else if (dt) pdtend = dtcat(pdtend, dt); else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } #endif } switch (tb->ty) { case Tsarray: { unsigned tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { #ifdef IN_GCC // Pad out the rest of the array with single elements. // Otherwise breaks -fsection-anchors on ARM when // backend calculates field positions for array members. for (size_t i = dim; i < tadim; i++) pdtend = dtcontainer(pdtend, NULL, sadefault); #else if (edefault->isBool(FALSE)) // pad out end of array pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (size_t i = dim; i < tadim; i++) { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } #endif } else if (dim > tadim) { error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } #ifdef IN_GCC dt_t * cdt = NULL; dtcontainer(& cdt, type, d); d = cdt; #endif break; } case Tpointer: case Tarray: { // Create symbol, and then refer to it Symbol *s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); #ifdef IN_GCC dt_t * cdt; cdt = NULL; if (tb->ty == Tarray) { dtcontainer(& cdt, type, d); d = cdt; } #endif break; } default: assert(0); } return d; }
Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) { 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 fieldi = 0; TypeStruct *ts = (TypeStruct *)t; ad = ts->sym; if (ad->ctor) error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", ad->kind(), ad->toChars(), ad->toChars()); size_t nfields = ad->fields.dim; if (((StructDeclaration *)ad)->isnested) nfields--; for (size_t i = 0; i < field.dim; i++) { Identifier *id = field[i]; Initializer *val = value[i]; Dsymbol *s; VarDeclaration *v; if (id == NULL) { if (fieldi >= nfields) { error(loc, "too many initializers for %s", ad->toChars()); errors = 1; field.remove(i); i--; continue; } else { s = ad->fields[fieldi]; } } else { //s = ad->symtab->lookup(id); s = ad->search(loc, id, 0); if (!s) { s = ad->search_correct(id); if (s) error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", id->toChars(), t->toChars(), s->kind(), s->toChars()); else error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); errors = 1; continue; } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { error(loc, "%s.%s is not a per-instance initializable field", t->toChars(), s->toChars()); errors = 1; break; } if (s == ad->fields[fieldi]) break; } } if (s && (v = s->isVarDeclaration()) != NULL) { val = val->semantic(sc, v->type, needInterpret); value[i] = val; vars[i] = 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 { } */ Parameters *arguments = new Parameters; 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, needInterpret); } 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; }
Initializer *ArrayInitializer::inferType(Scope *sc, Type *tx) { //printf("ArrayInitializer::inferType() %s\n", toChars()); Expressions *keys = NULL; Expressions *values; if (tx ? (tx->ty == Taarray || tx->ty != Tarray && tx->ty != Tsarray && isAssociativeArray()) : isAssociativeArray()) { Type *tidx = NULL; Type *tval = NULL; if (tx && tx->ty == Taarray) { tidx = ((TypeAArray *)tx)->index; tval = ((TypeAArray *)tx)->next; } keys = new Expressions(); keys->setDim(value.dim); values = new Expressions(); values->setDim(value.dim); for (size_t i = 0; i < value.dim; i++) { Expression *e = index[i]; if (!e) goto Lno; if (tidx) { e = ::inferType(e, tidx); e = e->semantic(sc); e = resolveProperties(sc, e); if (tidx->deco) // tidx may be partial type e = e->implicitCastTo(sc, tidx); } (*keys)[i] = e; Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc, tval); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*values)[i] = ((ExpInitializer *)iz)->exp; assert((*values)[i]->op != TOKerror); } Expression *e = new AssocArrayLiteralExp(loc, keys, values); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc, tx); } else { Type *tn = NULL; if (tx && (tx->ty == Tarray || tx->ty == Tsarray)) tn = ((TypeNext *)tx)->next; Expressions *elements = new Expressions(); elements->setDim(value.dim); elements->zero(); for (size_t i = 0; i < value.dim; i++) { assert(!index[i]); // already asserted by isAssociativeArray() Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc, tn); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*elements)[i] = ((ExpInitializer *)iz)->exp; assert((*elements)[i]->op != TOKerror); } Expression *e = new ArrayLiteralExp(loc, elements); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc, tx); } Lno: if (keys) { delete keys; delete values; error(loc, "not an associative array initializer"); } else { error(loc, "cannot infer type from array initializer"); } return new ErrorInitializer(); }