1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.ir; 27 28import jdk.nashorn.internal.ir.annotations.Immutable; 29import jdk.nashorn.internal.ir.visitor.NodeVisitor; 30 31/** 32 * IR representation for an IF statement. 33 */ 34@Immutable 35public final class IfNode extends Statement implements JoinPredecessor { 36 private static final long serialVersionUID = 1L; 37 38 /** Test expression. */ 39 private final Expression test; 40 41 /** Pass statements. */ 42 private final Block pass; 43 44 /** Fail statements. */ 45 private final Block fail; 46 47 /** 48 * Local variable conversions that need to be performed after test if it evaluates to false, and there's no else 49 * branch. 50 */ 51 private final LocalVariableConversion conversion; 52 53 /** 54 * Constructor 55 * 56 * @param lineNumber line number 57 * @param token token 58 * @param finish finish 59 * @param test test 60 * @param pass block to execute when test passes 61 * @param fail block to execute when test fails or null 62 */ 63 public IfNode(final int lineNumber, final long token, final int finish, final Expression test, final Block pass, final Block fail) { 64 super(lineNumber, token, finish); 65 this.test = test; 66 this.pass = pass; 67 this.fail = fail; 68 this.conversion = null; 69 } 70 71 private IfNode(final IfNode ifNode, final Expression test, final Block pass, final Block fail, final LocalVariableConversion conversion) { 72 super(ifNode); 73 this.test = test; 74 this.pass = pass; 75 this.fail = fail; 76 this.conversion = conversion; 77 } 78 79 @Override 80 public boolean isTerminal() { 81 return pass.isTerminal() && fail != null && fail.isTerminal(); 82 } 83 84 @Override 85 public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 86 if (visitor.enterIfNode(this)) { 87 return visitor.leaveIfNode( 88 setTest((Expression)test.accept(visitor)). 89 setPass((Block)pass.accept(visitor)). 90 setFail(fail == null ? null : (Block)fail.accept(visitor))); 91 } 92 93 return this; 94 } 95 96 @Override 97 public void toString(final StringBuilder sb, final boolean printTypes) { 98 sb.append("if ("); 99 test.toString(sb, printTypes); 100 sb.append(')'); 101 } 102 103 /** 104 * Get the else block of this IfNode 105 * @return the else block, or null if none exists 106 */ 107 public Block getFail() { 108 return fail; 109 } 110 111 private IfNode setFail(final Block fail) { 112 if (this.fail == fail) { 113 return this; 114 } 115 return new IfNode(this, test, pass, fail, conversion); 116 } 117 118 /** 119 * Get the then block for this IfNode 120 * @return the then block 121 */ 122 public Block getPass() { 123 return pass; 124 } 125 126 private IfNode setPass(final Block pass) { 127 if (this.pass == pass) { 128 return this; 129 } 130 return new IfNode(this, test, pass, fail, conversion); 131 } 132 133 /** 134 * Get the test expression for this IfNode 135 * @return the test expression 136 */ 137 public Expression getTest() { 138 return test; 139 } 140 141 /** 142 * Reset the test expression for this IfNode 143 * @param test a new test expression 144 * @return new or same IfNode 145 */ 146 public IfNode setTest(final Expression test) { 147 if (this.test == test) { 148 return this; 149 } 150 return new IfNode(this, test, pass, fail, conversion); 151 } 152 153 @Override 154 public IfNode setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) { 155 if(this.conversion == conversion) { 156 return this; 157 } 158 return new IfNode(this, test, pass, fail, conversion); 159 } 160 161 @Override 162 public LocalVariableConversion getLocalVariableConversion() { 163 return conversion; 164 } 165} 166