* 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()) {