Mercurial > projects > ddmd
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