blob: 34e1e0cca603c441a09426d670bae2b34f12e750 [file] [log] [blame]
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.parser;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.Module;
/**
* ParserContextNode that represents a function that is currently being parsed
*/
class ParserContextFunctionNode extends ParserContextBaseNode {
/** Function name */
private final String name;
/** Function identifier node */
private final IdentNode ident;
/** Name space for function */
private final Namespace namespace;
/** Line number for function declaration */
private final int line;
/** Function node kind, see {@link FunctionNode.Kind} */
private final FunctionNode.Kind kind;
/** List of parameter identifiers for function */
private List<IdentNode> parameters;
/** Token for function start */
private final long token;
/** Last function token */
private long lastToken;
/** Opaque node for parser end state, see {@link Parser} */
private Object endParserState;
private HashSet<String> parameterBoundNames;
private IdentNode duplicateParameterBinding;
private boolean simpleParameterList = true;
private Module module;
private int debugFlags;
private Map<IdentNode, Expression> parameterExpressions;
/**
* @param token The token for the function
* @param ident External function name
* @param name Internal name of the function
* @param namespace Function's namespace
* @param line The source line of the function
* @param kind Function kind
* @param parameters The parameters of the function
*/
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) {
this.ident = ident;
this.namespace = namespace;
this.line = line;
this.kind = kind;
this.name = name;
this.parameters = parameters;
this.token = token;
}
/**
* @return Internal name of the function
*/
public String getName() {
return name;
}
/**
* @return The external identifier for the function
*/
public IdentNode getIdent() {
return ident;
}
/**
*
* @return true if function is the program function
*/
public boolean isProgram() {
return getFlag(FunctionNode.IS_PROGRAM) != 0;
}
/**
* @return if function in strict mode
*/
public boolean isStrict() {
return getFlag(FunctionNode.IS_STRICT) != 0;
}
/**
* @return true if the function has nested evals
*/
public boolean hasNestedEval() {
return getFlag(FunctionNode.HAS_NESTED_EVAL) != 0;
}
/**
* Returns true if any of the blocks in this function create their own scope.
* @return true if any of the blocks in this function create their own scope.
*/
public boolean hasScopeBlock() {
return getFlag(FunctionNode.HAS_SCOPE_BLOCK) != 0;
}
/**
* Create a unique name in the namespace of this FunctionNode
* @param base prefix for name
* @return base if no collision exists, otherwise a name prefix with base
*/
public String uniqueName(final String base) {
return namespace.uniqueName(base);
}
/**
* @return line number of the function
*/
public int getLineNumber() {
return line;
}
/**
* @return The kind if function
*/
public FunctionNode.Kind getKind() {
return kind;
}
/**
* Get parameters
* @return The parameters of the function
*/
public List<IdentNode> getParameters() {
return parameters;
}
void setParameters(final List<IdentNode> parameters) {
this.parameters = parameters;
}
/**
* Return ES6 function parameter expressions
*
* @return ES6 function parameter expressions
*/
public Map<IdentNode, Expression> getParameterExpressions() {
return parameterExpressions;
}
void addParameterExpression(final IdentNode ident, final Expression node) {
if (parameterExpressions == null) {
parameterExpressions = new HashMap<>();
}
parameterExpressions.put(ident, node);
}
/**
* Set last token
* @param token New last token
*/
public void setLastToken(final long token) {
this.lastToken = token;
}
/**
* @return lastToken Function's last token
*/
public long getLastToken() {
return lastToken;
}
/**
* Returns the ParserState of when the parsing of this function was ended
* @return endParserState The end parser state
*/
public Object getEndParserState() {
return endParserState;
}
/**
* Sets the ParserState of when the parsing of this function was ended
* @param endParserState The end parser state
*/
public void setEndParserState(final Object endParserState) {
this.endParserState = endParserState;
}
/**
* Returns the if of this function
* @return The function id
*/
public int getId() {
return isProgram() ? -1 : Token.descPosition(token);
}
/**
* Returns the debug flags for this function.
*
* @return the debug flags
*/
int getDebugFlags() {
return debugFlags;
}
/**
* Sets a debug flag for this function.
*
* @param debugFlag the debug flag
*/
void setDebugFlag(final int debugFlag) {
debugFlags |= debugFlag;
}
public boolean isMethod() {
return getFlag(FunctionNode.ES6_IS_METHOD) != 0;
}
public boolean isClassConstructor() {
return getFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR) != 0;
}
public boolean isSubclassConstructor() {
return getFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR) != 0;
}
boolean addParameterBinding(final IdentNode bindingIdentifier) {
if (Parser.isArguments(bindingIdentifier)) {
setFlag(FunctionNode.DEFINES_ARGUMENTS);
}
if (parameterBoundNames == null) {
parameterBoundNames = new HashSet<>();
}
if (parameterBoundNames.add(bindingIdentifier.getName())) {
return true;
} else {
duplicateParameterBinding = bindingIdentifier;
return false;
}
}
public IdentNode getDuplicateParameterBinding() {
return duplicateParameterBinding;
}
public boolean isSimpleParameterList() {
return simpleParameterList;
}
public void setSimpleParameterList(final boolean simpleParameterList) {
this.simpleParameterList = simpleParameterList;
}
public Module getModule() {
return module;
}
public void setModule(final Module module) {
this.module = module;
}
}