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