diff --git a/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java b/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java new file mode 100644 index 000000000..7ef479b9e --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java @@ -0,0 +1,111 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.javascript; + +import java.util.List; +import org.teavm.javascript.ast.*; + +/** + * + * @author Alexey Andreev + */ +class BreakToContinueReplacer implements StatementVisitor { + private IdentifiedStatement replacedBreak; + private IdentifiedStatement replacement; + private ContinueStatement replaceBy; + + public BreakToContinueReplacer(IdentifiedStatement replacedBreak, IdentifiedStatement replacement) { + this.replacedBreak = replacedBreak; + this.replacement = replacement; + } + + @Override + public void visit(AssignmentStatement statement) { + } + + public void visitSequence(List statements) { + for (int i = 0; i < statements.size(); ++i) { + Statement stmt = statements.get(i); + stmt.acceptVisitor(this); + if (replaceBy != null) { + statements.set(i, replaceBy); + replaceBy = null; + } + } + } + + @Override + public void visit(SequentialStatement statement) { + visitSequence(statement.getSequence()); + } + + @Override + public void visit(ConditionalStatement statement) { + visitSequence(statement.getConsequent()); + visitSequence(statement.getAlternative()); + } + + @Override + public void visit(SwitchStatement statement) { + for (SwitchClause clause : statement.getClauses()) { + visitSequence(clause.getBody()); + } + visitSequence(statement.getDefaultClause()); + } + + @Override + public void visit(WhileStatement statement) { + visitSequence(statement.getBody()); + } + + @Override + public void visit(BlockStatement statement) { + visitSequence(statement.getBody()); + } + + @Override + public void visit(ForStatement statement) { + } + + @Override + public void visit(BreakStatement statement) { + if (statement.getTarget() == replacedBreak) { + replaceBy = new ContinueStatement(); + replaceBy.setTarget(replacement); + } + } + + @Override + public void visit(ContinueStatement statement) { + } + + @Override + public void visit(ReturnStatement statement) { + } + + @Override + public void visit(ThrowStatement statement) { + } + + @Override + public void visit(IncrementStatement statement) { + } + + @Override + public void visit(InitClassStatement statement) { + } + +} diff --git a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java index 5f3ae485f..3d88cb72d 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -447,6 +447,13 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { @Override public void visit(WhileStatement statement) { + if (statement.getBody().size() == 1 && statement.getBody().get(0) instanceof WhileStatement) { + WhileStatement innerLoop = (WhileStatement)statement.getBody().get(0); + BreakToContinueReplacer replacer = new BreakToContinueReplacer(innerLoop, statement); + replacer.visitSequence(innerLoop.getBody()); + statement.getBody().clear(); + statement.getBody().addAll(innerLoop.getBody()); + } List statements = processSequence(statement.getBody(), true); statement.getBody().clear(); statement.getBody().addAll(statements); @@ -454,6 +461,25 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { statement.getCondition().acceptVisitor(this); statement.setCondition(resultExpr); } + while (true) { + if (!statement.getBody().isEmpty() && statement.getBody().get(0) instanceof ConditionalStatement) { + ConditionalStatement cond = (ConditionalStatement)statement.getBody().get(0); + if (cond.getConsequent().size() == 1 && cond.getConsequent().get(0) instanceof BreakStatement) { + BreakStatement breakStmt = (BreakStatement)cond.getConsequent().get(0); + if (breakStmt.getTarget() == statement) { + statement.getBody().remove(0); + if (statement.getCondition() != null) { + statement.setCondition(Expr.binary(BinaryOperation.AND, statement.getCondition(), + ExprOptimizer.invert(cond.getCondition()))); + } else { + statement.setCondition(ExprOptimizer.invert(cond.getCondition())); + } + continue; + } + } + } + break; + } resultStmt = statement; }