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