diff dmd/CompoundStatement.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 3f834bed4f13
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CompoundStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,355 @@
+module dmd.CompoundStatement;
+
+import dmd.Loc;
+import dmd.Statement;
+import dmd.Array;
+import dmd.TryCatchStatement;
+import dmd.TryFinallyStatement;
+import dmd.Catch;
+import dmd.ScopeStatement;
+import dmd.Identifier;
+import dmd.Lexer;
+import dmd.ThrowStatement;
+import dmd.IdentifierExp;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.ReturnStatement;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.InlineDoState;
+import dmd.InlineCostState;
+import dmd.InlineScanState;
+import dmd.IfStatement;
+import dmd.IRState;
+import dmd.BE;
+import dmd.Util;
+
+class CompoundStatement : Statement
+{
+    Statements statements;
+
+    this(Loc loc, Statements s)
+	{
+		super(loc);
+		statements = s;
+	}
+	
+    this(Loc loc, Statement s1, Statement s2)
+	{
+		super(loc);
+		
+		statements = new Statements();
+		statements.reserve(2);
+		statements.push(cast(void*)s1);
+		statements.push(cast(void*)s2);
+	}
+	
+    Statement syntaxCopy()
+	{
+		Statements a = new Statements();
+		a.setDim(statements.dim);
+
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement)statements.data[i];
+			if (s)
+				s = s.syntaxCopy();
+			a.data[i] = cast(void*)s;
+		}
+
+		return new CompoundStatement(loc, a);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+	static int indent = 0;
+	static int depth = 0;
+	
+    Statement semantic(Scope sc)
+	{
+		Statement s;
+
+		//printf("CompoundStatement.semantic(this = %p, sc = %p)\n", this, sc);
+
+		for (size_t i = 0; i < statements.dim; )
+		{
+			s = cast(Statement) statements.data[i];
+			if (s)
+			{   
+				Statements a = s.flatten(sc);
+
+				if (a)
+				{
+					statements.remove(i);
+					statements.insert(i, a);
+					continue;
+				}
+
+				s = s.semantic(sc);
+
+				statements.data[i] = cast(void*)s;
+				if (s)
+				{
+					Statement sentry;
+					Statement sexception;
+					Statement sfinally;
+
+					s.scopeCode(sc, &sentry, &sexception, &sfinally);
+					if (sentry)
+					{
+						sentry = sentry.semantic(sc);
+						if (s.isDeclarationStatement())
+						{	
+							statements.insert(i, cast(void*)sentry);
+							i++;
+						}
+						else
+							statements.data[i] = cast(void*)sentry;
+					}
+					if (sexception)
+					{
+						if (i + 1 == statements.dim && !sfinally)
+						{
+		static if (true) {
+						sexception = sexception.semantic(sc);
+		} else {
+						statements.push(sexception);
+						if (sfinally)
+							// Assume sexception does not throw
+							statements.push(sfinally);
+		}
+						}
+						else
+						{
+							/* Rewrite:
+							 *	s; s1; s2;
+							 * As:
+							 *	s;
+							 *	try { s1; s2; }
+							 *	catch (Object __o)
+							 *	{ sexception; throw __o; }
+							 */
+							Statement body_;
+							Statements aa = new Statements();
+
+							for (int j = i + 1; j < statements.dim; j++)
+							{
+								aa.push(statements.data[j]);
+							}
+							body_ = new CompoundStatement(Loc(0), aa);
+							body_ = new ScopeStatement(Loc(0), body_);
+
+							Identifier id = Lexer.uniqueId("__o");
+
+							Statement handler = new ThrowStatement(Loc(0), new IdentifierExp(Loc(0), id));
+							handler = new CompoundStatement(Loc(0), sexception, handler);
+
+							Array catches = new Array();
+							Catch ctch = new Catch(Loc(0), null, id, handler);
+							catches.push(cast(void*)ctch);
+							s = new TryCatchStatement(Loc(0), body_, catches);
+
+							if (sfinally)
+								s = new TryFinallyStatement(Loc(0), s, sfinally);
+							s = s.semantic(sc);
+							statements.setDim(i + 1);
+							statements.push(cast(void*)s);
+							break;
+						}
+					}
+					else if (sfinally)
+					{
+						if (0 && i + 1 == statements.dim)
+						{
+							statements.push(cast(void*)sfinally);
+						}
+						else
+						{
+							/* Rewrite:
+							 *	s; s1; s2;
+							 * As:
+							 *	s; try { s1; s2; } finally { sfinally; }
+							 */
+							Statement body_;
+							Statements aa = new Statements();
+
+							for (int j = i + 1; j < statements.dim; j++)
+							{
+								aa.push(statements.data[j]);
+							}
+							body_ = new CompoundStatement(Loc(0), aa);
+							s = new TryFinallyStatement(Loc(0), body_, sfinally);
+							s = s.semantic(sc);
+							statements.setDim(i + 1);
+							statements.push(cast(void*)s);
+							break;
+						}
+					}
+				}
+			}
+			i++;
+		}
+		if (statements.dim == 1)
+		{
+			return cast(Statement)statements.data[0];
+		}
+		return this;
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		//printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
+		BE result = BE.BEfallthru;
+		for (size_t i = 0; i < statements.dim; i++)
+		{	Statement s = cast(Statement)statements.data[i];
+			if (s)
+			{
+				//printf("result = x%x\n", result);
+				//printf("%s\n", s->toChars());
+				if (!(result & BE.BEfallthru) && !s.comeFrom())
+				{
+					if (s.blockExit() != BE.BEhalt)
+						s.warning("statement is not reachable");
+				}
+
+				result &= ~BE.BEfallthru;
+				result |= s.blockExit();
+			}
+		}
+
+		return result;
+	}
+	
+    bool comeFrom()
+	{
+		assert(false);
+	}
+	
+    bool isEmpty()
+	{
+		for (int i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement) statements.data[i];
+			if (s && !s.isEmpty())
+				return false;
+		}
+		return true;
+	}
+
+    Statements flatten(Scope sc)
+	{
+		return statements;
+	}
+
+    ReturnStatement isReturnStatement()
+	{
+		ReturnStatement rs = null;
+
+		for (int i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement) statements.data[i];
+			if (s)
+			{
+				rs = s.isReturnStatement();
+				if (rs)
+					break;
+			}
+		}
+		return rs;
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    int inlineCost(InlineCostState* ics)
+	{
+		int cost = 0;
+
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement)statements.data[i];
+			if (s)
+			{
+				cost += s.inlineCost(ics);
+				if (cost >= COST_MAX)
+					break;
+			}
+		}
+
+		return cost;
+	}
+
+    Expression doInline(InlineDoState ids)
+	{
+		Expression e = null;
+
+		//printf("CompoundStatement.doInline() %d\n", statements.dim);
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement)statements.data[i];
+			if (s)
+			{
+				Expression e2 = s.doInline(ids);
+				e = Expression.combine(e, e2);
+				if (s.isReturnStatement())
+					break;
+
+				/* Check for:
+				 *	if (condition)
+				 *	    return exp1;
+				 *	else
+				 *	    return exp2;
+				 */
+				IfStatement ifs = s.isIfStatement();
+				if (ifs && ifs.elsebody && ifs.ifbody &&
+					ifs.ifbody.isReturnStatement() &&
+					ifs.elsebody.isReturnStatement()
+				)
+					break;
+			}
+		}
+		return e;
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement) statements.data[i];
+			if (s)
+				statements.data[i] = cast(void*)s.inlineScan(iss);
+		}
+
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		if (statements)
+		{
+			size_t dim = statements.dim;
+			for (size_t i = 0 ; i < dim ; i++)
+			{
+				Statement s = cast(Statement)statements.data[i];
+				if (s !is null)
+				{
+					s.toIR(irs);
+				}
+			}
+		}
+	}
+
+    CompoundStatement isCompoundStatement() { return this; }
+}
\ No newline at end of file