view dmd/ArrayInitializer.d @ 79:43073c7c7769

updated to 2.035 also implemented a few missing functions still crashes in Import.importAll though
author Trass3r
date Mon, 30 Aug 2010 03:57:51 +0200
parents ef02e2e203c2
children be2ab491772e
line wrap: on
line source

module dmd.ArrayInitializer;

import dmd.ArrayTypes;
import dmd.Type;
import dmd.TypeAArray;
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();
	}
	
    override 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;
	}
	
    override 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;
	}
	
    override 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 Laa;
		}

		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;

	Laa:
		/* It's possibly an associative array initializer
	     */
	    Initializer iz = cast(Initializer)value.data[0];
	    Expression indexinit = cast(Expression)index.data[0];
	    if (iz && indexinit)
		{
			Type t = iz.inferType(sc);
			indexinit = indexinit.semantic(sc);
			Type indext = indexinit.type;
			t = new TypeAArray(t, indext);
			type = t.semantic(loc, sc);
		}
		else
			error(loc, "cannot infer type from this array initializer");
		return type;
	}

	/********************************
	 * If possible, convert array initializer to array literal.
	  * Otherwise return null.
	 */	
    override 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)
		{
			if (type == Type.terror)
			    return new ErrorExp();

			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:
	    return null;
	}
	
    Initializer toAssocArrayInitializer()
	{
		assert(false);
	}
	
    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		assert(false);
	}

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

    override ArrayInitializer isArrayInitializer() { return this; }
}