view dmd/StructLiteralExp.d @ 64:4290d870944a

More fixes
author korDen
date Mon, 23 Aug 2010 20:29:15 +0400
parents cab4c37afb89
children f708f0452e81
line wrap: on
line source

module dmd.StructLiteralExp;

import dmd.Expression;
import dmd.MOD;
import dmd.TypeStruct;
import dmd.expression.Util;
import dmd.ErrorExp;
import dmd.Dsymbol;
import dmd.VarDeclaration;
import dmd.StructDeclaration;
import dmd.backend.elem;
import dmd.InterState;
import dmd.MATCH;
import dmd.WANT;
import dmd.TY;
import dmd.Type;
import dmd.OutBuffer;
import dmd.Loc;
import dmd.Scope;
import dmd.InlineCostState;
import dmd.IRState;
import dmd.InlineDoState;
import dmd.backend.Symbol;
import dmd.HdrGenState;
import dmd.backend.dt_t;
import dmd.InlineScanState;
import dmd.ArrayTypes;
import dmd.TOK;


class StructLiteralExp : Expression
{
	StructDeclaration sd;		// which aggregate this is for
    Expressions elements;	// parallels sd->fields[] with
				// NULL entries for fields to skip

    Symbol* sym;		// back end symbol to initialize with literal
    size_t soffset;		// offset from start of s
    int fillHoles;		// fill alignment 'holes' with zero

	this(Loc loc, StructDeclaration sd, Expressions elements)
	{
		super(loc, TOKstructliteral, StructLiteralExp.sizeof);
		this.sd = sd;
		this.elements = elements;
		this.sym = null;
		this.soffset = 0;
		this.fillHoles = 1;
	}

	Expression syntaxCopy()
	{
		assert(false);
	}

	Expression semantic(Scope sc)
	{
		Expression e;
		int nfields = sd.fields.dim - sd.isnested;

version (LOGSEMANTIC) {
		printf("StructLiteralExp.semantic('%s')\n", toChars());
}
		if (type)
			return this;

		// Run semantic() on each element
		for (size_t i = 0; i < elements.dim; i++)
		{	
			e = cast(Expression)elements.data[i];
			if (!e)
				continue;
			e = e.semantic(sc);
			elements.data[i] = cast(void*)e;
		}
		expandTuples(elements);
		size_t offset = 0;
		for (size_t i = 0; i < elements.dim; i++)
		{	
			e = cast(Expression)elements.data[i];
			if (!e)
				continue;

			if (!e.type)
				error("%s has no value", e.toChars());
			e = resolveProperties(sc, e);
			if (i >= nfields)
			{   
				error("more initializers than fields of %s", sd.toChars());
				return new ErrorExp();
			}
			Dsymbol s = cast(Dsymbol)sd.fields.data[i];
			VarDeclaration v = s.isVarDeclaration();
			assert(v);
			if (v.offset < offset)
				error("overlapping initialization for %s", v.toChars());
			offset = v.offset + cast(uint)v.type.size();

			Type telem = v.type;
			while (!e.implicitConvTo(telem) && telem.toBasetype().ty == Tsarray)
			{   
				/* Static array initialization, as in:
				 *	T[3][5] = e;
				 */
				telem = telem.toBasetype().nextOf();
			}

			e = e.implicitCastTo(sc, telem);

			elements.data[i] = cast(void*)e;
		}

		/* Fill out remainder of elements[] with default initializers for fields[]
		 */
		for (size_t i = elements.dim; i < nfields; i++)
		{	
			Dsymbol s = cast(Dsymbol)sd.fields.data[i];
			VarDeclaration v = s.isVarDeclaration();
			assert(v);
			assert(!v.isThisDeclaration());

			if (v.offset < offset)
			{   
				e = null;
				sd.hasUnions = 1;
			}
			else
			{
				if (v.init)
				{   
					e = v.init.toExpression();
					if (!e)
						error("cannot make expression out of initializer for %s", v.toChars());
				}
				else
				{	
					e = v.type.defaultInit(Loc(0));
					e.loc = loc;
				}
				offset = v.offset + cast(uint)v.type.size();
			}
			elements.push(cast(void*)e);
		}

		type = sd.type;
		return this;
	}

	Expression getField(Type type, uint offset)
	{
		assert(false);
	}

	int getFieldIndex(Type type, uint offset)
	{
		assert(false);
	}

	elem* toElem(IRState* irs)
	{
		assert(false);
	}

	bool checkSideEffect(int flag)
	{
		assert(false);
	}

	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		assert(false);
	}

	void toMangleBuffer(OutBuffer buf)
	{
		assert(false);
	}

	void scanForNestedRef(Scope sc)
	{
		assert(false);
	}

	Expression optimize(int result)
	{
		if (elements)
		{
			for (size_t i = 0; i < elements.dim; i++)
			{   
				Expression e = cast(Expression)elements.data[i];
				if (!e)
					continue;
				e = e.optimize(WANTvalue | (result & WANTinterpret));
				elements.data[i] = cast(void*)e;
			}
		}
		return this;
	}

	Expression interpret(InterState istate)
	{
		assert(false);
	}

	dt_t** toDt(dt_t** pdt)
	{
		assert(false);
	}

	int isLvalue()
	{
		assert(false);
	}

	Expression toLvalue(Scope sc, Expression e)
	{
		assert(false);
	}

	bool canThrow()
	{
		return arrayExpressionCanThrow(elements);
	}

	MATCH implicitConvTo(Type t)
	{
static if (false) {
		printf("StructLiteralExp.implicitConvTo(this=%.*s, type=%.*s, t=%.*s)\n",
			toChars(), type.toChars(), t.toChars());
}
		MATCH m = Expression.implicitConvTo(t);
		if (m != MATCHnomatch)
			return m;
		if (type.ty == t.ty && type.ty == Tstruct && (cast(TypeStruct)type).sym == (cast(TypeStruct)t).sym)
		{
			m = MATCHconst;
			for (int i = 0; i < elements.dim; i++)
			{   
				Expression e = cast(Expression)elements.data[i];
				Type te = e.type;
				if (t.mod == 0)
					te = te.mutableOf();
				else
				{	
					assert(t.mod == MODinvariant);
					te = te.invariantOf();
				}
				MATCH m2 = e.implicitConvTo(te);
				//printf("\t%s => %s, match = %d\n", e.toChars(), te.toChars(), m2);
				if (m2 < m)
					m = m2;
			}
		}
		return m;
	}

	int inlineCost(InlineCostState* ics)
	{
		assert(false);
	}

	Expression doInline(InlineDoState ids)
	{
		assert(false);
	}

	Expression inlineScan(InlineScanState* iss)
	{
		assert(false);
	}
}