*/
private boolean trySimplifyAssociativeExpression(JsBinaryOperation x,
JsContext<JsExpression> ctx) {
boolean toReturn = false;
JsBinaryOperator op = x.getOperator();
JsExpression arg1 = x.getArg1();
JsExpression arg2 = x.getArg2();
/*
* First, we'll try to normalize the nesting of any binary expressions
* that we encounter. If we do this correctly,it will help to cut down on
* the number of unnecessary parens in the emitted JS.
*/
// (X) O (c O d) ==> ((X) O c) O d
{
JsBinaryOperation rightOp = null;
if (arg2 instanceof JsBinaryOperation) {
rightOp = (JsBinaryOperation) arg2;
}
if (rightOp != null && !rightOp.getOperator().isAssignment()
&& op == rightOp.getOperator()) {
if (op == JsBinaryOperator.ADD) {
/*
* JS type coercion is a problem if we don't know for certain that
* the right-hand expression will definitely be evaluated in a
* string context.
*/
boolean mustBeString = additionCoercesToString(rightOp.getArg1())
|| (additionCoercesToString(arg1) && additionCoercesToString(rightOp.getArg2()));
if (!mustBeString) {
return toReturn;
}
}
// (X) O c --> Try to reduce this
JsExpression newLeft = new JsBinaryOperation(x.getSourceInfo(), op,
arg1, rightOp.getArg1());
// Reset local vars with new state
op = rightOp.getOperator();
arg1 = accept(newLeft);
arg2 = rightOp.getArg2();
x = new JsBinaryOperation(x.getSourceInfo(), op, arg1, arg2);
ctx.replaceMe(x);
toReturn = didChange = true;
}
}
/*
* Now that we know that our AST is as left-normal as we can make it
* (because this method is called from endVisit), we now try to simplify
* the left-right node and the right node.
*/
// (a O b) O c ==> a O s
{
JsBinaryOperation leftOp = null;
JsExpression leftLeft = null;
JsExpression leftRight = null;
if (arg1 instanceof JsBinaryOperation) {
leftOp = (JsBinaryOperation) arg1;
if (op.getPrecedence() == leftOp.getOperator().getPrecedence()) {
leftLeft = leftOp.getArg1();
leftRight = leftOp.getArg2();
}
}
if (leftRight != null) {
if (op == JsBinaryOperator.ADD) {
// Behavior as described above
boolean mustBeString = additionCoercesToString(leftRight)
|| (additionCoercesToString(leftLeft) && additionCoercesToString(arg2));
if (!mustBeString) {
return toReturn;
}
}
// (b O c)
JsBinaryOperation middle = new JsBinaryOperation(x.getSourceInfo(),
op, leftRight, arg2);
StaticEvalVisitor v = new StaticEvalVisitor();
JsExpression maybeSimplified = v.accept(middle);
if (v.didChange()) {
x.setArg1(leftLeft);
x.setArg2(maybeSimplified);
toReturn = didChange = true;