// AND and OR children below.
return newRoot;
}
default:
TernaryValue nVal = NodeUtil.getPureBooleanValue(first);
if (nVal != TernaryValue.UNKNOWN) {
boolean result = nVal.not().toBoolean(true);
int equivalentResult = result ? 1 : 0;
return maybeReplaceChildWithNumber(n, parent, equivalentResult);
}
}
// No need to traverse, tryMinimizeCondition is called on the NOT
// children in the general case in the main post-order traversal.
return n;
case Token.OR:
case Token.AND: {
Node left = n.getFirstChild();
Node right = n.getLastChild();
// Because the expression is in a boolean context minimize
// the children, this can't be done in the general case.
left = tryMinimizeCondition(left);
right = tryMinimizeCondition(right);
// Remove useless conditionals
// Handle four cases:
// x || false --> x
// x || true --> true
// x && true --> x
// x && false --> false
TernaryValue rightVal = NodeUtil.getPureBooleanValue(right);
if (NodeUtil.getPureBooleanValue(right) != TernaryValue.UNKNOWN) {
int type = n.getType();
Node replacement = null;
boolean rval = rightVal.toBoolean(true);
// (x || FALSE) => x
// (x && TRUE) => x
if (type == Token.OR && !rval ||
type == Token.AND && rval) {
replacement = left;
} else if (!mayHaveSideEffects(left)) {
replacement = right;
}
if (replacement != null) {
n.detachChildren();
parent.replaceChild(n, replacement);
reportCodeChange();
return replacement;
}
}
return n;
}
case Token.HOOK: {
Node condition = n.getFirstChild();
Node trueNode = n.getFirstChild().getNext();
Node falseNode = n.getLastChild();
// Because the expression is in a boolean context minimize
// the result children, this can't be done in the general case.
// The condition is handled in the general case in #optimizeSubtree
trueNode = tryMinimizeCondition(trueNode);
falseNode = tryMinimizeCondition(falseNode);
// Handle four cases:
// x ? true : false --> x
// x ? false : true --> !x
// x ? true : y --> x || y
// x ? y : false --> x && y
Node replacement = null;
TernaryValue trueNodeVal = NodeUtil.getPureBooleanValue(trueNode);
TernaryValue falseNodeVal = NodeUtil.getPureBooleanValue(falseNode);
if (trueNodeVal == TernaryValue.TRUE
&& falseNodeVal == TernaryValue.FALSE) {
// Remove useless conditionals, keep the condition
condition.detachFromParent();
replacement = condition;
} else if (trueNodeVal == TernaryValue.FALSE
&& falseNodeVal == TernaryValue.TRUE) {
// Remove useless conditionals, keep the condition
condition.detachFromParent();
replacement = new Node(Token.NOT, condition);
} else if (trueNodeVal == TernaryValue.TRUE) {
// Remove useless true case.
n.detachChildren();
replacement = new Node(Token.OR, condition, falseNode);
} else if (falseNodeVal == TernaryValue.FALSE) {
// Remove useless false case
n.detachChildren();
replacement = new Node(Token.AND, condition, trueNode);
}
if (replacement != null) {
parent.replaceChild(n, replacement);
n = replacement;
reportCodeChange();
}
return n;
}
default:
// while(true) --> while(1)
TernaryValue nVal = NodeUtil.getPureBooleanValue(n);
if (nVal != TernaryValue.UNKNOWN) {
boolean result = nVal.toBoolean(true);
int equivalentResult = result ? 1 : 0;
return maybeReplaceChildWithNumber(n, parent, equivalentResult);
}
// We can't do anything else currently.
return n;