diff dmd/ArrayInitializer.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 51605de93870
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayInitializer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,373 @@
+module dmd.ArrayInitializer;
+
+import dmd.ArrayTypes;
+import dmd.Type;
+import dmd.TypeNext;
+import dmd.Array;
+import dmd.Loc;
+import dmd.Initializer;
+import dmd.WANT;
+import dmd.Util;
+import dmd.TY;
+import dmd.TypeSArray;
+import dmd.IntegerExp;
+import dmd.Expression;
+import dmd.ArrayLiteralExp;
+import dmd.Scope;
+import dmd.ErrorExp;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.TYM;
+import dmd.backend.Symbol;
+
+class ArrayInitializer : Initializer
+{
+    Expressions index;	// indices
+    Initializers value;	// of Initializer *'s
+    uint dim = 0;		// length of array being initialized
+    Type type = null;	// type that array will be used to initialize
+    int sem = 0;		// !=0 if semantic() is run
+
+    this(Loc loc)
+	{
+		super(loc);
+		index = new Expressions();
+		value = new Initializers();
+	}
+	
+    Initializer syntaxCopy()
+	{
+		//printf("ArrayInitializer.syntaxCopy()\n");
+
+		ArrayInitializer ai = new ArrayInitializer(loc);
+
+		assert(index.dim == value.dim);
+		ai.index.setDim(index.dim);
+		ai.value.setDim(value.dim);
+		for (int i = 0; i < ai.value.dim; i++)
+		{	
+			Expression e = cast(Expression)index.data[i];
+			if (e)
+				e = e.syntaxCopy();
+			ai.index.data[i] = cast(void*)e;
+
+			Initializer init = cast(Initializer)value.data[i];
+			init = init.syntaxCopy();
+			ai.value.data[i] = cast(void*)init;
+		}
+		return ai;
+	}
+	
+    void addInit(Expression index, Initializer value)
+	{
+		this.index.push(cast(void*)index);
+		this.value.push(cast(void*)value);
+		dim = 0;
+		type = null;
+	}
+	
+    Initializer semantic(Scope sc, Type t)
+	{
+		uint i;
+		uint length;
+
+		//printf("ArrayInitializer.semantic(%s)\n", t.toChars());
+		if (sem)				// if semantic() already run
+			return this;
+
+		sem = 1;
+		type = t;
+		t = t.toBasetype();
+		switch (t.ty)
+		{
+			case Tpointer:
+			case Tsarray:
+			case Tarray:
+				break;
+
+			default:
+				error(loc, "cannot use array to initialize %s", type.toChars());
+				return this;
+		}
+
+		length = 0;
+		for (i = 0; i < index.dim; i++)
+		{	
+			Expression idx;
+			Initializer val;
+
+			idx = cast(Expression)index.data[i];
+			if (idx)
+			{   
+				idx = idx.semantic(sc);
+				idx = idx.optimize(WANTvalue | WANTinterpret);
+				index.data[i] = cast(void*)idx;
+				length = cast(uint)idx.toInteger();
+			}
+
+			val = cast(Initializer)value.data[i];
+			val = val.semantic(sc, t.nextOf());
+			value.data[i] = cast(void*)val;
+			length++;
+			if (length == 0)
+				error(loc, "array dimension overflow");
+			if (length > dim)
+				dim = length;
+		}
+		uint amax = 0x80000000;
+		if (cast(uint) (dim * t.nextOf().size()) >= amax)
+			error(loc, "array dimension %u exceeds max of %ju", dim, amax / t.nextOf().size());
+
+		return this;
+	}
+	
+    Type inferType(Scope sc)
+	{
+		//printf("ArrayInitializer.inferType() %s\n", toChars());
+		type = Type.terror;
+		for (size_t i = 0; i < value.dim; i++)
+		{
+			if (index.data[i])
+				goto Lno;
+		}
+
+		for (size_t i = 0; i < value.dim; i++)
+		{
+			Initializer iz = cast(Initializer)value.data[i];
+			if (iz)
+			{   
+				Type t = iz.inferType(sc);
+				if (i == 0)
+				{	
+					t = new TypeSArray(t, new IntegerExp(value.dim));
+					t = t.semantic(loc, sc);
+					type = t;
+				}
+			}
+		}
+		return type;
+
+	Lno:
+		error(loc, "cannot infer type from this array initializer");
+		return Type.terror;
+	}
+
+	/********************************
+	 * If possible, convert array initializer to array literal.
+	 */	
+    Expression toExpression()
+	{
+		Expression e;
+
+		//printf("ArrayInitializer.toExpression(), dim = %d\n", dim);
+		//static int i; if (++i == 2) halt();
+
+		size_t edim;
+		Type t = null;
+		if (type)
+		{
+			t = type.toBasetype();
+			switch (t.ty)
+			{
+				case Tsarray:
+					edim = cast(uint)(cast(TypeSArray)t).dim.toInteger();
+					break;
+
+				case Tpointer:
+				case Tarray:
+					edim = dim;
+					break;
+
+				default:
+					assert(0);
+			}
+		}
+		else
+		{
+			edim = value.dim;
+			for (size_t i = 0, j = 0; i < value.dim; i++, j++)
+			{
+				if (index.data[i])
+					j = cast(uint)(cast(Expression)index.data[i]).toInteger();
+				if (j >= edim)
+					edim = j + 1;
+			}
+		}
+
+		Expressions elements = new Expressions();
+		elements.setDim(edim);
+		for (size_t i = 0, j = 0; i < value.dim; i++, j++)
+		{
+			if (index.data[i])
+				j = cast(uint)(cast(Expression)index.data[i]).toInteger();
+			assert(j < edim);
+			Initializer iz = cast(Initializer)value.data[i];
+			if (!iz)
+				goto Lno;
+			Expression ex = iz.toExpression();
+			if (!ex)
+			{
+				goto Lno;
+			}
+			elements.data[j] = cast(void*)ex;
+		}
+
+		/* Fill in any missing elements with the default initializer
+		 */
+		{
+			Expression init = null;
+			for (size_t i = 0; i < edim; i++)
+			{
+				if (!elements.data[i])
+				{
+					if (!type)
+						goto Lno;
+					if (!init)
+						init = (cast(TypeNext)t).next.defaultInit(Loc(0));
+					elements.data[i] = cast(void*)init;
+				}
+			}
+
+			Expression e2 = new ArrayLiteralExp(loc, elements);
+			e2.type = type;
+			return e2;
+		}
+
+	Lno:
+		delete elements;
+		error(loc, "array initializers as expressions are not allowed");
+		return new ErrorExp();
+	}
+	
+    Initializer toAssocArrayInitializer()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    dt_t* toDt()
+	{
+		//printf("ArrayInitializer.toDt('%s')\n", toChars());
+		Type tb = type.toBasetype();
+		Type tn = tb.nextOf().toBasetype();
+
+		scope Array dts = new Array();
+		uint size;
+		uint length;
+		uint i;
+		dt_t* dt;
+		dt_t* d;
+		dt_t** pdtend;
+
+		//printf("\tdim = %d\n", dim);
+		dts.setDim(dim);
+		dts.zero();
+
+		size = cast(uint)tn.size();
+
+		length = 0;
+		for (i = 0; i < index.dim; i++)
+		{
+			Expression idx;
+			Initializer val;
+
+			idx = cast(Expression)index.data[i];
+			if (idx)
+				length = cast(uint)idx.toInteger();
+			//printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);
+
+			assert(length < dim);
+			val = cast(Initializer)value.data[i];
+			dt = val.toDt();
+			if (dts.data[length])
+				error(loc, "duplicate initializations for index %d", length);
+			dts.data[length] = cast(void*)dt;
+			length++;
+		}
+
+		Expression edefault = tb.nextOf().defaultInit(Loc(0));
+
+		uint n = 1;
+		for (Type tbn = tn; tbn.ty == Tsarray; tbn = tbn.nextOf().toBasetype())
+		{	
+			TypeSArray tsa = cast(TypeSArray)tbn;
+			n *= tsa.dim.toInteger();
+		}
+
+		d = null;
+		pdtend = &d;
+		for (i = 0; i < dim; i++)
+		{
+			dt = cast(dt_t*)dts.data[i];
+			if (dt)
+				pdtend = dtcat(pdtend, dt);
+			else
+			{
+				for (int j = 0; j < n; j++)
+					pdtend = edefault.toDt(pdtend);
+			}
+		}
+		switch (tb.ty)
+		{
+			case Tsarray:
+			{   
+				uint tadim;
+				TypeSArray ta = cast(TypeSArray)tb;
+
+				tadim = cast(uint)ta.dim.toInteger();
+				if (dim < tadim)
+				{
+					if (edefault.isBool(false))
+						// pad out end of array
+						pdtend = dtnzeros(pdtend, size * (tadim - dim));
+					else
+					{
+						for (i = dim; i < tadim; i++)
+						{	
+							for (int j = 0; j < n; j++)
+								pdtend = edefault.toDt(pdtend);
+						}
+					}
+				}
+				else if (dim > tadim)
+				{
+					debug writef("1: ");
+					error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
+				}
+				break;
+			}
+
+			case Tpointer:
+			case Tarray:
+				// Create symbol, and then refer to it
+				Symbol* s = static_sym();
+				s.Sdt = d;
+				outdata(s);
+
+				d = null;
+				if (tb.ty == Tarray)
+					dtdword(&d, dim);
+				dtxoff(&d, s, 0, TYnptr);
+				break;
+
+			default:
+				assert(0);
+		}
+		return d;
+	}
+	
+    dt_t* toDtBit()	// for bit arrays
+	{
+		assert(false);
+	}
+
+    ArrayInitializer isArrayInitializer() { return this; }
+}
\ No newline at end of file