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 */ WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile, final JoinPredecessorExpression test, final Block body)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 */ WhileNode(final WhileNode whileNode, final JoinPredecessorExpression test, final Block body, final boolean controlFlowEscapes, final LocalVariableConversion conversion)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 ensureUniqueLabels(final LexicalContext lc)73 public Node ensureUniqueLabels(final LexicalContext lc) { 74 return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion)); 75 } 76 77 @Override hasGoto()78 public boolean hasGoto() { 79 return test == null; 80 } 81 82 @Override accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor)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 setTest(final LexicalContext lc, final JoinPredecessorExpression test)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 getBody()106 public Block getBody() { 107 return body; 108 } 109 110 @Override setBody(final LexicalContext lc, final Block body)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 setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes)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 setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion)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 */ isDoWhile()135 public boolean isDoWhile() { 136 return isDoWhile; 137 } 138 139 @Override toString(final StringBuilder sb, final boolean printType)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 mustEnter()147 public boolean mustEnter() { 148 if (isDoWhile()) { 149 return true; 150 } 151 return test == null; 152 } 153 154 @Override hasPerIterationScope()155 public boolean hasPerIterationScope() { 156 return false; 157 } 158 } 159