view 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 source

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; }
}