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