Search in sources :

Example 11 with Tri

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);
            }
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) Tri(com.google.javascript.jscomp.base.Tri)

Example 12 with Tri

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);
}
Also used : Node(com.google.javascript.rhino.Node) Tri(com.google.javascript.jscomp.base.Tri)

Example 13 with Tri

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;
}
Also used : Node(com.google.javascript.rhino.Node) Tri(com.google.javascript.jscomp.base.Tri)

Example 14 with Tri

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;
    }
}
Also used : Node(com.google.javascript.rhino.Node) Tri(com.google.javascript.jscomp.base.Tri)

Example 15 with Tri

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;
}
Also used : Node(com.google.javascript.rhino.Node) Tri(com.google.javascript.jscomp.base.Tri)

Aggregations

Tri (com.google.javascript.jscomp.base.Tri)17 Node (com.google.javascript.rhino.Node)12 Token (com.google.javascript.rhino.Token)3 BigInteger (java.math.BigInteger)3 JSType (com.google.javascript.rhino.jstype.JSType)2 MeasuredNode (com.google.javascript.jscomp.MinimizedCondition.MeasuredNode)1 ValueType (com.google.javascript.jscomp.NodeUtil.ValueType)1 EnumType (com.google.javascript.rhino.jstype.EnumType)1 Test (org.junit.Test)1