mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
New AST optimization algorithm
This commit is contained in:
parent
d93883296e
commit
16d11909ea
|
@ -53,7 +53,7 @@
|
|||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<minifying>false</minifying>
|
||||
<numThreads>0</numThreads>
|
||||
<numThreads>1</numThreads>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.javascript.ast.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class BlockRefCountVisitor implements StatementVisitor {
|
||||
Map<IdentifiedStatement, Integer> refs = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void visit(AssignmentStatement statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SequentialStatement statement) {
|
||||
for (Statement part : statement.getSequence()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
for (Statement stmt : statement.getConsequent()) {
|
||||
stmt.acceptVisitor(this);
|
||||
}
|
||||
for (Statement stmt : statement.getAlternative()) {
|
||||
stmt.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchStatement statement) {
|
||||
for (SwitchClause clause : statement.getClauses()) {
|
||||
for (Statement part : clause.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
for (Statement part : statement.getDefaultClause()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WhileStatement statement) {
|
||||
refs.put(statement, 0);
|
||||
for (Statement part : statement.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BlockStatement statement) {
|
||||
refs.put(statement, 0);
|
||||
for (Statement part : statement.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ForStatement statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BreakStatement statement) {
|
||||
refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ContinueStatement statement) {
|
||||
refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ReturnStatement statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ThrowStatement statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IncrementStatement statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassStatement statement) {
|
||||
}
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 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 java.util.Map;
|
||||
import org.teavm.javascript.ast.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class ConditionalOptimizer {
|
||||
public Map<IdentifiedStatement, Integer> referencedStatements;
|
||||
public ReadWriteStatsBuilder stats;
|
||||
|
||||
public Statement tryOptimizeElse(BlockStatement stmt) {
|
||||
if (stmt.getBody().isEmpty()) {
|
||||
return stmt;
|
||||
}
|
||||
if (!(stmt.getBody().get(0) instanceof ConditionalStatement)) {
|
||||
return stmt;
|
||||
}
|
||||
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(0);
|
||||
if (condStmt.getAlternative() != null) {
|
||||
return stmt;
|
||||
}
|
||||
if (!(condStmt.getConsequent() instanceof SequentialStatement)) {
|
||||
return stmt;
|
||||
}
|
||||
SequentialStatement condBody = (SequentialStatement)condStmt.getConsequent();
|
||||
if (condBody.getSequence().isEmpty()) {
|
||||
return stmt;
|
||||
}
|
||||
Statement lastStmt = condBody.getSequence().get(condBody.getSequence().size() - 1);
|
||||
if (!(lastStmt instanceof BreakStatement)) {
|
||||
return stmt;
|
||||
}
|
||||
BreakStatement breakStmt = (BreakStatement)lastStmt;
|
||||
if (breakStmt.getTarget() != stmt) {
|
||||
return stmt;
|
||||
}
|
||||
SequentialStatement altBody = new SequentialStatement();
|
||||
for (int j = 1; j < stmt.getBody().size(); ++j) {
|
||||
altBody.getSequence().add(stmt.getBody().get(j));
|
||||
}
|
||||
if (!altBody.getSequence().isEmpty()) {
|
||||
condStmt.setAlternative(altBody.getSequence().size() != 1 ?
|
||||
altBody : altBody.getSequence().get(0));
|
||||
}
|
||||
condBody.getSequence().remove(condBody.getSequence().size() - 1);
|
||||
if (condBody.getSequence().size() == 1) {
|
||||
condStmt.setConsequent(condBody.getSequence().get(0));
|
||||
}
|
||||
stmt.getBody().clear();
|
||||
stmt.getBody().add(condStmt);
|
||||
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||
if (referencedStatements.get(stmt) > 0) {
|
||||
return stmt;
|
||||
} else {
|
||||
return tryMakeInline(condStmt);
|
||||
}
|
||||
}
|
||||
|
||||
public Statement tryOptimize(BlockStatement stmt) {
|
||||
for (int i = 0; i < stmt.getBody().size(); ++i) {
|
||||
if (stmt.getBody().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!(stmt.getBody().get(i) instanceof ConditionalStatement)) {
|
||||
continue;
|
||||
}
|
||||
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(i);
|
||||
if (condStmt.getAlternative() != null) {
|
||||
continue;
|
||||
}
|
||||
if (!(condStmt.getConsequent() instanceof BreakStatement)) {
|
||||
continue;
|
||||
}
|
||||
BreakStatement breakStmt = (BreakStatement)condStmt.getConsequent();
|
||||
if (breakStmt.getTarget() != stmt) {
|
||||
continue;
|
||||
}
|
||||
stmt.getBody().remove(i);
|
||||
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||
ConditionalStatement newCond = new ConditionalStatement();
|
||||
newCond.setCondition(ExprOptimizer.invert(condStmt.getCondition()));
|
||||
List<Statement> remaining = stmt.getBody().subList(i, stmt.getBody().size());
|
||||
if (remaining.size() == 1) {
|
||||
newCond.setConsequent(remaining.get(0));
|
||||
} else {
|
||||
SequentialStatement newConsequent = new SequentialStatement();
|
||||
newConsequent.getSequence().addAll(remaining);
|
||||
newCond.setConsequent(newConsequent);
|
||||
}
|
||||
remaining.clear();
|
||||
stmt.getBody().add(newCond);
|
||||
if (referencedStatements.get(stmt) == 0) {
|
||||
SequentialStatement flat = new SequentialStatement();
|
||||
flat.getSequence().addAll(stmt.getBody());
|
||||
return flat;
|
||||
} else {
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
||||
public void tryOptimize(WhileStatement stmt) {
|
||||
if (stmt.getBody().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!(stmt.getBody().get(0) instanceof ConditionalStatement)) {
|
||||
return;
|
||||
}
|
||||
if (stmt.getCondition() != null) {
|
||||
return;
|
||||
}
|
||||
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(0);
|
||||
if (condStmt.getAlternative() != null) {
|
||||
return;
|
||||
}
|
||||
if (!(condStmt.getConsequent() instanceof BreakStatement)) {
|
||||
return;
|
||||
}
|
||||
BreakStatement breakStmt = (BreakStatement)condStmt.getConsequent();
|
||||
if (breakStmt.getTarget() != stmt) {
|
||||
return;
|
||||
}
|
||||
stmt.getBody().remove(0);
|
||||
stmt.setCondition(ExprOptimizer.invert(condStmt.getCondition()));
|
||||
}
|
||||
|
||||
public Statement tryMakeInline(ConditionalStatement stmt) {
|
||||
if (!(stmt.getConsequent() instanceof AssignmentStatement) ||
|
||||
!(stmt.getAlternative() instanceof AssignmentStatement)) {
|
||||
return stmt;
|
||||
}
|
||||
AssignmentStatement consequent = (AssignmentStatement)stmt.getConsequent();
|
||||
AssignmentStatement alternative = (AssignmentStatement)stmt.getAlternative();
|
||||
if (!(consequent.getLeftValue() instanceof VariableExpr) ||
|
||||
!(alternative.getLeftValue() instanceof VariableExpr)) {
|
||||
return stmt;
|
||||
}
|
||||
VariableExpr consequentLeft = (VariableExpr)consequent.getLeftValue();
|
||||
VariableExpr alternativeLeft = (VariableExpr)alternative.getLeftValue();
|
||||
if (consequentLeft.getIndex() != alternativeLeft.getIndex()) {
|
||||
return stmt;
|
||||
}
|
||||
AssignmentStatement result = new AssignmentStatement();
|
||||
result.setLeftValue(consequentLeft);
|
||||
ConditionalExpr rightValue = new ConditionalExpr();
|
||||
rightValue.setCondition(stmt.getCondition());
|
||||
rightValue.setConsequent(consequent.getRightValue());
|
||||
rightValue.setAlternative(alternative.getRightValue());
|
||||
result.setRightValue(rightValue);
|
||||
stats.writes[consequentLeft.getIndex()]--;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Statement tryOptimizeSwitch(BlockStatement stmt) {
|
||||
if (stmt.getBody().size() < 2) {
|
||||
return stmt;
|
||||
}
|
||||
if (!(stmt.getBody().get(0) instanceof SwitchStatement)) {
|
||||
return stmt;
|
||||
}
|
||||
SwitchStatement switchStmt = (SwitchStatement)stmt.getBody().get(0);
|
||||
Statement last = stmt.getBody().get(stmt.getBody().size() - 1);
|
||||
if (!(last instanceof BreakStatement) && !(last instanceof ContinueStatement) &&
|
||||
!(last instanceof ReturnStatement) && !(last instanceof ThrowStatement)) {
|
||||
return stmt;
|
||||
}
|
||||
SequentialStatement seqStmt = new SequentialStatement();
|
||||
for (int i = 1; i < stmt.getBody().size(); ++i) {
|
||||
seqStmt.getSequence().add(stmt.getBody().get(i));
|
||||
}
|
||||
int count = referencedStatements.get(stmt);
|
||||
ReferenceCountingVisitor refCounter = new ReferenceCountingVisitor(stmt);
|
||||
switchStmt.acceptVisitor(refCounter);
|
||||
if (count > refCounter.count) {
|
||||
return stmt;
|
||||
}
|
||||
referencedStatements.put(stmt, 0);
|
||||
for (SwitchClause clause : switchStmt.getClauses()) {
|
||||
if (!(clause.getStatement() instanceof BreakStatement)) {
|
||||
continue;
|
||||
}
|
||||
BreakStatement breakStmt = (BreakStatement)clause.getStatement();
|
||||
if (breakStmt.getTarget() == stmt) {
|
||||
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||
Integer switchRefs = referencedStatements.get(switchStmt);
|
||||
referencedStatements.put(switchStmt, (switchRefs != null ? switchRefs : 0) + 1);
|
||||
breakStmt.setTarget(switchStmt);
|
||||
} else if (breakStmt.getTarget() == switchStmt) {
|
||||
clause.setStatement(seqStmt);
|
||||
}
|
||||
}
|
||||
if (switchStmt.getDefaultClause() instanceof BreakStatement) {
|
||||
BreakStatement breakStmt = (BreakStatement)switchStmt.getDefaultClause();
|
||||
if (breakStmt.getTarget() == stmt) {
|
||||
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||
Integer switchRefs = referencedStatements.get(switchStmt);
|
||||
referencedStatements.put(switchStmt, (switchRefs != null ? switchRefs : 0) + 1);
|
||||
breakStmt.setTarget(switchStmt);
|
||||
} else if (breakStmt.getTarget() == switchStmt) {
|
||||
switchStmt.setDefaultClause(seqStmt);
|
||||
}
|
||||
}
|
||||
return switchStmt;
|
||||
}
|
||||
}
|
|
@ -27,7 +27,10 @@ public class Optimizer {
|
|||
public void optimize(RegularMethodNode method, Program program) {
|
||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||
stats.analyze(program);
|
||||
BlockRefCountVisitor refsCounter = new BlockRefCountVisitor();
|
||||
method.getBody().acceptVisitor(refsCounter);
|
||||
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
||||
optimizer.referencedStatements = refsCounter.refs;
|
||||
method.getBody().acceptVisitor(optimizer);
|
||||
method.setBody(optimizer.resultStmt);
|
||||
int paramCount = method.getReference().parameterCount();
|
||||
|
|
|
@ -26,15 +26,11 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
public Expr resultExpr;
|
||||
public Statement resultStmt;
|
||||
private ReadWriteStatsBuilder stats;
|
||||
private Map<IdentifiedStatement, IdentifiedStatement> copies = new HashMap<>();
|
||||
private Map<IdentifiedStatement, Integer> referencedStatements = new HashMap<>();
|
||||
private ConditionalOptimizer conditionalOptimizer = new ConditionalOptimizer();
|
||||
Map<IdentifiedStatement, Integer> referencedStatements = new HashMap<>();
|
||||
private List<Statement> resultSequence;
|
||||
|
||||
public OptimizingVisitor(ReadWriteStatsBuilder stats) {
|
||||
this.stats = stats;
|
||||
conditionalOptimizer.referencedStatements = referencedStatements;
|
||||
conditionalOptimizer.stats = stats;
|
||||
}
|
||||
|
||||
private static boolean isZero(Expr expr) {
|
||||
|
@ -83,14 +79,17 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
break;
|
||||
}
|
||||
}
|
||||
resultExpr = Expr.binary(expr.getOperation(), a, b);
|
||||
expr.setFirstOperand(a);
|
||||
expr.setSecondOperand(b);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnaryExpr expr) {
|
||||
expr.getOperand().acceptVisitor(this);
|
||||
Expr operand = resultExpr;
|
||||
resultExpr = Expr.unary(expr.getOperation(), operand);
|
||||
expr.setOperand(operand);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,22 +100,21 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
Expr consequent = resultExpr;
|
||||
expr.getAlternative().acceptVisitor(this);
|
||||
Expr alternative = resultExpr;
|
||||
ConditionalExpr result = new ConditionalExpr();
|
||||
result.setCondition(cond);
|
||||
result.setConsequent(consequent);
|
||||
result.setAlternative(alternative);
|
||||
resultExpr = result;
|
||||
expr.setCondition(cond);
|
||||
expr.setConsequent(consequent);
|
||||
expr.setAlternative(alternative);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstantExpr expr) {
|
||||
resultExpr = Expr.constant(expr.getValue());
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(VariableExpr expr) {
|
||||
int index = expr.getIndex();
|
||||
resultExpr = Expr.var(index);
|
||||
resultExpr = expr;
|
||||
if (stats.reads[index] != 1 || stats.writes[index] != 1) {
|
||||
return;
|
||||
}
|
||||
|
@ -144,16 +142,17 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
Expr index = resultExpr;
|
||||
expr.getArray().acceptVisitor(this);
|
||||
Expr array = resultExpr;
|
||||
resultExpr = Expr.subscript(array, index);
|
||||
expr.setArray(array);
|
||||
expr.setIndex(index);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnwrapArrayExpr expr) {
|
||||
expr.getArray().acceptVisitor(this);
|
||||
Expr arrayExpr = resultExpr;
|
||||
UnwrapArrayExpr result = new UnwrapArrayExpr(expr.getElementType());
|
||||
result.setArray(arrayExpr);
|
||||
resultExpr = result;
|
||||
expr.setArray(arrayExpr);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -163,20 +162,10 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
expr.getArguments().get(i).acceptVisitor(this);
|
||||
args[i] = resultExpr;
|
||||
}
|
||||
switch (expr.getType()) {
|
||||
case STATIC:
|
||||
resultExpr = Expr.invokeStatic(expr.getMethod(), args);
|
||||
break;
|
||||
case DYNAMIC:
|
||||
resultExpr = Expr.invoke(expr.getMethod(), args[0], Arrays.copyOfRange(args, 1, args.length));
|
||||
break;
|
||||
case SPECIAL:
|
||||
resultExpr = Expr.invokeSpecial(expr.getMethod(), args[0], Arrays.copyOfRange(args, 1, args.length));
|
||||
break;
|
||||
case CONSTRUCTOR:
|
||||
resultExpr = Expr.constructObject(expr.getMethod(), args);
|
||||
break;
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
expr.getArguments().set(i, args[i]);
|
||||
}
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
private boolean tryApplyConstructor(InvocationExpr expr) {
|
||||
|
@ -220,42 +209,43 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
public void visit(QualificationExpr expr) {
|
||||
expr.getQualified().acceptVisitor(this);
|
||||
Expr qualified = resultExpr;
|
||||
resultExpr = Expr.qualify(qualified, expr.getField());
|
||||
expr.setQualified(qualified);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewExpr expr) {
|
||||
resultExpr = Expr.createObject(expr.getConstructedClass());
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewArrayExpr expr) {
|
||||
expr.getLength().acceptVisitor(this);
|
||||
Expr length = resultExpr;
|
||||
resultExpr = Expr.createArray(expr.getType(), length);
|
||||
expr.setLength(length);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewMultiArrayExpr expr) {
|
||||
NewMultiArrayExpr result = new NewMultiArrayExpr();
|
||||
result.setType(expr.getType());
|
||||
for (Expr dimension : expr.getDimensions()) {
|
||||
for (int i = 0; i < expr.getDimensions().size(); ++i) {
|
||||
Expr dimension = expr.getDimensions().get(i);
|
||||
dimension.acceptVisitor(this);
|
||||
result.getDimensions().add(resultExpr);
|
||||
expr.getDimensions().set(i, resultExpr);
|
||||
}
|
||||
resultExpr = result;
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InstanceOfExpr expr) {
|
||||
expr.getExpr().acceptVisitor(this);
|
||||
Expr value = resultExpr;
|
||||
resultExpr = Expr.instanceOf(value, expr.getType());
|
||||
expr.setExpr(resultExpr);
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StaticClassExpr expr) {
|
||||
resultExpr = Expr.staticClass(expr.getType());
|
||||
resultExpr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -266,7 +256,8 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
tryApplyConstructor((InvocationExpr)resultExpr)) {
|
||||
resultStmt = new SequentialStatement();
|
||||
} else {
|
||||
resultStmt = Statement.assign(null, resultExpr);
|
||||
statement.setRightValue(resultExpr);
|
||||
resultStmt = statement;
|
||||
}
|
||||
} else {
|
||||
statement.getRightValue().acceptVisitor(this);
|
||||
|
@ -276,7 +267,9 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
statement.getLeftValue().acceptVisitor(this);
|
||||
left = resultExpr;
|
||||
}
|
||||
resultStmt = Statement.assign(left, right);
|
||||
statement.setLeftValue(left);
|
||||
statement.setRightValue(right);
|
||||
resultStmt = statement;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,14 +279,21 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
if (strict) {
|
||||
resultSequence = result;
|
||||
}
|
||||
for (Statement part : statements) {
|
||||
outer: for (int i = 0; i < statements.size(); ++i) {
|
||||
Statement part = statements.get(i);
|
||||
part.acceptVisitor(this);
|
||||
if (resultStmt != null) {
|
||||
List<Statement> newStatements = new ArrayList<>();
|
||||
if (resultStmt instanceof SequentialStatement) {
|
||||
newStatements.addAll(((SequentialStatement)resultStmt).getSequence());
|
||||
} else {
|
||||
newStatements.add(resultStmt);
|
||||
}
|
||||
for (int j = 0; j < newStatements.size(); ++j) {
|
||||
Statement newStatement = newStatements.get(j);
|
||||
resultSequence = result;
|
||||
if (resultStmt instanceof SequentialStatement) {
|
||||
result.addAll(((SequentialStatement)resultStmt).getSequence());
|
||||
} else {
|
||||
result.add(resultStmt);
|
||||
result.add(newStatement);
|
||||
if (newStatement instanceof BreakStatement) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,118 +301,168 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
return result;
|
||||
}
|
||||
|
||||
private void eliminateRedundantBreaks(List<Statement> statements, Set<IdentifiedStatement> currentExits,
|
||||
Set<IdentifiedStatement> exits) {
|
||||
if (statements.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Statement last = statements.get(statements.size() - 1);
|
||||
if (last instanceof BreakStatement) {
|
||||
IdentifiedStatement target = ((BreakStatement)last).getTarget();
|
||||
if (exits.contains(target)) {
|
||||
statements.remove(statements.size() - 1);
|
||||
}
|
||||
}
|
||||
if (statements.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Set<IdentifiedStatement> nestedExits = new HashSet<>();
|
||||
nestedExits.addAll(currentExits);
|
||||
for (int i = 0; i < statements.size(); ++i) {
|
||||
if (i == statements.size() - 1) {
|
||||
nestedExits.addAll(exits);
|
||||
}
|
||||
Statement stmt = statements.get(i);
|
||||
if (stmt instanceof ConditionalStatement) {
|
||||
ConditionalStatement cond = (ConditionalStatement)stmt;
|
||||
last = cond.getConsequent().get(cond.getConsequent().size() - 1);
|
||||
if (last instanceof BreakStatement) {
|
||||
BreakStatement breakStmt = (BreakStatement)last;
|
||||
if (currentExits.contains(breakStmt.getTarget()) || exits.contains(breakStmt.getTarget())) {
|
||||
int refs = referencedStatements.get(breakStmt.getTarget());
|
||||
referencedStatements.put(breakStmt.getTarget(), refs - 1);
|
||||
cond.getConsequent().remove(cond.getConsequent().size() - 1);
|
||||
List<Statement> remaining = statements.subList(i + 1, statements.size());
|
||||
cond.getAlternative().addAll(remaining);
|
||||
remaining.clear();
|
||||
visit(cond);
|
||||
if (resultStmt == cond) {
|
||||
eliminateRedundantBreaks(cond.getConsequent(),
|
||||
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||
eliminateRedundantBreaks(cond.getAlternative(),
|
||||
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||
} else {
|
||||
statements.set(i, resultStmt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
last = cond.getAlternative().isEmpty() ? null :
|
||||
cond.getAlternative().get(cond.getAlternative().size() - 1);
|
||||
if (last instanceof BreakStatement) {
|
||||
BreakStatement breakStmt = (BreakStatement)last;
|
||||
if (currentExits.contains(breakStmt.getTarget()) || exits.contains(breakStmt.getTarget())) {
|
||||
int refs = referencedStatements.get(breakStmt.getTarget());
|
||||
referencedStatements.put(breakStmt.getTarget(), refs - 1);
|
||||
cond.getAlternative().remove(cond.getConsequent().size() - 1);
|
||||
List<Statement> remaining = statements.subList(i + 1, statements.size());
|
||||
cond.getConsequent().addAll(remaining);
|
||||
remaining.clear();
|
||||
visit(cond);
|
||||
if (resultStmt == cond) {
|
||||
eliminateRedundantBreaks(cond.getConsequent(),
|
||||
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||
eliminateRedundantBreaks(cond.getAlternative(),
|
||||
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||
}
|
||||
statements.set(i, resultStmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (stmt instanceof BlockStatement) {
|
||||
BlockStatement nestedBlock = (BlockStatement)stmt;
|
||||
eliminateRedundantBreaks(nestedBlock.getBody(),
|
||||
Collections.<IdentifiedStatement>singleton(nestedBlock), nestedExits);
|
||||
} else if (stmt instanceof WhileStatement) {
|
||||
WhileStatement whileStmt = (WhileStatement)stmt;
|
||||
eliminateRedundantBreaks(whileStmt.getBody(), Collections.<IdentifiedStatement>emptySet(),
|
||||
Collections.<IdentifiedStatement>emptySet());
|
||||
} else if (stmt instanceof SwitchStatement) {
|
||||
SwitchStatement switchStmt = (SwitchStatement)stmt;
|
||||
for (SwitchClause clause : switchStmt.getClauses()) {
|
||||
eliminateRedundantBreaks(clause.getBody(), Collections.<IdentifiedStatement>emptySet(),
|
||||
Collections.<IdentifiedStatement>emptySet());
|
||||
}
|
||||
eliminateRedundantBreaks(switchStmt.getDefaultClause(), null,
|
||||
Collections.<IdentifiedStatement>emptySet());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SequentialStatement statement) {
|
||||
List<Statement> statements = processSequence(statement.getSequence(), false);
|
||||
if (statements.isEmpty()) {
|
||||
resultStmt = null;
|
||||
return;
|
||||
}
|
||||
if (statements.size() == 1) {
|
||||
resultStmt = statements.get(0);
|
||||
} else {
|
||||
SequentialStatement result = new SequentialStatement();
|
||||
result.getSequence().addAll(statements);
|
||||
resultStmt = result;
|
||||
statement.getSequence().clear();
|
||||
statement.getSequence().addAll(statements);
|
||||
resultStmt = statement;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
Expr predicate = resultExpr;
|
||||
List<Statement> sequenceBackup = resultSequence;
|
||||
resultSequence = new ArrayList<>();
|
||||
statement.getConsequent().acceptVisitor(this);
|
||||
Statement consequent = resultStmt;
|
||||
Statement alternative = null;
|
||||
if (statement.getAlternative() != null) {
|
||||
statement.getAlternative().acceptVisitor(this);
|
||||
alternative = resultStmt;
|
||||
statement.setCondition(resultExpr);
|
||||
List<Statement> consequent = processSequence(statement.getConsequent(), true);
|
||||
List<Statement> alternative = processSequence(statement.getAlternative(), true);
|
||||
if (consequent.isEmpty()) {
|
||||
consequent.addAll(alternative);
|
||||
alternative.clear();
|
||||
statement.setCondition(ExprOptimizer.invert(statement.getCondition()));
|
||||
}
|
||||
if (consequent == null) {
|
||||
if (alternative != null) {
|
||||
Statement tmp = alternative;
|
||||
alternative = consequent;
|
||||
consequent = tmp;
|
||||
predicate = ExprOptimizer.invert(predicate);
|
||||
} else {
|
||||
consequent = Statement.empty();
|
||||
}
|
||||
if (consequent.isEmpty()) {
|
||||
resultStmt = Statement.empty();
|
||||
return;
|
||||
}
|
||||
resultStmt = conditionalOptimizer.tryMakeInline(
|
||||
(ConditionalStatement)Statement.cond(predicate, consequent, alternative));
|
||||
resultSequence = sequenceBackup;
|
||||
}
|
||||
|
||||
private void visitIdentified(IdentifiedStatement stmt, IdentifiedStatement copy) {
|
||||
copies.put(stmt, copy);
|
||||
statement.getConsequent().clear();
|
||||
statement.getConsequent().addAll(consequent);
|
||||
statement.getAlternative().clear();
|
||||
statement.getAlternative().addAll(alternative);
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchStatement statement) {
|
||||
SwitchStatement result = new SwitchStatement();
|
||||
result.setId(statement.getId());
|
||||
visitIdentified(statement, result);
|
||||
statement.getValue().acceptVisitor(this);
|
||||
result.setValue(resultExpr);
|
||||
statement.setValue(resultExpr);
|
||||
for (SwitchClause clause : statement.getClauses()) {
|
||||
clause.getStatement().acceptVisitor(this);
|
||||
SwitchClause resultClause = new SwitchClause();
|
||||
resultClause.setConditions(clause.getConditions());
|
||||
resultClause.setStatement(resultStmt != null ? resultStmt : Statement.empty());
|
||||
result.getClauses().add(resultClause);
|
||||
List<Statement> newBody = processSequence(clause.getBody(), true);
|
||||
clause.getBody().clear();
|
||||
clause.getBody().addAll(newBody);
|
||||
}
|
||||
if (statement.getDefaultClause() != null) {
|
||||
statement.getDefaultClause().acceptVisitor(this);
|
||||
} else {
|
||||
resultStmt = null;
|
||||
}
|
||||
result.setDefaultClause(resultStmt != null ? resultStmt : Statement.empty());
|
||||
resultStmt = result;
|
||||
List<Statement> newDefault = processSequence(statement.getDefaultClause(), true);
|
||||
statement.getDefaultClause().clear();
|
||||
statement.getDefaultClause().addAll(newDefault);
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WhileStatement statement) {
|
||||
WhileStatement result = new WhileStatement();
|
||||
result.setId(statement.getId());
|
||||
visitIdentified(statement, result);
|
||||
List<Statement> statements = processSequence(statement.getBody(), true);
|
||||
statement.getBody().clear();
|
||||
statement.getBody().addAll(statements);
|
||||
if (statement.getCondition() != null) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
result.setCondition(resultExpr);
|
||||
} else {
|
||||
result.setCondition(null);
|
||||
statement.setCondition(resultExpr);
|
||||
}
|
||||
result.getBody().addAll(statements);
|
||||
conditionalOptimizer.tryOptimize(result);
|
||||
resultStmt = result;
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BlockStatement statement) {
|
||||
BlockStatement result = new BlockStatement();
|
||||
result.setId(statement.getId());
|
||||
visitIdentified(statement, result);
|
||||
List<Statement> statements = processSequence(statement.getBody(), false);
|
||||
result.getBody().addAll(statements);
|
||||
if (referencedStatements.containsKey(result)) {
|
||||
resultStmt = conditionalOptimizer.tryOptimize(result);
|
||||
eliminateRedundantBreaks(statements, Collections.<IdentifiedStatement>singleton(statement),
|
||||
Collections.<IdentifiedStatement>emptySet());
|
||||
if (referencedStatements.get(statement).equals(0)) {
|
||||
SequentialStatement result = new SequentialStatement();
|
||||
result.getSequence().addAll(statements);
|
||||
resultStmt = result;
|
||||
} else {
|
||||
SequentialStatement altResult = new SequentialStatement();
|
||||
altResult.getSequence().addAll(result.getBody());
|
||||
resultStmt = altResult;
|
||||
}
|
||||
if (resultStmt instanceof BlockStatement) {
|
||||
resultStmt = conditionalOptimizer.tryOptimizeElse((BlockStatement)resultStmt);
|
||||
}
|
||||
if (resultStmt instanceof BlockStatement) {
|
||||
resultStmt = conditionalOptimizer.tryOptimizeSwitch((BlockStatement)resultStmt);
|
||||
}
|
||||
if (resultStmt instanceof ConditionalStatement) {
|
||||
ConditionalStatement conditional = (ConditionalStatement)resultStmt;
|
||||
conditional.getCondition().acceptVisitor(this);
|
||||
conditional.setCondition(resultExpr);
|
||||
statement.getBody().clear();
|
||||
statement.getBody().addAll(statements);
|
||||
resultStmt = statement;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,48 +472,28 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(BreakStatement statement) {
|
||||
BreakStatement result = new BreakStatement();
|
||||
if (statement.getTarget() != null) {
|
||||
IdentifiedStatement targetCopy = copies.get(statement.getTarget());
|
||||
result.setTarget(targetCopy);
|
||||
Integer refCount = referencedStatements.get(targetCopy);
|
||||
if (refCount == null) {
|
||||
refCount = 0;
|
||||
}
|
||||
referencedStatements.put(targetCopy, refCount + 1);
|
||||
}
|
||||
resultStmt = result;
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ContinueStatement statement) {
|
||||
ContinueStatement result = new ContinueStatement();
|
||||
if (statement.getTarget() != null) {
|
||||
IdentifiedStatement targetCopy = copies.get(statement.getTarget());
|
||||
result.setTarget(targetCopy);
|
||||
Integer refCount = referencedStatements.get(targetCopy);
|
||||
if (refCount == null) {
|
||||
refCount = 0;
|
||||
}
|
||||
referencedStatements.put(targetCopy, refCount + 1);
|
||||
}
|
||||
resultStmt = result;
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ReturnStatement statement) {
|
||||
if (statement.getResult() == null) {
|
||||
resultStmt = Statement.exitFunction(null);
|
||||
} else {
|
||||
if (statement.getResult() != null) {
|
||||
statement.getResult().acceptVisitor(this);
|
||||
resultStmt = Statement.exitFunction(resultExpr);
|
||||
statement.setResult(resultExpr);
|
||||
}
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ThrowStatement statement) {
|
||||
statement.getException().acceptVisitor(this);
|
||||
resultStmt = Statement.raiseException(resultExpr);
|
||||
statement.setException(resultExpr);
|
||||
resultStmt = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -42,18 +42,24 @@ class ReferenceCountingVisitor implements StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
statement.getConsequent().acceptVisitor(this);
|
||||
if (statement.getAlternative() != null) {
|
||||
statement.getAlternative().acceptVisitor(this);
|
||||
for (Statement part : statement.getConsequent()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
for (Statement part : statement.getAlternative()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchStatement statement) {
|
||||
for (SwitchClause clause : statement.getClauses()) {
|
||||
clause.getStatement().acceptVisitor(this);
|
||||
for (Statement part : clause.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
for (Statement part : statement.getDefaultClause()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
statement.getDefaultClause().acceptVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -388,10 +388,14 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
writer.append("if").ws().append("(");
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
writer.append(")").ws().append("{").softNewLine().indent();
|
||||
statement.getConsequent().acceptVisitor(this);
|
||||
if (statement.getAlternative() != null) {
|
||||
for (Statement part : statement.getConsequent()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
if (!statement.getAlternative().isEmpty()) {
|
||||
writer.outdent().append("}").ws().append("else").ws().append("{").indent().softNewLine();
|
||||
statement.getAlternative().acceptVisitor(this);
|
||||
for (Statement part : statement.getAlternative()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
writer.outdent().append("}").softNewLine();
|
||||
} catch (IOException e) {
|
||||
|
@ -413,12 +417,16 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
writer.append("case ").append(condition).append(":").softNewLine();
|
||||
}
|
||||
writer.indent();
|
||||
clause.getStatement().acceptVisitor(this);
|
||||
for (Statement part : clause.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
writer.outdent();
|
||||
}
|
||||
if (statement.getDefaultClause() != null) {
|
||||
writer.append("default:").softNewLine().indent();
|
||||
statement.getDefaultClause().acceptVisitor(this);
|
||||
for (Statement part : statement.getDefaultClause()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
writer.outdent();
|
||||
}
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
|
|
@ -413,10 +413,16 @@ class StatementGenerator implements InstructionVisitor {
|
|||
conditions[i] = conditionList.get(i);
|
||||
}
|
||||
clause.setConditions(conditions);
|
||||
clause.setStatement(generateJumpStatement(stmt, target));
|
||||
Statement jumpStmt = generateJumpStatement(stmt, target);
|
||||
if (jumpStmt != null) {
|
||||
clause.getBody().add(jumpStmt);
|
||||
}
|
||||
stmt.getClauses().add(clause);
|
||||
}
|
||||
stmt.setDefaultClause(generateJumpStatement(insn.getDefaultTarget()));
|
||||
Statement breakStmt = generateJumpStatement(insn.getDefaultTarget());
|
||||
if (breakStmt != null) {
|
||||
stmt.getDefaultClause().add(breakStmt);
|
||||
}
|
||||
statements.add(stmt);
|
||||
}
|
||||
|
||||
|
@ -605,13 +611,9 @@ class StatementGenerator implements InstructionVisitor {
|
|||
private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) {
|
||||
Statement consequent = generateJumpStatement(consequentBlock);
|
||||
Statement alternative = generateJumpStatement(alternativeBlock);
|
||||
if (consequent == null) {
|
||||
consequent = Statement.empty();
|
||||
}
|
||||
if (alternative == null) {
|
||||
alternative = Statement.empty();
|
||||
}
|
||||
statements.add(Statement.cond(condition, consequent, alternative));
|
||||
statements.add(Statement.cond(condition,
|
||||
consequent != null ? Arrays.asList(consequent) : Collections.<Statement>emptyList(),
|
||||
alternative != null ? Arrays.asList(alternative) : Collections.<Statement>emptyList()));
|
||||
}
|
||||
|
||||
private Expr compare(BinaryOperation op, Variable value) {
|
||||
|
|
|
@ -61,9 +61,11 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
|
|||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
statement.getConsequent().acceptVisitor(this);
|
||||
if (statement.getAlternative() != null) {
|
||||
statement.getAlternative().acceptVisitor(this);
|
||||
for (Statement part : statement.getConsequent()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
for (Statement part : statement.getAlternative()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,9 +73,13 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
|
|||
public void visit(SwitchStatement statement) {
|
||||
statement.getValue().acceptVisitor(this);
|
||||
for (SwitchClause clause : statement.getClauses()) {
|
||||
clause.getStatement().acceptVisitor(this);
|
||||
for (Statement part : clause.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
for (Statement part : statement.getDefaultClause()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
statement.getDefaultClause().acceptVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2011 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.
|
||||
|
@ -15,14 +15,17 @@
|
|||
*/
|
||||
package org.teavm.javascript.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class ConditionalStatement extends Statement {
|
||||
private Expr condition;
|
||||
private Statement consequent;
|
||||
private Statement alternative;
|
||||
private List<Statement> consequent = new ArrayList<>();
|
||||
private List<Statement> alternative = new ArrayList<>();
|
||||
|
||||
public Expr getCondition() {
|
||||
return condition;
|
||||
|
@ -32,22 +35,14 @@ public class ConditionalStatement extends Statement {
|
|||
this.condition = condition;
|
||||
}
|
||||
|
||||
public Statement getConsequent() {
|
||||
public List<Statement> getConsequent() {
|
||||
return consequent;
|
||||
}
|
||||
|
||||
public void setConsequent(Statement consequent) {
|
||||
this.consequent = consequent;
|
||||
}
|
||||
|
||||
public Statement getAlternative() {
|
||||
public List<Statement> getAlternative() {
|
||||
return alternative;
|
||||
}
|
||||
|
||||
public void setAlternative(Statement alternative) {
|
||||
this.alternative = alternative;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(StatementVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
|
|
|
@ -119,9 +119,11 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
|
|||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
statement.getConsequent().acceptVisitor(this);
|
||||
if (statement.getAlternative() != null) {
|
||||
statement.getAlternative().acceptVisitor(this);
|
||||
for (Statement part : statement.getConsequent()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
for (Statement part : statement.getAlternative()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,10 +131,12 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
|
|||
public void visit(SwitchStatement statement) {
|
||||
statement.getValue().acceptVisitor(this);
|
||||
for (SwitchClause clause : statement.getClauses()) {
|
||||
clause.getStatement().acceptVisitor(this);
|
||||
for (Statement part : clause.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
if (statement.getDefaultClause() != null) {
|
||||
statement.getDefaultClause().acceptVisitor(this);
|
||||
for (Statement part : statement.getDefaultClause()) {
|
||||
part.acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package org.teavm.javascript.ast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
|
@ -52,16 +55,16 @@ public abstract class Statement {
|
|||
return stmt;
|
||||
}
|
||||
|
||||
public static Statement cond(Expr predicate, Statement consequent, Statement alternative) {
|
||||
public static Statement cond(Expr predicate, List<Statement> consequent, List<Statement> alternative) {
|
||||
ConditionalStatement statement = new ConditionalStatement();
|
||||
statement.setCondition(predicate);
|
||||
statement.setConsequent(consequent);
|
||||
statement.setAlternative(alternative);
|
||||
statement.getConsequent().addAll(consequent);
|
||||
statement.getAlternative().addAll(alternative);
|
||||
return statement;
|
||||
}
|
||||
|
||||
public static Statement cond(Expr predicate, Statement consequent) {
|
||||
return cond(predicate, consequent, null);
|
||||
public static Statement cond(Expr predicate, List<Statement> consequent) {
|
||||
return cond(predicate, consequent, Collections.<Statement>emptyList());
|
||||
}
|
||||
|
||||
public static Statement initClass(String className) {
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
*/
|
||||
package org.teavm.javascript.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -23,7 +25,7 @@ import java.util.Arrays;
|
|||
*/
|
||||
public class SwitchClause {
|
||||
private int[] conditions;
|
||||
private Statement statement;
|
||||
private List<Statement> body = new ArrayList<>();
|
||||
|
||||
public int[] getConditions() {
|
||||
return conditions != null ? Arrays.copyOf(conditions, conditions.length) : null;
|
||||
|
@ -33,11 +35,7 @@ public class SwitchClause {
|
|||
this.conditions = conditions != null ? Arrays.copyOf(conditions, conditions.length) : null;
|
||||
}
|
||||
|
||||
public Statement getStatement() {
|
||||
return statement;
|
||||
}
|
||||
|
||||
public void setStatement(Statement statement) {
|
||||
this.statement = statement;
|
||||
public List<Statement> getBody() {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,20 +25,16 @@ import java.util.List;
|
|||
public class SwitchStatement extends IdentifiedStatement {
|
||||
private Expr value;
|
||||
private List<SwitchClause> clauses = new ArrayList<>();
|
||||
private Statement defaultClause;
|
||||
private List<Statement> defaultClause = new ArrayList<>();
|
||||
|
||||
public List<SwitchClause> getClauses() {
|
||||
return clauses;
|
||||
}
|
||||
|
||||
public Statement getDefaultClause() {
|
||||
public List<Statement> getDefaultClause() {
|
||||
return defaultClause;
|
||||
}
|
||||
|
||||
public void setDefaultClause(Statement defaultClause) {
|
||||
this.defaultClause = defaultClause;
|
||||
}
|
||||
|
||||
public Expr getValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user