diff dmd/StructLiteralExp.d @ 123:9e39c7de8438

Make dmd test suite compile
author korDen
date Fri, 03 Sep 2010 20:46:58 +0400
parents e28b18c23469
children af1bebfd96a4
line wrap: on
line diff
--- a/dmd/StructLiteralExp.d	Thu Sep 02 23:37:49 2010 +0100
+++ b/dmd/StructLiteralExp.d	Fri Sep 03 20:46:58 2010 +0400
@@ -2,11 +2,13 @@
 
 import dmd.common;
 import dmd.Expression;
+import dmd.GlobalExpressions;
 import dmd.MOD;
 import dmd.TypeStruct;
 import dmd.TypeSArray;
 import dmd.expression.Util;
 import dmd.ErrorExp;
+import dmd.Array;
 import dmd.Dsymbol;
 import dmd.VarDeclaration;
 import dmd.StructDeclaration;
@@ -63,7 +65,7 @@
 
 	override Expression syntaxCopy()
 	{
-		assert(false);
+		return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
 	}
 
 	override Expression semantic(Scope sc)
@@ -459,12 +461,163 @@
 
 	override Expression interpret(InterState istate)
 	{
-		assert(false);
+		Expressions expsx = null;
+
+version (LOG) {
+		printf("StructLiteralExp.interpret() %.*s\n", toChars());
+}
+		/* We don't know how to deal with overlapping fields
+		 */
+		if (sd.hasUnions)
+		{   
+			error("Unions with overlapping fields are not yet supported in CTFE");
+			return EXP_CANT_INTERPRET;
+		}
+
+		if (elements)
+		{
+			foreach (size_t i, Expression e; elements)
+			{   
+				if (!e)
+					continue;
+
+				Expression ex = e.interpret(istate);
+				if (ex is EXP_CANT_INTERPRET)
+				{   
+					delete expsx;
+					return EXP_CANT_INTERPRET;
+				}
+
+				/* If any changes, do Copy On Write
+				 */
+				if (ex != e)
+				{
+					if (!expsx)
+					{   
+						expsx = new Expressions();
+						expsx.setDim(elements.dim);
+						for (size_t j = 0; j < elements.dim; j++)
+						{
+							expsx[j] = elements[j];
+						}
+					}
+					expsx[i] = ex;
+				}
+			}
+		}
+		if (elements && expsx)
+		{
+			expandTuples(expsx);
+			if (expsx.dim != elements.dim)
+			{   
+				delete expsx;
+				return EXP_CANT_INTERPRET;
+			}
+			StructLiteralExp se = new StructLiteralExp(loc, sd, expsx);
+			se.type = type;
+			return se;
+		}
+		return this;
 	}
 
 	override dt_t** toDt(dt_t** pdt)
 	{
-		assert(false);
+		Array dts;
+		dt_t *dt;
+		dt_t *d;
+		uint offset;
+
+		//printf("StructLiteralExp.toDt() %s)\n", toChars());
+		dts.setDim(sd.fields.dim);
+		dts.zero();
+		assert(elements.dim <= sd.fields.dim);
+
+		foreach (uint i, Expression e; elements)
+		{
+			if (!e)
+				continue;
+
+			dt = null;
+			e.toDt(&dt);
+			dts.data[i] = dt;
+		}
+
+		offset = 0;
+		foreach (uint j, VarDeclaration v; sd.fields)
+		{
+			d = cast(dt_t*)dts.data[j];
+			if (!d)
+			{   // An instance specific initializer was not provided.
+				// Look to see if there's a default initializer from the
+				// struct definition
+				if (v.init)
+				{
+					d = v.init.toDt();
+				}
+				else if (v.offset >= offset)
+				{
+					uint k;
+					uint offset2 = v.offset + cast(uint)v.type.size();
+					// Make sure this field (v) does not overlap any explicitly
+					// initialized field.
+					for (k = j + 1; 1; k++)
+					{
+						if (k == dts.dim)		// didn't find any overlap
+						{
+							v.type.toDt(&d);
+							break;
+						}
+						VarDeclaration v2 = sd.fields[k];
+
+						if (v2.offset < offset2 && dts.data[k])
+							break;			// overlap
+					}
+				}
+			}
+			if (d)
+			{
+				if (v.offset < offset)
+					error("duplicate union initialization for %s", v.toChars());
+				else
+				{	
+					uint sz = dt_size(d);
+					uint vsz = cast(uint)v.type.size();
+					uint voffset = v.offset;
+					assert(sz <= vsz);
+
+					uint dim = 1;
+					for (Type vt = v.type.toBasetype(); vt.ty == Tsarray; vt = vt.nextOf().toBasetype())
+					{   
+						TypeSArray tsa = cast(TypeSArray)vt;
+						dim *= tsa.dim.toInteger();
+					}
+
+					for (size_t i = 0; i < dim; i++)
+					{
+						if (offset < voffset)
+							pdt = dtnzeros(pdt, voffset - offset);
+						if (!d)
+						{
+							if (v.init)
+								d = v.init.toDt();
+							else
+								v.type.toDt(&d);
+						}
+						pdt = dtcat(pdt, d);
+						d = null;
+						offset = voffset + sz;
+						voffset += vsz / dim;
+						if (sz == vsz)
+							break;
+					}
+				}
+			}
+		}
+		
+		if (offset < sd.structsize)
+			pdt = dtnzeros(pdt, sd.structsize - offset);
+
+		return pdt;
 	}
 
 version(DMDV2)