Mercurial > projects > ddmd
diff dmd/AliasDeclaration.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 5c9b78899f5d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/AliasDeclaration.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,233 @@ +module dmd.AliasDeclaration; + +import dmd.LINK; +import dmd.Declaration; +import dmd.TypedefDeclaration; +import dmd.VarDeclaration; +import dmd.FuncDeclaration; +import dmd.FuncAliasDeclaration; +import dmd.Dsymbol; +import dmd.ScopeDsymbol; +import dmd.Loc; +import dmd.Identifier; +import dmd.Type; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.Scope; +import dmd.STC; +import dmd.Expression; +import dmd.Global; + +class AliasDeclaration : Declaration +{ + Dsymbol aliassym; + Dsymbol overnext; // next in overload list + int inSemantic; + + this(Loc loc, Identifier ident, Type type) + { + super(ident); + + //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type); + //printf("type = '%s'\n", type.toChars()); + this.loc = loc; + this.type = type; + this.aliassym = null; + version (_DH) { + this.htype = null; + this.haliassym = null; + } + + assert(type); + } + + this(Loc loc, Identifier id, Dsymbol s) + { + super(id); + + //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); + assert(s !is this); /// huh? + this.loc = loc; + this.type = null; + this.aliassym = s; + version (_DH) { + this.htype = null; + this.haliassym = null; + } + assert(s); + } + + Dsymbol syntaxCopy(Dsymbol) + { + assert(false); + } + + void semantic(Scope sc) + { + //printf("AliasDeclaration.semantic() %s\n", toChars()); + if (aliassym) + { + if (aliassym.isTemplateInstance()) + aliassym.semantic(sc); + return; + } + this.inSemantic = 1; + + if (storage_class & STC.STCconst) + error("cannot be const"); + + storage_class |= sc.stc & STC.STCdeprecated; + + // Given: + // alias foo.bar.abc def; + // it is not knowable from the syntax whether this is an alias + // for a type or an alias for a symbol. It is up to the semantic() + // pass to distinguish. + // If it is a type, then type is set and getType() will return that + // type. If it is a symbol, then aliassym is set and type is null - + // toAlias() will return aliasssym. + + Dsymbol s; + Type t; + Expression e; + + /* This section is needed because resolve() will: + * const x = 3; + * alias x y; + * try to alias y to 3. + */ + s = type.toDsymbol(sc); + if (s && ((s.getType() && type.equals(s.getType())) || s.isEnumMember())) + goto L2; // it's a symbolic alias + +///version (DMDV2) { + if (storage_class & STC.STCref) + { // For 'ref' to be attached to function types, and picked + // up by Type.resolve(), it has to go into sc. + sc = sc.push(); + sc.stc |= STC.STCref; + type.resolve(loc, sc, &e, &t, &s); + sc = sc.pop(); + } + else +/// #endif + type.resolve(loc, sc, &e, &t, &s); + if (s) + { + goto L2; + } + else if (e) + { + // Try to convert Expression to Dsymbol + s = getDsymbol(e); + if (s) + goto L2; + + error("cannot alias an expression %s", e.toChars()); + t = e.type; + } + else if (t) + { + type = t; + } + if (overnext) + ScopeDsymbol.multiplyDefined(Loc(0), this, overnext); + this.inSemantic = 0; + return; + + L2: + //printf("alias is a symbol %s %s\n", s.kind(), s.toChars()); + type = null; + VarDeclaration v = s.isVarDeclaration(); + if (v && v.linkage == LINK.LINKdefault) + { + error("forward reference of %s", v.toChars()); + s = null; + } + else + { + FuncDeclaration f = s.toAlias().isFuncDeclaration(); + if (f) + { + if (overnext) + { + FuncAliasDeclaration fa = new FuncAliasDeclaration(f); + if (!fa.overloadInsert(overnext)) + ScopeDsymbol.multiplyDefined(Loc(0), f, overnext); + overnext = null; + s = fa; + s.parent = sc.parent; + } + } + if (overnext) + ScopeDsymbol.multiplyDefined(Loc(0), s, overnext); + if (s == this) + { + assert(global.errors); + s = null; + } + } + //printf("setting aliassym %p to %p\n", this, s); + aliassym = s; + this.inSemantic = 0; + } + + bool overloadInsert(Dsymbol s) + { + /* Don't know yet what the aliased symbol is, so assume it can + * be overloaded and check later for correctness. + */ + + //printf("AliasDeclaration.overloadInsert('%s')\n", s.toChars()); + if (overnext is null) + { + overnext = s; + return true; + } + else + { + return overnext.overloadInsert(s); + } + } + + string kind() + { + return "alias"; + } + + Type getType() + { + return type; + } + + Dsymbol toAlias() + { + //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); + assert(this !is aliassym); + //static int count; if (++count == 10) *(char*)0=0; + if (inSemantic) + { + error("recursive alias declaration"); + aliassym = new TypedefDeclaration(loc, ident, Type.terror, null); + } + + Dsymbol s = aliassym ? aliassym.toAlias() : this; + return s; + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + +version (_DH) { + Type htype; + Dsymbol haliassym; +} + void toDocBuffer(OutBuffer buf) + { + assert(false); + } + + AliasDeclaration isAliasDeclaration() { return this; } +} \ No newline at end of file