MeasuredNode pos = new MeasuredNode(n, 0, false); MeasuredNode neg = pos.cloneTree().negate(); return new MinimizedCondition(pos, neg);
MeasuredNode withoutNot() { checkState(this.isNot()); return (normalizeChildren(node, children)[0]).change(); }
/** * Whether the MeasuredNode is a change from the original. * This can either be a change within the original AST tree or a * replacement of the original node. */ public boolean willChange(Node original) { checkNotNull(original); return original != this.node || this.isChanged(); }
if (shortCond.getNode().isNot()) { shortCond.getNode().removeFirstChild(), expr.removeFirstChild()).srcref(n); Node newExpr = NodeUtil.newExpr(or); if (isLowerPrecedence(shortCond.getNode(), AND_PRECEDENCE) && isLowerPrecedence(expr.getFirstChild(), AND_PRECEDENCE)) { Node and = IR.and(shortCond.getNode(), expr.removeFirstChild()).srcref(n); Node newExpr = NodeUtil.newExpr(and); parent.replaceChild(n, newExpr); !(isLowerPrecedence(unnegatedCond.getNode(), AND_PRECEDENCE) && isLowerPrecedence(innerCond, AND_PRECEDENCE))) { n.detachChildren(); n.addChildToBack( IR.and( unnegatedCond.getNode(), innerCond.detachFromParent()) .srcref(placeholder)); if (shortCond.getNode().isNot() && !consumesDanglingElse(elseBranch)) { n.replaceChild(placeholder, shortCond.getNode().removeFirstChild()); n.removeChild(thenBranch); n.addChildToBack(thenBranch); IR.hook(shortCond.getNode(), thenExpr, elseExpr)
/** * Try flipping HOOKs that have negated conditions. * * Returns the replacement for n or the original if no replacement was * necessary. */ private Node tryMinimizeHook(Node n) { MinimizedCondition minCond = MinimizedCondition.fromConditionNode(n.getFirstChild()); MinimizedCondition.MeasuredNode mNode = minCond.getMinimized(MinimizationStyle.ALLOW_LEADING_NOT); Node placeholder = minCond.getPlaceholder(); if (mNode.getNode().isNot()) { // Swap the HOOK Node thenBranch = n.getSecondChild(); n.replaceChild(placeholder, mNode.getNode().removeFirstChild()); n.removeChild(thenBranch); n.addChildToBack(thenBranch); reportCodeChange(); } else { replaceNode(placeholder, mNode); } return n; }
/** * Try to remove leading NOTs from EXPR_RESULTS. * * Returns the replacement for n or the original if no replacement was * necessary. */ private Node tryMinimizeExprResult(Node n) { MinimizedCondition minCond = MinimizedCondition.fromConditionNode(n.getFirstChild()); MinimizedCondition.MeasuredNode mNode = minCond.getMinimized(MinimizationStyle.ALLOW_LEADING_NOT); Node placeholder = minCond.getPlaceholder(); if (mNode.getNode().isNot()) { // Remove the leading NOT in the EXPR_RESULT. n.replaceChild(placeholder, mNode.getNode().removeFirstChild()); reportCodeChange(); } else { replaceNode(placeholder, mNode); } return n; }
/** * Return a MeasuredNode of the given condition node, without minimizing * the result. * <p> * Since a MinimizedCondition necessarily must contain two trees, this * method sets the negative side to a {@link Token#SCRIPT} node (never valid * inside an expression) with an unreasonably high length so that it will * never be chosen by {@link #getMinimized}. * * @param n the conditional expression tree to minimize. * This must be connected to the AST, and will be swapped * with a placeholder node during minimization. * @return a MinimizedCondition object representing that tree. */ static MinimizedCondition unoptimized(Node n) { Preconditions.checkNotNull(n.getParent()); Node placeholder = swapWithPlaceholderNode(n); MeasuredNode pos = new MeasuredNode(n, 0, false); MeasuredNode neg = new MeasuredNode(IR.script(), Integer.MAX_VALUE, true); return new MinimizedCondition(pos, neg).setPlaceholder(placeholder); }
private MeasuredNode negate() { this.change(); switch (node.getType()) { case Token.EQ: node.setType(Token.NE); return this; case Token.NE: node.setType(Token.EQ); return this; case Token.SHEQ: node.setType(Token.SHNE); return this; case Token.SHNE: node.setType(Token.SHEQ); return this; default: return this.addNot(); } }
/** * Return a MeasuredNode of the given condition node, without minimizing * the result. * <p> * Since a MinimizedCondition necessarily must contain two trees, * this method sets the negative side to a invalid node * with an unreasonably high length so that it will * never be chosen by {@link #getMinimized}. * * @param n the conditional expression tree * @return a MinimizedCondition object representing that tree. */ static MinimizedCondition unoptimized(Node n) { checkNotNull(n.getParent()); MeasuredNode pos = new MeasuredNode(n, null, 0, false); MeasuredNode neg = new MeasuredNode(null, null, Integer.MAX_VALUE, true); return new MinimizedCondition(pos, neg); }
/** * Build the final AST structure, detaching component Nodes as necessary * from the original AST. The root Node, if currently attached is left attached * to avoid the need to keep track of its position. */ @VisibleForTesting Node buildReplacement() { if (children != null) { node.detachChildren(); for (MeasuredNode child : children) { Node replacementChild = safeDetach(child.buildReplacement()); node.addChildToBack(replacementChild); } } return node; }
private MeasuredNode negate() { switch (node.getToken()) { case EQ: return updateToken(Token.NE); case NE: return updateToken(Token.EQ); case SHEQ: return updateToken(Token.SHNE); case SHNE: return updateToken(Token.SHEQ); case NOT: return withoutNot(); default: return this.addNot(); } }
/** * Update the AST for the result of this MeasuredNode. * This can either be a change within the original AST tree or a * replacement of the original node. */ public Node applyTo(Node original) { checkNotNull(original); checkState(willChange(original)); Node replacement = buildReplacement(); if (original != replacement) { safeDetach(replacement); original.replaceWith(replacement); } return replacement; }
private MeasuredNode cloneTree() { return new MeasuredNode(node.cloneTree(), length, changed); }
/** * The returned MeasuredNode is only marked as changed if the children * are marked as changed. */ private static MeasuredNode addNode(Node parent, MeasuredNode ...children) { int cost = 0; boolean changed = false; for (MeasuredNode child : children) { cost += child.length; changed = changed || child.changed; } cost += estimateCostOneLevel(parent, children); return new MeasuredNode(parent, children, cost, changed); }
private MeasuredNode change() { return (isChanged()) ? this : new MeasuredNode(node, children, length, true); }
private MeasuredNode addNot() { node = new Node(Token.NOT, node).srcref(node); length += estimateCostOneLevel(node); return this; }
private MeasuredNode updateToken(Token token) { return new MeasuredNode( new Node(token).srcref(node), normalizeChildren(node, children), length, true); }
private Node replaceNode(Node original, MeasuredNode measuredNodeReplacement) { if (measuredNodeReplacement.willChange(original)) { Node replacement = measuredNodeReplacement.applyTo(original); reportChangeToEnclosingScope(replacement); return replacement; } return original; }