diff dmd/ArrayLiteralExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children cab4c37afb89
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayLiteralExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,363 @@
+module dmd.ArrayLiteralExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.WANT;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.backend.dt_t;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.IntegerExp;
+import dmd.TypeSArray;
+import dmd.TY;
+import dmd.StringExp;
+
+import dmd.expression.Util;
+import dmd.backend.Util;
+import dmd.backend.RTLSYM;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+class ArrayLiteralExp : Expression
+{
+	Expressions elements;
+
+	this(Loc loc, Expressions elements)
+	{
+		super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof);
+		this.elements = elements;
+	}
+
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof);
+		elements = new Expressions();
+		elements.push(cast(void*)e);
+	}
+
+	Expression syntaxCopy()
+	{
+		return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t0 = null;
+
+	version (LOGSEMANTIC) {
+		printf("ArrayLiteralExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			return this;
+
+		// Run semantic() on each element
+		for (int i = 0; i < elements.dim; i++)
+		{	
+			e = cast(Expression)elements.data[i];
+			e = e.semantic(sc);
+			assert(e.type);
+			elements.data[i] = cast(void*)e;
+		}
+
+		expandTuples(elements);
+
+		for (int i = 0; i < elements.dim; i++)
+		{	
+			e = cast(Expression)elements.data[i];
+
+			if (!e.type)
+				error("%s has no value", e.toChars());
+
+			e = resolveProperties(sc, e);
+
+			ubyte committed = 1;
+			if (e.op == TOKstring)
+				committed = (cast(StringExp)e).committed;
+
+			if (!t0)
+			{   
+				t0 = e.type;
+				// Convert any static arrays to dynamic arrays
+				if (t0.ty == Tsarray)
+				{
+					t0 = (cast(TypeSArray)t0).next.arrayOf();
+					e = e.implicitCastTo(sc, t0);
+				}
+			}
+			else
+				e = e.implicitCastTo(sc, t0);
+
+			if (!committed && e.op == TOKstring)
+			{   
+				StringExp se = cast(StringExp)e;
+				se.committed = 0;
+			}
+			elements.data[i] = cast(void*)e;
+		}
+
+		if (!t0)
+			t0 = Type.tvoid;
+		type = new TypeSArray(t0, new IntegerExp(elements.dim));
+		type = type.semantic(loc, sc);
+		return this;
+	}
+
+	bool isBool(bool result)
+	{
+		size_t dim = elements ? elements.dim : 0;
+		return result ? (dim != 0) : (dim == 0);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		size_t dim;
+
+		//printf("ArrayLiteralExp.toElem() %s\n", toChars());
+		if (elements)
+		{
+			scope Expressions args = new Expressions();
+			dim = elements.dim;
+			args.setDim(dim + 1);		// +1 for number of args parameter
+			e = el_long(TYint, dim);
+			args.data[dim] = cast(void*)e;
+			for (size_t i = 0; i < dim; i++)
+			{   
+				Expression el = cast(Expression)elements.data[i];
+				elem* ep = el.toElem(irs);
+
+				if (tybasic(ep.Ety) == TYstruct || tybasic(ep.Ety) == TYarray)
+				{
+					ep = el_una(OPstrpar, TYstruct, ep);
+					ep.Enumbytes = cast(uint)el.type.size();
+				}
+				args.data[dim - (i + 1)] = cast(void *)ep;
+			}
+
+			/* Because the number of parameters can get very large, produce
+			 * a balanced binary tree so we don't blow up the stack in
+			 * the subsequent tree walking code.
+			 */
+			e = el_params(args.data, dim + 1);
+		}
+		else
+		{	
+			dim = 0;
+			e = el_long(TYint, 0);
+		}
+		Type tb = type.toBasetype();
+	static if (true) {
+		e = el_param(e, type.getTypeInfo(null).toElem(irs));
+
+		// call _d_arrayliteralT(ti, dim, ...)
+		e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e);
+	} else {
+		e = el_param(e, el_long(TYint, tb.next.size()));
+
+		// call _d_arrayliteral(size, dim, ...)
+		e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e);
+	}
+		if (tb.ty == Tarray)
+		{
+			e = el_pair(TYullong, el_long(TYint, dim), e);
+		}
+		else if (tb.ty == Tpointer)
+		{
+		}
+		else
+		{
+			e = el_una(OPind,TYstruct,e);
+			e.Enumbytes = cast(uint)type.size();
+		}
+
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		bool f = false;
+
+		for (size_t i = 0; i < elements.dim; i++)
+		{	
+			Expression e = cast(Expression)elements.data[i];
+			f |= e.checkSideEffect(2);
+		}
+		if (flag == 0 && f == false)
+			Expression.checkSideEffect(0);
+
+		return f;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writeByte('[');
+		argsToCBuffer(buf, elements, hgs);
+		buf.writeByte(']');
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		size_t dim = elements ? elements.dim : 0;
+		buf.printf("A%u", dim);
+		for (size_t i = 0; i < dim; i++)
+		{	
+			Expression e = cast(Expression)elements.data[i];
+			e.toMangleBuffer(buf);
+		}
+	}
+
+	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];
+
+				e = e.optimize(WANTvalue | (result & WANTinterpret));
+				elements.data[i] = cast(void*)e;
+			}
+		}
+
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+		MATCH result = MATCHexact;
+
+	static if (false) {
+		printf("ArrayLiteralExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
+		toChars(), type.toChars(), t.toChars());
+	}
+		Type typeb = type.toBasetype();
+		Type tb = t.toBasetype();
+		if ((tb.ty == Tarray || tb.ty == Tsarray) &&
+			(typeb.ty == Tarray || typeb.ty == Tsarray))
+		{
+			if (tb.ty == Tsarray)
+			{   
+				TypeSArray tsa = cast(TypeSArray)tb;
+				if (elements.dim != tsa.dim.toInteger())
+					result = MATCHnomatch;
+			}
+
+			for (int i = 0; i < elements.dim; i++)
+			{
+				Expression e = cast(Expression)elements.data[i];
+				MATCH m = cast(MATCH)e.implicitConvTo(tb.nextOf());
+				if (m < result)
+					result = m;			// remember worst match
+				if (result == MATCHnomatch)
+					break;				// no need to check for worse
+			}
+			return result;
+		}
+		else
+			return Expression.implicitConvTo(t);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	static if (false) {
+		printf("ArrayLiteralExp.castTo(this=%s, type=%s, => %s)\n",
+		toChars(), type.toChars(), t.toChars());
+	}
+		if (type == t)
+			return this;
+		ArrayLiteralExp e = this;
+		Type typeb = type.toBasetype();
+		Type tb = t.toBasetype();
+		if ((tb.ty == Tarray || tb.ty == Tsarray) &&
+			(typeb.ty == Tarray || typeb.ty == Tsarray) &&
+			// Not trying to convert non-void[] to void[]
+			!(tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid))
+		{
+			if (tb.ty == Tsarray)
+			{   
+				TypeSArray tsa = cast(TypeSArray)tb;
+				if (elements.dim != tsa.dim.toInteger())
+					goto L1;
+			}
+
+			e = cast(ArrayLiteralExp)copy();
+			e.elements = cast(Expressions)elements.copy();
+			for (int i = 0; i < elements.dim; i++)
+			{   
+				Expression ex = cast(Expression)elements.data[i];
+				ex = ex.castTo(sc, tb.nextOf());
+				e.elements.data[i] = cast(void*)ex;
+			}
+			e.type = t;
+			return e;
+		}
+		if (tb.ty == Tpointer && typeb.ty == Tsarray)
+		{
+			Type tp = typeb.nextOf().pointerTo();
+			if (!tp.equals(e.type))
+			{   
+				e = cast(ArrayLiteralExp)copy();
+				e.type = tp;
+			}
+		}
+	L1:
+		return e.Expression.castTo(sc, t);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		return 1;	// because it can fail allocating memory
+	}
+}
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + arrayInlineCost(ics, elements);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		ArrayLiteralExp ce = cast(ArrayLiteralExp)copy();
+		ce.elements = arrayExpressiondoInline(elements, ids);
+		return ce;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		Expression e = this;
+
+		//printf("ArrayLiteralExp.inlineScan()\n");
+		arrayInlineScan(iss, elements);
+
+		return e;
+	}
+}
+