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