WhileNode.java revision 1118:e26843ca558b
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 a WHILE statement. This is the superclass of all
33 * loop nodes
34 */
35@Immutable
36public 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}
159