CaseNode.java revision 1068:34ef988d5959
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 java.util.Collections; 29import java.util.List; 30import jdk.nashorn.internal.codegen.Label; 31import jdk.nashorn.internal.ir.annotations.Immutable; 32import jdk.nashorn.internal.ir.visitor.NodeVisitor; 33 34/** 35 * IR representation of CASE clause. 36 * Case nodes are not BreakableNodes, but the SwitchNode is 37 */ 38@Immutable 39public final class CaseNode extends Node implements JoinPredecessor, Labels, Terminal { 40 private static final long serialVersionUID = 1L; 41 42 /** Test expression. */ 43 private final Expression test; 44 45 /** Statements. */ 46 private final Block body; 47 48 /** Case entry label. */ 49 private final Label entry; 50 51 /** 52 * @see JoinPredecessor 53 */ 54 private final LocalVariableConversion conversion; 55 56 /** 57 * Constructors 58 * 59 * @param token token 60 * @param finish finish 61 * @param test case test node, can be any node in JavaScript 62 * @param body case body 63 */ 64 public CaseNode(final long token, final int finish, final Expression test, final Block body) { 65 super(token, finish); 66 67 this.test = test; 68 this.body = body; 69 this.entry = new Label("entry"); 70 this.conversion = null; 71 } 72 73 CaseNode(final CaseNode caseNode, final Expression test, final Block body, final LocalVariableConversion conversion) { 74 super(caseNode); 75 76 this.test = test; 77 this.body = body; 78 this.entry = new Label(caseNode.entry); 79 this.conversion = conversion; 80 } 81 82 /** 83 * Is this a terminal case node, i.e. does it end control flow like having a throw or return? 84 * 85 * @return true if this node statement is terminal 86 */ 87 @Override 88 public boolean isTerminal() { 89 return body.isTerminal(); 90 } 91 92 /** 93 * Assist in IR navigation. 94 * @param visitor IR navigating visitor. 95 */ 96 @Override 97 public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 98 if (visitor.enterCaseNode(this)) { 99 final Expression newTest = test == null ? null : (Expression)test.accept(visitor); 100 final Block newBody = body == null ? null : (Block)body.accept(visitor); 101 102 return visitor.leaveCaseNode(setTest(newTest).setBody(newBody)); 103 } 104 105 return this; 106 } 107 108 @Override 109 public void toString(final StringBuilder sb, final boolean printTypes) { 110 if (test != null) { 111 sb.append("case "); 112 test.toString(sb, printTypes); 113 sb.append(':'); 114 } else { 115 sb.append("default:"); 116 } 117 } 118 119 /** 120 * Get the body for this case node 121 * @return the body 122 */ 123 public Block getBody() { 124 return body; 125 } 126 127 /** 128 * Get the entry label for this case node 129 * @return the entry label 130 */ 131 public Label getEntry() { 132 return entry; 133 } 134 135 /** 136 * Get the test expression for this case node 137 * @return the test 138 */ 139 public Expression getTest() { 140 return test; 141 } 142 143 /** 144 * Reset the test expression for this case node 145 * @param test new test expression 146 * @return new or same CaseNode 147 */ 148 public CaseNode setTest(final Expression test) { 149 if (this.test == test) { 150 return this; 151 } 152 return new CaseNode(this, test, body, conversion); 153 } 154 155 @Override 156 public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) { 157 if(this.conversion == conversion) { 158 return this; 159 } 160 return new CaseNode(this, test, body, conversion); 161 } 162 163 @Override 164 public LocalVariableConversion getLocalVariableConversion() { 165 return conversion; 166 } 167 168 private CaseNode setBody(final Block body) { 169 if (this.body == body) { 170 return this; 171 } 172 return new CaseNode(this, test, body, conversion); 173 } 174 175 @Override 176 public List<Label> getLabels() { 177 return Collections.unmodifiableList(Collections.singletonList(entry)); 178 } 179} 180