Author: sco...@google.com
Date: Thu Jun 11 12:08:45 2009
New Revision: 5540

Modified:
    trunk/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
    trunk/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java

Log:
JsStaticEval now optimizes certain if statements to conditional operators.

if (a()) {b()} else {c()}   -> a()?b():c()

if (a()) {b()}  ->  a()&&b()

if (a()) {} else {b()}  -> a()||b()

Patch by: mmastrac
Suggested by: me
Review by: me

Modified: trunk/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java  (original)
+++ trunk/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java  Thu Jun 11  
12:08:45 2009
@@ -352,32 +352,50 @@
        } 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()".
+          sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+              "Replaced if statement with conditional");
+
+          JsConditional cond = new JsConditional(sourceInfo, x.getIfExpr(),
+              thenExpr, elseExpr);
+          ctx.replaceMe(accept(cond.makeStmt()));
+        } else if (thenIsEmpty && elseExpr != null) {
+          // Convert "if (a()) {} else {b()}" => a()||b().
+          sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+              "Replaced if statement with ||");
+
+          JsBinaryOperation op = new JsBinaryOperation(sourceInfo,
+              JsBinaryOperator.OR, x.getIfExpr(), elseExpr);
+          ctx.replaceMe(accept(op.makeStmt()));
          } else if (thenIsEmpty && !elseIsEmpty) {
-          /*
-           * If the then block is blank, but the else statement has  
statements,
-           * invert the test
-           */
+          // Convert "if (a()) {} else {stuff}" => "if (!a()) {stuff}".
            sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
                "Simplified if with empty then statement");

            JsUnaryOperation negatedOperation = new  
JsPrefixOperation(sourceInfo,
                JsUnaryOperator.NOT, x.getIfExpr());
            JsIf newIf = new JsIf(sourceInfo, negatedOperation, elseStmt,  
null);
-
            ctx.replaceMe(accept(newIf));
+        } else if (elseIsEmpty && thenExpr != null) {
+          // Convert "if (a()) {b()}" => "a()&&b()".
+          sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+              "Replaced if statement with &&");
+
+          JsBinaryOperation op = new JsBinaryOperation(sourceInfo,
+              JsBinaryOperator.AND, x.getIfExpr(), thenExpr);
+          ctx.replaceMe(accept(op.makeStmt()));
          } else if (elseIsEmpty && elseStmt != null) {
-          /*
-           * If the else statement is present but has no effective  
statements,
-           * prune it
-           */
+          // Convert "if (a()) {b()} else {}" => "if (a()) {b()}".
            sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
                "Pruned empty else statement");
-
            JsIf newIf = new JsIf(sourceInfo, x.getIfExpr(), thenStmt, null);
-
            ctx.replaceMe(accept(newIf));
          }
        }
@@ -583,6 +601,26 @@

    public static boolean exec(JsProgram program) {
      return (new JsStaticEval(program)).execImpl();
+  }
+
+  /**
+   * Attempts to extract a single expression from a given statement and  
returns
+   * it. If no such expression exists, returns <code>null</code>.
+   */
+  protected static JsExpression extractExpression(JsStatement stmt) {
+    if (stmt == null) {
+      return null;
+    }
+
+    if (stmt instanceof JsExprStmt) {
+      return ((JsExprStmt) stmt).getExpression();
+    }
+
+    if (stmt instanceof JsBlock && ((JsBlock) stmt).getStatements().size()  
== 1) {
+      return extractExpression(((JsBlock) stmt).getStatements().get(0));
+    }
+
+    return null;
    }

    protected static boolean isEmpty(JsStatement stmt) {

Modified: trunk/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
==============================================================================
--- trunk/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java      
(original)
+++ trunk/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java     Thu Jun 
 
11 12:08:45 2009
@@ -33,8 +33,13 @@
      assertEquals("a();", optimize("if (a()) { }"));
    }

+  public void testIfWithEmptyThenAndElseExpression() throws Exception {
+    assertEquals("a()||b();", optimize("if (a()) { } else { b(); }"));
+  }
+
    public void testIfWithEmptyThenAndElse() throws Exception {
-    assertEquals("if(!a()){b()}", optimize("if (a()) { } else { b(); }"));
+    assertEquals("if(!a()){throw 1}",
+        optimize("if (a()) { } else { throw 1; }"));
    }

    public void testIfWithEmptyThenAndEmptyElse() throws Exception {
@@ -42,7 +47,21 @@
    }

    public void testIfWithThenAndEmptyElse() throws Exception {
-    assertEquals("if(a()){b()}", optimize("if (a()) { b() } else { }"));
+    assertEquals("if(a()){throw 1}", optimize("if (a()) { throw 1; } else  
{ }"));
+  }
+
+  public void testIfWithThenExpressionAndEmptyElse() throws Exception {
+    assertEquals("a()&&b();", optimize("if (a()) { b() } else { }"));
+  }
+
+  public void testIfWithThenExpressionAndElseExpression() throws Exception  
{
+    assertEquals("a()?b():c();", optimize("if (a()) { b() } else { c();  
}"));
+  }
+
+  public void testIfWithThenExpressionAndElseStatement() throws Exception {
+    // This can't be optimized further
+    assertEquals("if(a()){b()}else{throw 1}",
+        optimize("if (a()) { b() } else { throw 1; }"));
    }

    public void testLiteralEqNull() throws Exception {
@@ -66,13 +85,13 @@
      List<JsStatement> expected = JsParser.parse(SourceOrigin.UNKNOWN,
          program.getScope(), new StringReader(js));
      program.getGlobalBlock().getStatements().addAll(expected);
-
+
      // Run the static evaluation over this new program
      JsStaticEval.exec(program);

      TextOutput text = new DefaultTextOutput(true);
      JsVisitor generator = new JsSourceGenerationVisitor(text);
-
+
      generator.accept(program);
      return text.toString();
    }

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to