void Module::semantic2() { if (deferred.dim) { for (size_t i = 0; i < deferred.dim; i++) { Dsymbol *sd = deferred[i]; sd->error("unable to resolve forward reference in definition"); } return; } //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); if (semanticRun != PASSsemanticdone) // semantic() not completed yet - could be recursive call return; semanticRun = PASSsemantic2; // Note that modules get their own scope, from scratch. // This is so regardless of where in the syntax a module // gets imported, it is unaffected by context. Scope *sc = Scope::createGlobal(this); // create root scope //printf("Module = %p\n", sc.scopesym); // Pass 2 semantic routines: do initializers and function bodies for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; s->semantic2(sc); } sc = sc->pop(); sc->pop(); semanticRun = PASSsemantic2done; //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); }
DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg) { DsymbolTable *dst = Module::modules; Dsymbol *parent = NULL; //printf("Package::resolve()\n"); if (ppkg) *ppkg = NULL; if (packages) { int i; for (i = 0; i < packages->dim; i++) { Identifier *pid = (Identifier *)packages->data[i]; Dsymbol *p; p = dst->lookup(pid); if (!p) { p = new Package(pid); dst->insert(p); p->parent = parent; ((ScopeDsymbol *)p)->symtab = new DsymbolTable(); } else { assert(p->isPackage()); #if TARGET_NET //dot net needs modules and packages with same name #else if (p->isModule()) { p->error("module and package have the same name"); fatal(); break; } #endif } parent = p; dst = ((Package *)p)->symtab; if (ppkg && !*ppkg) *ppkg = (Package *)p; } if (pparent) { *pparent = parent; } } return dst; }
/******************************************* * Look for constructor declaration. */ Dsymbol *AggregateDeclaration::searchCtor() { Dsymbol *s = search(Loc(), Id::ctor); if (s) { if (!(s->isCtorDeclaration() || s->isTemplateDeclaration() || s->isOverloadSet())) { s->error("is not a constructor; identifiers starting with __ are reserved for the implementation"); errors = true; s = NULL; } } return s; }
void Module::semantic2(Scope* unused_sc) { int i; if (deferred.dim) { for (int i = 0; i < deferred.dim; i++) { Dsymbol *sd = (Dsymbol *)deferred.data[i]; sd->error("unable to resolve forward reference in definition"); } return; } //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); if (semanticstarted >= 2) return; assert(semanticstarted == 1); semanticstarted = 2; // Note that modules get their own scope, from scratch. // This is so regardless of where in the syntax a module // gets imported, it is unaffected by context. Scope *sc = Scope::createGlobal(this); // create root scope //printf("Module = %p\n", sc.scopesym); // Pass 2 semantic routines: do initializers and function bodies for (i = 0; i < members->dim; i++) { Dsymbol *s; s = (Dsymbol *)members->data[i]; s->semantic2(sc); } sc = sc->pop(); sc->pop(); semanticRun = semanticstarted; //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); }
/*************************************** * 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 (*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; }
/*************************************** * 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; }
Initializer *StructInitializer::semantic(Scope *sc, Type *t) { 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()); for (size_t 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()); errors = 1; 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()); errors = 1; 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"); errors = 1; 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 { } */ 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); } 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; }