view dmd/TupleExp.d @ 56:51605de93870

TupleExp.optimize UnrolledLoopStatement.ctor UnrolledLoopStatement.semantic UnrolledLoopStatement.blockExit OrOrExp.checkSideEffect FuncExp.syntaxCopy FuncLiteralDeclaration.syntaxCopy WhileStatement.hasBreak StructInitializer.toExpression StructLiteralExp.ctor StructLiteralExp.optimize BinExp.commonSemanticAssign ModAssignExp.opId Argument.isLazyArray CommaExp.implicitConvTo CommaExp.castTo TypeClass.isBaseOf createTypeInfoArray TypeTuple.getTypeInfoDeclaration TypeInfoTupleDeclaration.ctor TypeNext.constConv XorExp.implicitConvTo TemplateParameter.isTemplateValueParameter
author korDen
date Sat, 21 Aug 2010 14:16:53 +0400
parents ccbc1e0bb3f0
children cab4c37afb89
line wrap: on
line source

module dmd.TupleExp;

import dmd.Expression;
import dmd.TupleDeclaration;
import dmd.backend.elem;
import dmd.InterState;
import dmd.WANT;
import dmd.Type;
import dmd.OutBuffer;
import dmd.Loc;
import dmd.Scope;
import dmd.InlineCostState;
import dmd.IRState;
import dmd.InlineDoState;
import dmd.HdrGenState;
import dmd.InlineScanState;
import dmd.ArrayTypes;
import dmd.TypeExp;
import dmd.TypeTuple;
import dmd.TOK;
import dmd.TY;
import dmd.Dsymbol;
import dmd.DsymbolExp;
import dmd.DYNCAST;
import dmd.expression.Util;

/****************************************
 * Expand tuples.
 */
/+
void expandTuples(Expressions exps)
{
    //printf("expandTuples()\n");
    if (exps)
    {
	for (size_t i = 0; i < exps.dim; i++)
	{   Expression arg = cast(Expression)exps.data[i];
	    if (!arg)
		continue;

	    // Look for tuple with 0 members
	    if (arg.op == TOKtype)
	    {	TypeExp e = cast(TypeExp)arg;
		if (e.type.toBasetype().ty == Ttuple)
		{   TypeTuple tt = cast(TypeTuple)e.type.toBasetype();

		    if (!tt.arguments || tt.arguments.dim == 0)
		    {
			exps.remove(i);
			if (i == exps.dim)
			    return;
			i--;
			continue;
		    }
		}
	    }

	    // Inline expand all the tuples
	    while (arg.op == TOKtuple)
	    {	TupleExp te = cast(TupleExp)arg;

		exps.remove(i);		// remove arg
		exps.insert(i, te.exps);	// replace with tuple contents
		if (i == exps.dim)
		    return;		// empty tuple, no more arguments
		arg = cast(Expression)exps.data[i];
	    }
	}
    }
}
+/
class TupleExp : Expression
{
	Expressions exps;

	this(Loc loc, Expressions exps)
	{
		super(loc, TOKtuple, TupleExp.sizeof);
		
		this.exps = exps;
		this.type = null;
	}

	this(Loc loc, TupleDeclaration tup)
	{
		super(loc, TOKtuple, TupleExp.sizeof);
		exps = new Expressions();
		type = null;

		exps.reserve(tup.objects.dim);
		for (size_t i = 0; i < tup.objects.dim; i++)
		{   
			Object o = cast(Object)tup.objects.data[i];
			if (auto e = cast(Expression)o)
			{
				e = e.syntaxCopy();
				exps.push(cast(void*)e);
			}
			else if (auto s = cast(Dsymbol)o)
			{
				Expression e = new DsymbolExp(loc, s);
				exps.push(cast(void*)e);
			}
			else if (auto t = cast(Type)o)
			{
				Expression e = new TypeExp(loc, t);
				exps.push(cast(void*)e);
			}
			else
			{
				error("%s is not an expression", o.toString());
			}
		}
	}

	Expression syntaxCopy()
	{
		return new TupleExp(loc, arraySyntaxCopy(exps));
	}

	bool equals(Object o)
	{
		TupleExp ne;

		if (this == o)
			return 1;
		if ((cast(Expression)o).op == TOKtuple)
		{
			TupleExp te = cast(TupleExp)o;
			if (exps.dim != te.exps.dim)
				return 0;
			for (size_t i = 0; i < exps.dim; i++)
			{   Expression e1 = cast(Expression)exps.data[i];
				Expression e2 = cast(Expression)te.exps.data[i];

				if (!e1.equals(e2))
					return 0;
			}
			return 1;
		}
		return 0;
	}

	Expression semantic(Scope sc)
	{
		version (LOGSEMANTIC) {
			printf("+TupleExp::semantic(%s)\n", toChars());
		}
		if (type)
			return this;

		// Run semantic() on each argument
		for (size_t i = 0; i < exps.dim; i++)
		{	Expression e = cast(Expression)exps.data[i];

			e = e.semantic(sc);
			if (!e.type)
			{   error("%s has no value", e.toChars());
				e.type = Type.terror;
			}
			exps.data[i] = cast(void *)e;
		}

		expandTuples(exps);
		if (0 && exps.dim == 1)
		{
			return cast(Expression)exps.data[0];
		}
		type = new TypeTuple(exps);
		type = type.semantic(loc, sc);
		//printf("-TupleExp::semantic(%s)\n", toChars());
		return this;
	}

	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		buf.writestring("tuple(");
		argsToCBuffer(buf, exps, hgs);
		buf.writeByte(')');
	}

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

	void checkEscape()
	{
		for (size_t i = 0; i < exps.dim; i++)
		{   Expression e = cast(Expression)exps.data[i];
			e.checkEscape();
		}
	}

	bool checkSideEffect(int flag)
	{
		bool f = false;

		for (int i = 0; i < exps.dim; i++)
		{	Expression e = cast(Expression)exps.data[i];

			f |= e.checkSideEffect(2);
		}
		if (flag == 0 && f == 0)
			Expression.checkSideEffect(0);
		return f;
	}

	Expression optimize(int result)
	{
		for (size_t i = 0; i < exps.dim; i++)
		{   
			Expression e = cast(Expression)exps.data[i];

			e = e.optimize(WANTvalue | (result & WANTinterpret));
			exps.data[i] = cast(void*)e;
		}
		return this;
	}

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

	Expression castTo(Scope sc, Type t)
	{
		assert(false);
	}

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

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

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

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

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