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(); } Expression *e = fill(sc, t, needInterpret); if (e->op == TOKerror) return new ErrorInitializer(); ExpInitializer *ie = new ExpInitializer(loc, e); return ie->semantic(sc, t, needInterpret); } 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, Loc(), 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); } error(loc, "a struct is not a valid initializer for a %s", t->toChars()); return new ErrorInitializer(); }
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()); StructDeclaration *sd = ad->isStructDeclaration(); assert(sd); sd->size(loc); if (sd->sizeok != SIZEOKdone) { error(loc, "struct %s is forward referenced", sd->toChars()); errors = 1; goto Lerror; } size_t nfields = sd->fields.dim; if (sd->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; } Lerror: if (errors) { field.setDim(0); value.setDim(0); vars.setDim(0); } return this; }
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; }
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(); }
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(); }
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(); }
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(); }