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