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 -~----------~----~----~----~------~----~------~--~---