Refactor JsStaticEval to allow additional simplification when static eval of the condition fails.
Review by: mmastrac
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5542 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
index 98b35a9..113c534 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
@@ -313,81 +313,55 @@
public void endVisit(JsIf x, JsContext<JsStatement> ctx) {
evalBooleanContext.remove(x.getIfExpr());
- JsExpression expr = x.getIfExpr();
- JsStatement thenStmt = x.getThenStmt();
- JsStatement elseStmt = x.getElseStmt();
- if (expr instanceof CanBooleanEval) {
- SourceInfo sourceInfo;
- CanBooleanEval cond = (CanBooleanEval) expr;
- JsStatement onlyStmtToExecute;
- JsStatement removed;
- if (cond.isBooleanTrue()) {
- onlyStmtToExecute = thenStmt;
- removed = elseStmt;
- sourceInfo = makeSourceInfo(x, "Simplified always-true condition");
- } else if (cond.isBooleanFalse()) {
- onlyStmtToExecute = elseStmt;
- removed = thenStmt;
- sourceInfo = makeSourceInfo(x, "Simplified always-false condition");
- } else {
+ JsExpression condExpr = x.getIfExpr();
+ if (condExpr instanceof CanBooleanEval) {
+ if (tryStaticEvalIf(x, (CanBooleanEval) condExpr, ctx)) {
return;
}
- JsBlock block = new JsBlock(sourceInfo);
- block.getStatements().add(expr.makeStmt());
+ }
- if (onlyStmtToExecute != null) {
- // We'll see this if the expression is always false and no else
- block.getStatements().add(onlyStmtToExecute);
- }
+ JsStatement thenStmt = x.getThenStmt();
+ JsStatement elseStmt = x.getElseStmt();
+ boolean thenIsEmpty = isEmpty(thenStmt);
+ boolean elseIsEmpty = isEmpty(elseStmt);
+ JsExpression thenExpr = extractExpression(thenStmt);
+ JsExpression elseExpr = extractExpression(elseStmt);
- JsStatement decls = ensureDeclarations(removed);
- if (decls != null) {
- block.getStatements().add(decls);
- }
- ctx.replaceMe(accept(block));
- } else {
- boolean thenIsEmpty = isEmpty(thenStmt);
- boolean elseIsEmpty = isEmpty(elseStmt);
- JsExpression thenExpr = extractExpression(thenStmt);
- JsExpression elseExpr = extractExpression(elseStmt);
-
- if (thenIsEmpty && elseIsEmpty) {
- // Convert "if (a()) {}" => "a()".
- ctx.replaceMe(expr.makeStmt());
- } else if (thenExpr != null && elseExpr != null) {
- // Convert "if (a()) {b()} else {c()}" => "a()?b():c()".
- JsConditional cond = new JsConditional(makeSourceInfo(x,
- "Replaced if statement with conditional"), x.getIfExpr(),
- thenExpr, elseExpr);
- ctx.replaceMe(accept(cond.makeStmt()));
- } else if (thenIsEmpty && elseExpr != null) {
- // Convert "if (a()) {} else {b()}" => a()||b().
- JsBinaryOperation op = new JsBinaryOperation(makeSourceInfo(x,
- "Replaced if statement with ||"), JsBinaryOperator.OR,
- x.getIfExpr(), elseExpr);
- ctx.replaceMe(accept(op.makeStmt()));
- } else if (thenIsEmpty && !elseIsEmpty) {
- // Convert "if (a()) {} else {stuff}" => "if (!a()) {stuff}".
- JsUnaryOperation negatedOperation = new JsPrefixOperation(
- makeSourceInfo(x, "Simplified if with empty then statement"),
- JsUnaryOperator.NOT, x.getIfExpr());
- JsIf newIf = new JsIf(makeSourceInfo(x,
- "Simplified if with empty then statement"), negatedOperation,
- elseStmt, null);
- ctx.replaceMe(accept(newIf));
- } else if (elseIsEmpty && thenExpr != null) {
- // Convert "if (a()) {b()}" => "a()&&b()".
- JsBinaryOperation op = new JsBinaryOperation(makeSourceInfo(x,
- "Replaced if statement with &&"), JsBinaryOperator.AND,
- x.getIfExpr(), thenExpr);
- ctx.replaceMe(accept(op.makeStmt()));
- } else if (elseIsEmpty && elseStmt != null) {
- // Convert "if (a()) {b()} else {}" => "if (a()) {b()}".
- JsIf newIf = new JsIf(
- makeSourceInfo(x, "Pruned empty else statement"), x.getIfExpr(),
- thenStmt, null);
- ctx.replaceMe(accept(newIf));
- }
+ if (thenIsEmpty && elseIsEmpty) {
+ // Convert "if (a()) {}" => "a()".
+ ctx.replaceMe(condExpr.makeStmt());
+ } else if (thenExpr != null && elseExpr != null) {
+ // Convert "if (a()) {b()} else {c()}" => "a()?b():c()".
+ JsConditional cond = new JsConditional(makeSourceInfo(x,
+ "Replaced if statement with conditional"), x.getIfExpr(), thenExpr,
+ elseExpr);
+ ctx.replaceMe(accept(cond.makeStmt()));
+ } else if (thenIsEmpty && elseExpr != null) {
+ // Convert "if (a()) {} else {b()}" => a()||b().
+ JsBinaryOperation op = new JsBinaryOperation(makeSourceInfo(x,
+ "Replaced if statement with ||"), JsBinaryOperator.OR,
+ x.getIfExpr(), elseExpr);
+ ctx.replaceMe(accept(op.makeStmt()));
+ } else if (thenIsEmpty && !elseIsEmpty) {
+ // Convert "if (a()) {} else {stuff}" => "if (!a()) {stuff}".
+ JsUnaryOperation negatedOperation = new JsPrefixOperation(
+ makeSourceInfo(x, "Simplified if with empty then statement"),
+ JsUnaryOperator.NOT, x.getIfExpr());
+ JsIf newIf = new JsIf(makeSourceInfo(x,
+ "Simplified if with empty then statement"), negatedOperation,
+ elseStmt, null);
+ ctx.replaceMe(accept(newIf));
+ } else if (elseIsEmpty && thenExpr != null) {
+ // Convert "if (a()) {b()}" => "a()&&b()".
+ JsBinaryOperation op = new JsBinaryOperation(makeSourceInfo(x,
+ "Replaced if statement with &&"), JsBinaryOperator.AND,
+ x.getIfExpr(), thenExpr);
+ ctx.replaceMe(accept(op.makeStmt()));
+ } else if (elseIsEmpty && elseStmt != null) {
+ // Convert "if (a()) {b()} else {}" => "if (a()) {b()}".
+ JsIf newIf = new JsIf(makeSourceInfo(x, "Pruned empty else statement"),
+ x.getIfExpr(), thenStmt, null);
+ ctx.replaceMe(accept(newIf));
}
}
@@ -591,6 +565,41 @@
ctx.replaceMe(updated);
}
}
+
+ private boolean tryStaticEvalIf(JsIf x, CanBooleanEval cond,
+ JsContext<JsStatement> ctx) {
+ JsStatement thenStmt = x.getThenStmt();
+ JsStatement elseStmt = x.getElseStmt();
+ if (cond.isBooleanTrue()) {
+ JsBlock block = new JsBlock(makeSourceInfo(x,
+ "Simplified always-true condition"));
+ block.getStatements().add(x.getIfExpr().makeStmt());
+ if (thenStmt != null) {
+ block.getStatements().add(thenStmt);
+ }
+ JsStatement decls = ensureDeclarations(elseStmt);
+ if (decls != null) {
+ block.getStatements().add(decls);
+ }
+ ctx.replaceMe(accept(block));
+ return true;
+ } else if (cond.isBooleanFalse()) {
+ JsBlock block = new JsBlock(makeSourceInfo(x,
+ "Simplified always-false condition"));
+ block.getStatements().add(x.getIfExpr().makeStmt());
+ if (elseStmt != null) {
+ block.getStatements().add(elseStmt);
+ }
+ JsStatement decls = ensureDeclarations(thenStmt);
+ if (decls != null) {
+ block.getStatements().add(decls);
+ }
+ ctx.replaceMe(accept(block));
+ return true;
+ } else {
+ return false;
+ }
+ }
}
public static boolean exec(JsProgram program) {