WhileNode.java revision 953:221a84ef44c0
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
38    /** is this a do while node ? */
39    private final boolean isDoWhile;
40
41    /**
42     * Constructor
43     *
44     * @param lineNumber line number
45     * @param token      token
46     * @param finish     finish
47     * @param isDoWhile  is this a do while loop?
48     */
49    public WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile) {
50        super(lineNumber, token, finish, null, false);
51        this.isDoWhile = isDoWhile;
52    }
53
54    /**
55     * Internal copy constructor
56     *
57     * @param whileNode while node
58     * @param test      test
59     * @param body      body
60     * @param controlFlowEscapes control flow escapes?
61     * @param conversion TODO
62     */
63    private WhileNode(final WhileNode whileNode, final JoinPredecessorExpression test, final Block body, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
64        super(whileNode, test, body, controlFlowEscapes, conversion);
65        this.isDoWhile = whileNode.isDoWhile;
66    }
67
68    @Override
69    public Node ensureUniqueLabels(final LexicalContext lc) {
70        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
71    }
72
73    @Override
74    public boolean hasGoto() {
75        return test == null;
76    }
77
78    @Override
79    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
80        if (visitor.enterWhileNode(this)) {
81            if (isDoWhile()) {
82                return visitor.leaveWhileNode(
83                        setBody(lc, (Block)body.accept(visitor)).
84                        setTest(lc, (JoinPredecessorExpression)test.accept(visitor)));
85            }
86            return visitor.leaveWhileNode(
87                    setTest(lc, (JoinPredecessorExpression)test.accept(visitor)).
88                    setBody(lc, (Block)body.accept(visitor)));
89        }
90        return this;
91    }
92
93    @Override
94    public WhileNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) {
95        if (this.test == test) {
96            return this;
97        }
98        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
99    }
100
101    @Override
102    public Block getBody() {
103        return body;
104    }
105
106    @Override
107    public WhileNode setBody(final LexicalContext lc, final Block body) {
108        if (this.body == body) {
109            return this;
110        }
111        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
112    }
113
114    @Override
115    public WhileNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes) {
116        if (this.controlFlowEscapes == controlFlowEscapes) {
117            return this;
118        }
119        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
120    }
121
122    @Override
123    JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
124        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
125    }
126
127    /**
128     * Check if this is a do while loop or a normal while loop
129     * @return true if do while
130     */
131    public boolean isDoWhile() {
132        return isDoWhile;
133    }
134
135    @Override
136    public void toString(final StringBuilder sb, final boolean printType) {
137        sb.append("while (");
138        test.toString(sb, printType);
139        sb.append(')');
140    }
141
142    @Override
143    public boolean mustEnter() {
144        if (isDoWhile()) {
145            return true;
146        }
147        return test == null;
148    }
149}
150