1 /* 2 * Copyright (c) 2014, 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 package jdk.nashorn.internal.parser; 26 27 import java.util.HashMap; 28 import java.util.HashSet; 29 import java.util.List; 30 import java.util.Map; 31 import jdk.nashorn.internal.codegen.Namespace; 32 import jdk.nashorn.internal.ir.Expression; 33 import jdk.nashorn.internal.ir.FunctionNode; 34 import jdk.nashorn.internal.ir.IdentNode; 35 import jdk.nashorn.internal.ir.Module; 36 37 /** 38 * ParserContextNode that represents a function that is currently being parsed 39 */ 40 class ParserContextFunctionNode extends ParserContextBaseNode { 41 42 /** Function name */ 43 private final String name; 44 45 /** Function identifier node */ 46 private final IdentNode ident; 47 48 /** Name space for function */ 49 private final Namespace namespace; 50 51 /** Line number for function declaration */ 52 private final int line; 53 54 /** Function node kind, see {@link FunctionNode.Kind} */ 55 private final FunctionNode.Kind kind; 56 57 /** List of parameter identifiers for function */ 58 private List<IdentNode> parameters; 59 60 /** Token for function start */ 61 private final long token; 62 63 /** Last function token */ 64 private long lastToken; 65 66 /** Opaque node for parser end state, see {@link Parser} */ 67 private Object endParserState; 68 69 private HashSet<String> parameterBoundNames; 70 private IdentNode duplicateParameterBinding; 71 private boolean simpleParameterList = true; 72 73 private Module module; 74 75 private int debugFlags; 76 private Map<IdentNode, Expression> parameterExpressions; 77 78 /** 79 * @param token The token for the function 80 * @param ident External function name 81 * @param name Internal name of the function 82 * @param namespace Function's namespace 83 * @param line The source line of the function 84 * @param kind Function kind 85 * @param parameters The parameters of the function 86 */ 87 public ParserContextFunctionNode(final long token, final IdentNode ident, final String name, final Namespace namespace, final int line, final FunctionNode.Kind kind, final List<IdentNode> parameters) { 88 this.ident = ident; 89 this.namespace = namespace; 90 this.line = line; 91 this.kind = kind; 92 this.name = name; 93 this.parameters = parameters; 94 this.token = token; 95 } 96 97 /** 98 * @return Internal name of the function 99 */ 100 public String getName() { 101 return name; 102 } 103 104 /** 105 * @return The external identifier for the function 106 */ 107 public IdentNode getIdent() { 108 return ident; 109 } 110 111 /** 112 * 113 * @return true if function is the program function 114 */ 115 public boolean isProgram() { 116 return getFlag(FunctionNode.IS_PROGRAM) != 0; 117 } 118 119 /** 120 * @return if function in strict mode 121 */ 122 public boolean isStrict() { 123 return getFlag(FunctionNode.IS_STRICT) != 0; 124 } 125 126 /** 127 * @return true if the function has nested evals 128 */ 129 public boolean hasNestedEval() { 130 return getFlag(FunctionNode.HAS_NESTED_EVAL) != 0; 131 } 132 133 /** 134 * Returns true if any of the blocks in this function create their own scope. 135 * @return true if any of the blocks in this function create their own scope. 136 */ 137 public boolean hasScopeBlock() { 138 return getFlag(FunctionNode.HAS_SCOPE_BLOCK) != 0; 139 } 140 141 /** 142 * Create a unique name in the namespace of this FunctionNode 143 * @param base prefix for name 144 * @return base if no collision exists, otherwise a name prefix with base 145 */ 146 public String uniqueName(final String base) { 147 return namespace.uniqueName(base); 148 } 149 150 /** 151 * @return line number of the function 152 */ 153 public int getLineNumber() { 154 return line; 155 } 156 157 /** 158 * @return The kind if function 159 */ 160 public FunctionNode.Kind getKind() { 161 return kind; 162 } 163 164 /** 165 * Get parameters 166 * @return The parameters of the function 167 */ 168 public List<IdentNode> getParameters() { 169 return parameters; 170 } 171 172 void setParameters(final List<IdentNode> parameters) { 173 this.parameters = parameters; 174 } 175 176 /** 177 * Return ES6 function parameter expressions 178 * 179 * @return ES6 function parameter expressions 180 */ 181 public Map<IdentNode, Expression> getParameterExpressions() { 182 return parameterExpressions; 183 } 184 185 void addParameterExpression(final IdentNode ident, final Expression node) { 186 if (parameterExpressions == null) { 187 parameterExpressions = new HashMap<>(); 188 } 189 parameterExpressions.put(ident, node); 190 } 191 192 /** 193 * Set last token 194 * @param token New last token 195 */ 196 public void setLastToken(final long token) { 197 this.lastToken = token; 198 199 } 200 201 /** 202 * @return lastToken Function's last token 203 */ 204 public long getLastToken() { 205 return lastToken; 206 } 207 208 /** 209 * Returns the ParserState of when the parsing of this function was ended 210 * @return endParserState The end parser state 211 */ 212 public Object getEndParserState() { 213 return endParserState; 214 } 215 216 /** 217 * Sets the ParserState of when the parsing of this function was ended 218 * @param endParserState The end parser state 219 */ 220 public void setEndParserState(final Object endParserState) { 221 this.endParserState = endParserState; 222 } 223 224 /** 225 * Returns the if of this function 226 * @return The function id 227 */ 228 public int getId() { 229 return isProgram() ? -1 : Token.descPosition(token); 230 } 231 232 /** 233 * Returns the debug flags for this function. 234 * 235 * @return the debug flags 236 */ 237 int getDebugFlags() { 238 return debugFlags; 239 } 240 241 /** 242 * Sets a debug flag for this function. 243 * 244 * @param debugFlag the debug flag 245 */ 246 void setDebugFlag(final int debugFlag) { 247 debugFlags |= debugFlag; 248 } 249 250 public boolean isMethod() { 251 return getFlag(FunctionNode.ES6_IS_METHOD) != 0; 252 } 253 254 public boolean isClassConstructor() { 255 return getFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR) != 0; 256 } 257 258 public boolean isSubclassConstructor() { 259 return getFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR) != 0; 260 } 261 262 boolean addParameterBinding(final IdentNode bindingIdentifier) { 263 if (Parser.isArguments(bindingIdentifier)) { 264 setFlag(FunctionNode.DEFINES_ARGUMENTS); 265 } 266 267 if (parameterBoundNames == null) { 268 parameterBoundNames = new HashSet<>(); 269 } 270 if (parameterBoundNames.add(bindingIdentifier.getName())) { 271 return true; 272 } else { 273 duplicateParameterBinding = bindingIdentifier; 274 return false; 275 } 276 } 277 278 public IdentNode getDuplicateParameterBinding() { 279 return duplicateParameterBinding; 280 } 281 282 public boolean isSimpleParameterList() { 283 return simpleParameterList; 284 } 285 286 public void setSimpleParameterList(final boolean simpleParameterList) { 287 this.simpleParameterList = simpleParameterList; 288 } 289 290 public Module getModule() { 291 return module; 292 } 293 294 public void setModule(final Module module) { 295 this.module = module; 296 } 297 }