CatchNode.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 of a catch clause.
33 */
34@Immutable
35public final class CatchNode extends Statement {
36    /** Exception identifier. */
37    private final IdentNode exception;
38
39    /** Exception condition. */
40    private final Expression exceptionCondition;
41
42    /** Catch body. */
43    private final Block body;
44
45    private final boolean isSyntheticRethrow;
46
47    /**
48     * Constructors
49     *
50     * @param lineNumber         lineNumber
51     * @param token              token
52     * @param finish             finish
53     * @param exception          variable name of exception
54     * @param exceptionCondition exception condition
55     * @param body               catch body
56     * @param isSyntheticRethrow true if this node is a synthetically generated rethrow node.
57     */
58    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception,
59            final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) {
60        super(lineNumber, token, finish);
61        this.exception          = exception == null ? null : exception.setIsInitializedHere();
62        this.exceptionCondition = exceptionCondition;
63        this.body               = body;
64        this.isSyntheticRethrow = isSyntheticRethrow;
65    }
66
67    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition,
68            final Block body, final boolean isSyntheticRethrow) {
69        super(catchNode);
70        this.exception          = exception;
71        this.exceptionCondition = exceptionCondition;
72        this.body               = body;
73        this.isSyntheticRethrow = isSyntheticRethrow;
74    }
75
76    /**
77     * Assist in IR navigation.
78     * @param visitor IR navigating visitor.
79     */
80    @Override
81    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
82        if (visitor.enterCatchNode(this)) {
83            return visitor.leaveCatchNode(
84                setException((IdentNode)exception.accept(visitor)).
85                setExceptionCondition(exceptionCondition == null ? null : (Expression)exceptionCondition.accept(visitor)).
86                setBody((Block)body.accept(visitor)));
87        }
88
89        return this;
90    }
91
92    @Override
93    public boolean isTerminal() {
94        return body.isTerminal();
95    }
96
97    @Override
98    public void toString(final StringBuilder sb, final boolean printTypes) {
99        sb.append(" catch (");
100        exception.toString(sb, printTypes);
101
102        if (exceptionCondition != null) {
103            sb.append(" if ");
104            exceptionCondition.toString(sb, printTypes);
105        }
106        sb.append(')');
107    }
108
109    /**
110     * Get the identifier representing the exception thrown
111     * @return the exception identifier
112     */
113    public IdentNode getException() {
114        return exception;
115    }
116
117    /**
118     * Get the exception condition for this catch block
119     * @return the exception condition
120     */
121    public Expression getExceptionCondition() {
122        return exceptionCondition;
123    }
124
125    /**
126     * Reset the exception condition for this catch block
127     * @param exceptionCondition the new exception condition
128     * @return new or same CatchNode
129     */
130    public CatchNode setExceptionCondition(final Expression exceptionCondition) {
131        if (this.exceptionCondition == exceptionCondition) {
132            return this;
133        }
134        return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
135    }
136
137    /**
138     * Get the body for this catch block
139     * @return the catch block body
140     */
141    public Block getBody() {
142        return body;
143    }
144
145    /**
146     * Resets the exception of a catch block
147     * @param exception new exception
148     * @return new catch node if changed, same otherwise
149     */
150    public CatchNode setException(final IdentNode exception) {
151        if (this.exception == exception) {
152            return this;
153        }
154        return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
155    }
156
157    private CatchNode setBody(final Block body) {
158        if (this.body == body) {
159            return this;
160        }
161        return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
162    }
163
164    /**
165     * Is this catch block a non-JavaScript constructor, for example created as
166     * part of the rethrow mechanism of a finally block in Lower? Then we just
167     * pass the exception on and need not unwrap whatever is in the ECMAException
168     * object catch symbol
169     * @return true if a finally synthetic rethrow
170     */
171    public boolean isSyntheticRethrow() {
172        return isSyntheticRethrow;
173    }
174}
175