view dmd/TypeEnum.d @ 178:e3afd1303184

Many small bugs fixed Made all classes derive from TObject to detect memory leaks (functionality is disabled for now) Began work on overriding backend memory allocations (to avoid memory leaks)
author korDen
date Sun, 17 Oct 2010 07:42:00 +0400
parents 0c8cc2a10f99
children cd48cb899aee
line wrap: on
line source

module dmd.TypeEnum;

import dmd.common;
import dmd.Type;
import dmd.EnumDeclaration;
import dmd.Scope;
import dmd.Loc;
import dmd.Id;
import dmd.ErrorExp;
import dmd.Dsymbol;
import dmd.EnumMember;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.Expression;
import dmd.Identifier;
import dmd.MATCH;
import dmd.OutBuffer;
import dmd.CppMangleState;
import dmd.StringExp;
import dmd.TypeInfoDeclaration;
import dmd.TypeInfoEnumDeclaration;
import dmd.ArrayTypes;
import dmd.TY;
import dmd.MOD;
import dmd.Util;

import dmd.backend.TYPE;

class TypeEnum : Type
{
    EnumDeclaration sym;

    this(EnumDeclaration sym)
	{
		register();
		super(TY.Tenum);
		this.sym = sym;
	}
	
    override Type syntaxCopy()
	{
		assert(false);
	}
	
    override ulong size(Loc loc)
	{
		if (!sym.memtype)
		{
			error(loc, "enum %s is forward referenced", sym.toChars());
			return 4;
		}
		return sym.memtype.size(loc);
	}
	
	override uint alignsize()
	{
		if (!sym.memtype)
		{
			debug writef("1: ");

			error(Loc(0), "enum %s is forward referenced", sym.toChars());
			return 4;
		}
		return sym.memtype.alignsize();
	}

	override string toChars()
	{
		if (mod)
			return super.toChars();
		return sym.toChars();
	}
	
    override Type semantic(Loc loc, Scope sc)
	{
		//printf("TypeEnum::semantic() %s\n", toChars());
		//sym.semantic(sc);
		return merge();
	}
	
    override Dsymbol toDsymbol(Scope sc)
	{
		return sym;
	}
	
    override void toDecoBuffer(OutBuffer buf, int flag)
	{
		string name = sym.mangle();
		Type.toDecoBuffer(buf, flag);
		buf.printf("%s", name);
	}
	
    override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
	{
		if (mod != this.mod)
		{	
			toCBuffer3(buf, hgs, mod);
			return;
		}
		buf.writestring(sym.toChars());
	}

    override Expression dotExp(Scope sc, Expression e, Identifier ident)
	{
	version (LOGDOTEXP) {
		printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), toChars());
	}
		Dsymbol s = sym.search(e.loc, ident, 0);
		if (!s)
		{
			if (ident is Id.max ||
				ident is Id.min ||
				ident is Id.init_ ||
				ident is Id.stringof_ ||
				!sym.memtype
			   )
			{
				return getProperty(e.loc, ident);
			}

			return sym.memtype.dotExp(sc, e, ident);
		}

		EnumMember m = s.isEnumMember();
		Expression em = m.value.copy();
		em.loc = e.loc;
		return em;
	}
	
	override Expression getProperty(Loc loc, Identifier ident)
	{
		Expression e;

		if (ident is Id.max)
		{
			if (!sym.maxval)
				goto Lfwd;
			e = sym.maxval;
		}
		else if (ident is Id.min)
		{
			if (!sym.minval)
				goto Lfwd;
			e = sym.minval;
		}
		else if (ident is Id.init_)
		{
			e = defaultInitLiteral(loc);
		}
		else if (ident is Id.stringof_)
		{
			string s = toChars();
			e = new StringExp(loc, s, 'c');
			Scope sc;
			e = e.semantic(sc);
		}
		else if (ident is Id.mangleof_)
		{
			e = Type.getProperty(loc, ident);
		}
		else
		{
			e = toBasetype().getProperty(loc, ident);
		}
		return e;

	Lfwd:
		error(loc, "forward reference of %s.%s", toChars(), ident.toChars());
		return new ErrorExp();
	}
	
    override bool isintegral()
	{
	    return sym.memtype.isintegral();
	}
	
    override bool isfloating()
	{
	    return sym.memtype.isfloating();
	}
	
    override bool isreal()
	{
		return sym.memtype.isreal();
	}
	
    override bool isimaginary()
	{
		return sym.memtype.isimaginary();
	}
	
    override bool iscomplex()
	{
		return sym.memtype.iscomplex();
	}
	
    override bool checkBoolean()
	{
		return sym.memtype.checkBoolean();
	}
	
    override bool isAssignable()
	{
		return sym.memtype.isAssignable();
	}
	
    override bool isscalar()
	{
	    return sym.memtype.isscalar();
	}
	
    override bool isunsigned()
	{
		return sym.memtype.isunsigned();
	}
	
    override MATCH implicitConvTo(Type to)
	{
		MATCH m;

		//printf("TypeEnum::implicitConvTo()\n");
		if (ty == to.ty && sym == (cast(TypeEnum)to).sym)
			m = (mod == to.mod) ? MATCHexact : MATCHconst;
		else if (sym.memtype.implicitConvTo(to))
			m = MATCHconvert;	// match with conversions
		else
			m = MATCHnomatch;	// no match
		return m;
	}
	
    override MATCH constConv(Type to)
	{
        if (equals(to))
	        return MATCHexact;
        if (ty == to.ty && sym == (cast(TypeEnum)to).sym &&
	        MODimplicitConv(mod, to.mod))
	        return MATCHconst;
        return MATCHnomatch;
	}
	
    override Type toBasetype()
	{
        if (sym.scope_)
        {
    	    sym.semantic(null);	// attempt to resolve forward reference
        }
		if (!sym.memtype)
		{
			debug writef("2: ");
			error(sym.loc, "enum %s is forward referenced", sym.toChars());
			return tint32;
		}

		return sym.memtype.toBasetype();
	}
	
    override Expression defaultInit(Loc loc)
	{
	version (LOGDEFAULTINIT) {
		printf("TypeEnum::defaultInit() '%s'\n", toChars());
	}
		// Initialize to first member of enum
		//printf("%s\n", sym.defaultval.type.toChars());
		if (!sym.defaultval)
		{
			error(loc, "forward reference of %s.init", toChars());
			return new ErrorExp();
		}
		return sym.defaultval;
	}
	
    override bool isZeroInit(Loc loc)
	{
		if (!sym.defaultval)
		{
			debug writef("3: ");
			error(loc, "enum %s is forward referenced", sym.toChars());
			return 0;
		}
		return sym.defaultval.isBool(false);
	}
	
	override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
	{
		// Extra check
		if (tparam && tparam.ty == Tenum)
		{
			TypeEnum tp = cast(TypeEnum)tparam;

			if (sym != tp.sym)
				return MATCHnomatch;
		}
		return Type.deduceType(sc, tparam, parameters, dedtypes);
	}
	
    override TypeInfoDeclaration getTypeInfoDeclaration()
	{
		return new TypeInfoEnumDeclaration(this);
	}
	
    override bool hasPointers()
	{
		return toBasetype().hasPointers();
	}
	
version (CPP_MANGLE) {
    void toCppMangle(OutBuffer buf, CppMangleState* cms)
	{
		assert(false);
	}
}

    override type* toCtype()
	{
		return sym.memtype.toCtype();
	}
}