Revision: 6569
Author: cromwellian
Date: Fri Oct 30 14:23:53 2009
Log: Adds patch to JsStaticEval to simplify literal1 + literal2 operations.  
(where literal can be one of: null, boolean, number, string)

Patch by: cromwellian
Review by: bobv


http://code.google.com/p/google-web-toolkit/source/detail?r=6569

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

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java Thu Jun 11  
13:01:57 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java Fri Oct 30  
14:23:53 2009
@@ -33,15 +33,18 @@
  import com.google.gwt.dev.js.ast.JsIf;
  import com.google.gwt.dev.js.ast.JsModVisitor;
  import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
  import com.google.gwt.dev.js.ast.JsPrefixOperation;
  import com.google.gwt.dev.js.ast.JsProgram;
  import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.js.ast.JsStringLiteral;
  import com.google.gwt.dev.js.ast.JsUnaryOperation;
  import com.google.gwt.dev.js.ast.JsUnaryOperator;
  import com.google.gwt.dev.js.ast.JsValueLiteral;
  import com.google.gwt.dev.js.ast.JsVars;
  import com.google.gwt.dev.js.ast.JsVisitor;
  import com.google.gwt.dev.js.ast.JsWhile;
+import com.google.gwt.dev.js.ast.JsBooleanLiteral;
  import com.google.gwt.dev.js.ast.JsVars.JsVar;

  import java.util.ArrayList;
@@ -163,6 +166,8 @@
          trySimplifyEq(x, arg1, arg2, ctx);
        } else if (op == JsBinaryOperator.NEQ) {
          trySimplifyNe(x, arg1, arg2, ctx);
+      } else if (op == JsBinaryOperator.ADD) {
+        trySimplifyAdd(x, arg1, arg2, ctx);
        }
      }

@@ -449,6 +454,22 @@
        return true;
      }

+    private boolean appendLiteral(StringBuilder result, JsValueLiteral  
val) {
+      if (val instanceof JsNumberLiteral) {
+        double number = ((JsNumberLiteral) val).getValue();
+        result.append(fixTrailingZeroes(String.valueOf(number)));
+      } else if (val instanceof JsStringLiteral) {
+        result.append(((JsStringLiteral) val).getValue());
+      } else if (val instanceof JsBooleanLiteral) {
+        result.append(((JsBooleanLiteral) val).getValue());
+      } else if (val instanceof JsNullLiteral) {
+        result.append("null");
+      } else {
+        return false;
+      }
+      return true;
+    }
+
      /**
       * This method MUST be called whenever any statements are removed from  
a
       * function. This is because some statements, such as JsVars or  
JsFunction
@@ -480,6 +501,20 @@
        }
      }

+    /*
+     * String.valueOf(Double) produces trailing .0 on integers which is
+     * incorrect for Javascript which produces conversions to string  
without
+     * trailing zeroes. Without this, int + String will turn out wrong.
+     */
+    private String fixTrailingZeroes(String num) {
+      if (num.endsWith(".0")) {
+        String fixNum = num.substring(0, num.length() - 2);
+        assert Double.parseDouble(fixNum) == Double.parseDouble(num);
+        num = fixNum;
+      }
+      return num;
+    }
+
      private SourceInfo makeSourceInfo(HasSourceInfo x, String m) {
        return x.getSourceInfo().makeChild(StaticEvalVisitor.class, m);
      }
@@ -550,6 +585,30 @@
        return original;
      }

+    /**
+     * Simplify a + b.
+     */
+    private void trySimplifyAdd(JsExpression original, JsExpression arg1,
+        JsExpression arg2, JsContext<JsExpression> ctx) {
+      if (arg1 instanceof JsValueLiteral && arg2 instanceof  
JsValueLiteral) {
+        // case: number + number
+        if (arg1 instanceof JsNumberLiteral &&
+            arg2 instanceof JsNumberLiteral) {
+          ctx.replaceMe(program.getNumberLiteral(
+              ((JsNumberLiteral) arg1).getValue() +
+              ((JsNumberLiteral) arg2).getValue()));
+        } else {
+          // cases: number + string or string + number
+          StringBuilder result = new StringBuilder();
+          if (appendLiteral(result, (JsValueLiteral) arg1) &&
+              appendLiteral(result, (JsValueLiteral) arg2)) {
+             
ctx.replaceMe(program.getStringLiteral(original.getSourceInfo(),
+                result.toString()));
+          }
+        }
+      }
+    }
+
      private void trySimplifyEq(JsExpression original, JsExpression arg1,
          JsExpression arg2, JsContext<JsExpression> ctx) {
        JsExpression updated = simplifyEq(original, arg1, arg2);
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java    Wed  
Oct 28 09:10:53 2009
+++ /trunk/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java    Fri  
Oct 30 14:23:53 2009
@@ -20,6 +20,16 @@
   */
  public class JsStaticEvalTest extends OptimizerTestBase {

+  public void testAddLiterals() throws Exception {
+    assertEquals("alert(42);", optimize("alert(21+21);"));
+    assertEquals("alert('Hello World');",  
optimize("alert('Hello '+'World');"));
+    assertEquals("alert('Hello 42');", optimize("alert('Hello ' + 42);"));
+    assertEquals("alert('42 Hello');", optimize("alert(42 + ' Hello');"));
+    assertEquals("alert('42 Hello');", optimize("alert(42.0 + '  
Hello');"));
+    assertEquals("alert('42.2 Hello');", optimize("alert(42.2 + '  
Hello');"));
+    assertEquals("alert('Hello 42.2');", optimize("alert('Hello ' +  
42.2);"));
+  }
+
    public void testIfWithEmptyThen() throws Exception {
      assertEquals("a();", optimize("if (a()) { }"));
    }

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

Reply via email to