use of com.google.javascript.jscomp.base.Tri in project closure-compiler by google.
the class PeepholeRemoveDeadCode method tryOptimizeConditionalAfterAssign.
// TODO(johnlenz): Consider moving this to a separate peephole pass.
/**
* Attempt to replace the condition of if or hook immediately that is a
* reference to a name that is assigned immediately before.
*/
private void tryOptimizeConditionalAfterAssign(Node n) {
Node next = n.getNext();
if (isSimpleAssignment(n) && isConditionalStatement(next)) {
Node lhsAssign = getSimpleAssignmentName(n);
Node condition = getConditionalStatementCondition(next);
if (lhsAssign.isName() && condition.isName() && lhsAssign.getString().equals(condition.getString())) {
Node rhsAssign = getSimpleAssignmentValue(n);
Tri value = NodeUtil.getBooleanValue(rhsAssign);
if (value != Tri.UNKNOWN) {
Node replacementConditionNode = NodeUtil.booleanNode(value.toBoolean(true));
condition.replaceWith(replacementConditionNode);
reportChangeToEnclosingScope(replacementConditionNode);
}
}
}
}
use of com.google.javascript.jscomp.base.Tri in project closure-compiler by google.
the class PeepholeRemoveDeadCode method tryOptimizeSwitch.
/**
* Remove useless switches and cases.
*/
private Node tryOptimizeSwitch(Node n) {
checkState(n.isSwitch(), n);
Node defaultCase = tryOptimizeDefaultCase(n);
// Generally, it is unsafe to remove other cases when the default case is not the last one.
if (defaultCase == null || n.getLastChild().isDefaultCase()) {
Node cond = n.getFirstChild();
Node prev = null;
Node next = null;
Node cur;
for (cur = cond.getNext(); cur != null; cur = next) {
next = cur.getNext();
if (!mayHaveSideEffects(cur.getFirstChild()) && isUselessCase(cur, prev, defaultCase)) {
removeCase(n, cur);
} else {
prev = cur;
}
}
// Optimize switches with constant condition
if (NodeUtil.isLiteralValue(cond, false)) {
Node caseLabel;
Tri caseMatches = Tri.TRUE;
// Remove cases until you find one that may match
for (cur = cond.getNext(); cur != null; cur = next) {
next = cur.getNext();
caseLabel = cur.getFirstChild();
caseMatches = PeepholeFoldConstants.evaluateComparison(this, Token.SHEQ, cond, caseLabel);
if (caseMatches == Tri.TRUE) {
break;
} else if (caseMatches == Tri.UNKNOWN) {
break;
} else {
removeCase(n, cur);
}
}
if (cur != null && caseMatches == Tri.TRUE) {
// Skip cases until you find one whose last stm is a removable break
Node matchingCase = cur;
Node matchingCaseBlock = matchingCase.getLastChild();
while (cur != null) {
Node block = cur.getLastChild();
Node lastStm = block.getLastChild();
boolean isLastStmRemovableBreak = false;
if (lastStm != null && isExit(lastStm)) {
removeIfUnnamedBreak(lastStm);
isLastStmRemovableBreak = true;
}
next = cur.getNext();
// Remove the fallthrough case labels
if (cur != matchingCase) {
while (block.hasChildren()) {
matchingCaseBlock.addChildToBack(block.removeFirstChild());
}
reportChangeToEnclosingScope(cur);
cur.detach();
}
cur = next;
if (isLastStmRemovableBreak) {
break;
}
}
// Remove any remaining cases
for (; cur != null; cur = next) {
next = cur.getNext();
removeCase(n, cur);
}
// If there is one case left, we may be able to fold it
cur = cond.getNext();
if (cur != null && cur.getNext() == null) {
return tryRemoveSwitchWithSingleCase(n, false);
}
}
}
}
return tryRemoveSwitch(n);
}
use of com.google.javascript.jscomp.base.Tri in project closure-compiler by google.
the class PeepholeFoldConstants method tryFoldComparison.
/**
* Try to fold comparison nodes, e.g ==
*/
private Node tryFoldComparison(Node n, Node left, Node right) {
Tri result = evaluateComparison(this, n.getToken(), left, right);
if (result == Tri.UNKNOWN) {
return n;
}
Node newNode = NodeUtil.booleanNode(result.toBoolean(true));
reportChangeToEnclosingScope(n);
n.replaceWith(newNode);
markFunctionsDeleted(n);
return newNode;
}
use of com.google.javascript.jscomp.base.Tri in project closure-compiler by google.
the class PeepholeFoldConstants method tryFoldCoalesce.
/**
* Try to fold a COALESCE node.
*/
private Node tryFoldCoalesce(Node n, Node left, Node right) {
Node result = null;
Node dropped = null;
Tri leftVal = NodeUtil.getBooleanValue(left);
if (leftVal != Tri.UNKNOWN) {
if (NodeUtil.isNullOrUndefined(left)) {
result = right;
dropped = left;
} else {
if (!mayHaveSideEffects(left)) {
result = left;
dropped = right;
} else {
n.detachChildren();
result = IR.comma(left, right);
dropped = null;
}
}
}
if (result != null) {
// Fold!
n.detachChildren();
n.replaceWith(result);
reportChangeToEnclosingScope(result);
if (dropped != null) {
markFunctionsDeleted(dropped);
}
return result;
} else {
return n;
}
}
use of com.google.javascript.jscomp.base.Tri in project closure-compiler by google.
the class NodeUtil method getStringValue.
/**
* Gets the value of a node as a String, or null if it cannot be converted. When it returns a
* non-null String, this method effectively emulates the <code>String()</code> JavaScript cast
* function.
*
* <p>IMPORTANT: This method does not consider whether {@code n} may have side effects.
*/
public static String getStringValue(Node n) {
// TODO(user): regex literals as well.
switch(n.getToken()) {
case STRINGLIT:
case STRING_KEY:
return n.getString();
case TEMPLATELIT:
// Only convert a template literal if all its expressions can be converted.
StringBuilder string = new StringBuilder();
for (Node child = n.getFirstChild(); child != null; child = child.getNext()) {
Node expression = child;
if (child.isTemplateLitSub()) {
expression = child.getFirstChild();
}
String expressionString = getStringValue(expression);
if (expressionString == null) {
// Cannot convert.
return null;
}
string.append(expressionString);
}
return string.toString();
case TEMPLATELIT_STRING:
return n.getCookedString();
case NAME:
String name = n.getString();
if ("undefined".equals(name) || "Infinity".equals(name) || "NaN".equals(name)) {
return name;
}
break;
case NEG:
case NUMBER:
{
Double value = getNumberValue(n);
if (value == null) {
break;
}
return DToA.numberToString(value.doubleValue());
}
case BIGINT:
return n.getBigInt() + "n";
case FALSE:
return "false";
case TRUE:
return "true";
case NULL:
return "null";
case VOID:
return "undefined";
case NOT:
Tri child = getBooleanValue(n.getFirstChild());
if (child != Tri.UNKNOWN) {
// reversed.
return child.toBoolean(true) ? "false" : "true";
}
break;
case ARRAYLIT:
return arrayToString(n);
case OBJECTLIT:
return "[object Object]";
default:
break;
}
return null;
}
Aggregations