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 26 package jdk.nashorn.internal.ir; 27 28 import jdk.nashorn.internal.ir.annotations.Immutable; 29 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 30 31 /** 32 * IR representation for a WHILE statement. This is the superclass of all 33 * loop nodes 34 */ 35 @Immutable 36 public final class WhileNode extends LoopNode { 37 private static final long serialVersionUID = 1L; 38 39 40 /** is this a do while node ? */ 41 private final boolean isDoWhile; 42 43 /** 44 * Constructor 45 * 46 * @param lineNumber line number 47 * @param token token 48 * @param finish finish 49 * @param isDoWhile is this a do while loop? 50 * @param test test expression 51 * @param body body of the while loop 52 */ 53 public WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile, final JoinPredecessorExpression test, final Block body) { 54 super(lineNumber, token, finish, body, test, false); 55 this.isDoWhile = isDoWhile; 56 } 57 58 /** 59 * Internal copy constructor 60 * 61 * @param whileNode while node 62 * @param test Test expression 63 * @param body body of the while loop 64 * @param controlFlowEscapes control flow escapes? 65 * @param conversion local variable conversion info 66 */ 67 private WhileNode(final WhileNode whileNode, final JoinPredecessorExpression test, final Block body, final boolean controlFlowEscapes, final LocalVariableConversion conversion) { 68 super(whileNode, test, body, controlFlowEscapes, conversion); 69 this.isDoWhile = whileNode.isDoWhile; 70 } 71 72 @Override 73 public Node ensureUniqueLabels(final LexicalContext lc) { 74 return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion)); 75 } 76 77 @Override 78 public boolean hasGoto() { 79 return test == null; 80 } 81 82 @Override 83 public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 84 if (visitor.enterWhileNode(this)) { 85 if (isDoWhile()) { 86 return visitor.leaveWhileNode( 87 setBody(lc, (Block)body.accept(visitor)). 88 setTest(lc, (JoinPredecessorExpression)test.accept(visitor))); 89 } 90 return visitor.leaveWhileNode( 91 setTest(lc, (JoinPredecessorExpression)test.accept(visitor)). 92 setBody(lc, (Block)body.accept(visitor))); 93 } 94 return this; 95 } 96 97 @Override 98 public WhileNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) { 99 if (this.test == test) { 100 return this; 101 } 102 return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion)); 103 } 104 105 @Override 106 public Block getBody() { 107 return body; 108 } 109 110 @Override 111 public WhileNode setBody(final LexicalContext lc, final Block body) { 112 if (this.body == body) { 113 return this; 114 } 115 return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion)); 116 } 117 118 @Override 119 public WhileNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes) { 120 if (this.controlFlowEscapes == controlFlowEscapes) { 121 return this; 122 } 123 return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion)); 124 } 125 126 @Override 127 JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { 128 return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion)); 129 } 130 131 /** 132 * Check if this is a do while loop or a normal while loop 133 * @return true if do while 134 */ 135 public boolean isDoWhile() { 136 return isDoWhile; 137 } 138 139 @Override 140 public void toString(final StringBuilder sb, final boolean printType) { 141 sb.append("while ("); 142 test.toString(sb, printType); 143 sb.append(')'); 144 } 145 146 @Override 147 public boolean mustEnter() { 148 if (isDoWhile()) { 149 return true; 150 } 151 return test == null; 152 } 153 154 @Override 155 public boolean hasPerIterationScope() { 156 return false; 157 } 158 }