if (stmts.isEmpty()) { return null; }
boolean changed = false;
boolean progress;
do {
progress = false;
Statement last = stmts.get(0);
for (int i = 1, n = stmts.size(); i < n; ++i) {
Statement next = stmts.get(i);
if (isExpressionListTerminator(next) && last instanceof Conditional) {
// Handle cases like
// if (baz) return boo(); return far();
// where the statement following the if, is implicitly an else
// statement since the if always returns or throws.
// We create a fake conditional, and try to optimize it in isolation,
// which would yield (return baz ? boo() : far()) for the above.
// This feeds into the tail handling for expression runs below.
Conditional combined = condAndImplicitElse((Conditional) last, next);
if (combined != null) {
ParseTreeNode optCond = optimize(combined, false);
if (isExpressionListTerminator(optCond)) {
stmts.subList(i - 1, i + 1).clear();
stmts.add(i - 1, last = (Statement) optCond);
--n;
--i;
progress = true;
continue;
}
}
}
last = next;
}
// Turning adjacent statements into comma operations replaces semis with
// commas, and lets us eliminate a lot more brackets. It also enables
// better conditional/return statement optimizations.
int firstExprStmt = -1;
for (int i = 0, n = stmts.size(); ; ++i) {
Statement s = i != n ? stmts.get(i) : null;
if (firstExprStmt != -1 && (i == n || !(s instanceof ExpressionStmt))) {
// We've finished a run of ExpressionStmts
int start = firstExprStmt;
int end = i;
firstExprStmt = -1;
if (isExpressionListTerminator(s)) {
// We can combine the child onto it, a la
// { foo(); return bar(); } -> { return foo(), bar(); }
++end;
}
if (end - start >= 2) {
progress = true;
Expression joined = null;
for (Statement toJoin : stmts.subList(start, end)) {
List<? extends ParseTreeNode> tjChildren = toJoin.children();
// tjChildren can be empty for return statements that implicitly
// return undefined.
Expression e = tjChildren.isEmpty()
? undef(FilePosition.endOf(toJoin.getFilePosition()))
: (Expression) tjChildren.get(0);
joined = joined == null ? e : commaOp(joined, e);
}
Statement newChild;
assert joined != null; // because start < end, loop assigns it
FilePosition exprPos = joined.getFilePosition();
if (s instanceof ReturnStmt) {
newChild = new ReturnStmt(exprPos, joined);
} else if (s instanceof ThrowStmt) {