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 THROW statements.
33  */
34 @Immutable
35 public final class ThrowNode extends Statement implements JoinPredecessor {
36     private static final long serialVersionUID = 1L;
37 
38     /** Exception expression. */
39     private final Expression expression;
40 
41     private final LocalVariableConversion conversion;
42 
43     private final boolean isSyntheticRethrow;
44 
45     /**
46      * Constructor
47      *
48      * @param lineNumber line number
49      * @param token      token
50      * @param finish     finish
51      * @param expression expression to throw
52      * @param isSyntheticRethrow true if this throw node is part of a synthetic rethrow.
53      */
ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final boolean isSyntheticRethrow)54     public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final boolean isSyntheticRethrow) {
55         super(lineNumber, token, finish);
56         this.expression = expression;
57         this.isSyntheticRethrow = isSyntheticRethrow;
58         this.conversion = null;
59     }
60 
ThrowNode(final ThrowNode node, final Expression expression, final boolean isSyntheticRethrow, final LocalVariableConversion conversion)61     private ThrowNode(final ThrowNode node, final Expression expression, final boolean isSyntheticRethrow,
62             final LocalVariableConversion conversion) {
63         super(node);
64         this.expression = expression;
65         this.isSyntheticRethrow = isSyntheticRethrow;
66         this.conversion = conversion;
67     }
68 
69     @Override
isTerminal()70     public boolean isTerminal() {
71         return true;
72     }
73 
74     /**
75      * Assist in IR navigation.
76      * @param visitor IR navigating visitor.
77      */
78     @Override
accept(final NodeVisitor<? extends LexicalContext> visitor)79     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
80         if (visitor.enterThrowNode(this)) {
81             return visitor.leaveThrowNode(setExpression((Expression)expression.accept(visitor)));
82         }
83 
84         return this;
85     }
86 
87     @Override
toString(final StringBuilder sb, final boolean printType)88     public void toString(final StringBuilder sb, final boolean printType) {
89         sb.append("throw ");
90 
91         if (expression != null) {
92             expression.toString(sb, printType);
93         }
94         if (conversion != null) {
95             conversion.toString(sb);
96         }
97     }
98 
99     /**
100      * Get the expression that is being thrown by this node
101      * @return expression
102      */
getExpression()103     public Expression getExpression() {
104         return expression;
105     }
106 
107     /**
108      * Reset the expression being thrown by this node
109      * @param expression new expression
110      * @return new or same thrownode
111      */
setExpression(final Expression expression)112     public ThrowNode setExpression(final Expression expression) {
113         if (this.expression == expression) {
114             return this;
115         }
116         return new ThrowNode(this, expression, isSyntheticRethrow, conversion);
117     }
118 
119     /**
120      * Is this a throw a synthetic rethrow in a synthetic catch-all block
121      * created when inlining finally statements? In that case we never
122      * wrap whatever is thrown into an ECMAException, just rethrow it.
123      * @return true if synthetic throw node
124      */
isSyntheticRethrow()125     public boolean isSyntheticRethrow() {
126         return isSyntheticRethrow;
127     }
128 
129     @Override
setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion)130     public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
131         if(this.conversion == conversion) {
132             return this;
133         }
134         return new ThrowNode(this, expression, isSyntheticRethrow, conversion);
135     }
136 
137     @Override
getLocalVariableConversion()138     public LocalVariableConversion getLocalVariableConversion() {
139         return conversion;
140     }
141 
142 }
143