/*
 * Copyright (c) 2010, 2016, 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.ir;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.parser.Lexer.LexerToken;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Undefined;

Literal nodes represent JavaScript values.
Type parameters:
  • <T> – the literal type
/** * Literal nodes represent JavaScript values. * * @param <T> the literal type */
@Immutable public abstract class LiteralNode<T> extends Expression implements PropertyKey { private static final long serialVersionUID = 1L;
Literal value
/** Literal value */
protected final T value;
Marker for values that must be computed at runtime
/** Marker for values that must be computed at runtime */
public static final Object POSTSET_MARKER = new Object();
Constructor
Params:
  • token – token
  • finish – finish
  • value – the value of the literal
/** * Constructor * * @param token token * @param finish finish * @param value the value of the literal */
protected LiteralNode(final long token, final int finish, final T value) { super(token, finish); this.value = value; }
Copy constructor
Params:
  • literalNode – source node
/** * Copy constructor * * @param literalNode source node */
protected LiteralNode(final LiteralNode<T> literalNode) { this(literalNode, literalNode.value); }
A copy constructor with value change.
Params:
  • literalNode – the original literal node
  • newValue – new value for this node
/** * A copy constructor with value change. * @param literalNode the original literal node * @param newValue new value for this node */
protected LiteralNode(final LiteralNode<T> literalNode, final T newValue) { super(literalNode); this.value = newValue; }
Initialization setter, if required for immutable state. This is used for things like ArrayLiteralNodes that need to carry state for the splitter. Default implementation is just a nop.
Params:
  • lc – lexical context
Returns:new literal node with initialized state, or same if nothing changed
/** * Initialization setter, if required for immutable state. This is used for * things like ArrayLiteralNodes that need to carry state for the splitter. * Default implementation is just a nop. * @param lc lexical context * @return new literal node with initialized state, or same if nothing changed */
public LiteralNode<?> initialize(final LexicalContext lc) { return this; }
Check if the literal value is null
Returns:true if literal value is null
/** * Check if the literal value is null * @return true if literal value is null */
public boolean isNull() { return value == null; } @Override public Type getType() { return Type.typeFor(value.getClass()); } @Override public String getPropertyName() { return JSType.toString(getObject()); }
Fetch boolean value of node.
Returns:boolean value of node.
/** * Fetch boolean value of node. * * @return boolean value of node. */
public boolean getBoolean() { return JSType.toBoolean(value); }
Fetch int32 value of node.
Returns:Int32 value of node.
/** * Fetch int32 value of node. * * @return Int32 value of node. */
public int getInt32() { return JSType.toInt32(value); }
Fetch uint32 value of node.
Returns:uint32 value of node.
/** * Fetch uint32 value of node. * * @return uint32 value of node. */
public long getUint32() { return JSType.toUint32(value); }
Fetch long value of node
Returns:long value of node
/** * Fetch long value of node * * @return long value of node */
public long getLong() { return JSType.toLong(value); }
Fetch double value of node.
Returns:double value of node.
/** * Fetch double value of node. * * @return double value of node. */
public double getNumber() { return JSType.toNumber(value); }
Fetch String value of node.
Returns:String value of node.
/** * Fetch String value of node. * * @return String value of node. */
public String getString() { return JSType.toString(value); }
Fetch Object value of node.
Returns:Object value of node.
/** * Fetch Object value of node. * * @return Object value of node. */
public Object getObject() { return value; }
Test if the value is an array
Returns:True if value is an array
/** * Test if the value is an array * * @return True if value is an array */
public boolean isArray() { return false; } public List<Expression> getElementExpressions() { return null; }
Test if the value is a boolean.
Returns:True if value is a boolean.
/** * Test if the value is a boolean. * * @return True if value is a boolean. */
public boolean isBoolean() { return value instanceof Boolean; }
Test if the value is a string.
Returns:True if value is a string.
/** * Test if the value is a string. * * @return True if value is a string. */
public boolean isString() { return value instanceof String; }
Test if tha value is a number
Returns:True if value is a number
/** * Test if tha value is a number * * @return True if value is a number */
public boolean isNumeric() { return value instanceof Number; }
Assist in IR navigation.
Params:
  • visitor – IR navigating visitor.
/** * Assist in IR navigation. * * @param visitor IR navigating visitor. */
@Override public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { if (visitor.enterLiteralNode(this)) { return visitor.leaveLiteralNode(this); } return this; } @Override public void toString(final StringBuilder sb, final boolean printType) { if (value == null) { sb.append("null"); } else { sb.append(value.toString()); } }
Get the literal node value
Returns:the value
/** * Get the literal node value * @return the value */
public final T getValue() { return value; } private static Expression[] valueToArray(final List<Expression> value) { return value.toArray(new Expression[0]); }
Create a new null literal
Params:
  • token – token
  • finish – finish
Returns:the new literal node
/** * Create a new null literal * * @param token token * @param finish finish * * @return the new literal node */
public static LiteralNode<Object> newInstance(final long token, final int finish) { return new NullLiteralNode(token, finish); }
Create a new null literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
Returns:the new literal node
/** * Create a new null literal based on a parent node (source, token, finish) * * @param parent parent node * * @return the new literal node */
public static LiteralNode<Object> newInstance(final Node parent) { return new NullLiteralNode(parent.getToken(), parent.getFinish()); }
Super class for primitive (side-effect free) literals.
Type parameters:
  • <T> – the literal type
/** * Super class for primitive (side-effect free) literals. * * @param <T> the literal type */
public static class PrimitiveLiteralNode<T> extends LiteralNode<T> { private static final long serialVersionUID = 1L; private PrimitiveLiteralNode(final long token, final int finish, final T value) { super(token, finish, value); } private PrimitiveLiteralNode(final PrimitiveLiteralNode<T> literalNode) { super(literalNode); }
Check if the literal value is boolean true
Returns:true if literal value is boolean true
/** * Check if the literal value is boolean true * @return true if literal value is boolean true */
public boolean isTrue() { return JSType.toBoolean(value); } @Override public boolean isLocal() { return true; } @Override public boolean isAlwaysFalse() { return !isTrue(); } @Override public boolean isAlwaysTrue() { return isTrue(); } } @Immutable private static final class BooleanLiteralNode extends PrimitiveLiteralNode<Boolean> { private static final long serialVersionUID = 1L; private BooleanLiteralNode(final long token, final int finish, final boolean value) { super(Token.recast(token, value ? TokenType.TRUE : TokenType.FALSE), finish, value); } private BooleanLiteralNode(final BooleanLiteralNode literalNode) { super(literalNode); } @Override public boolean isTrue() { return value; } @Override public Type getType() { return Type.BOOLEAN; } @Override public Type getWidestOperationType() { return Type.BOOLEAN; } }
Create a new boolean literal
Params:
  • token – token
  • finish – finish
  • value – true or false
Returns:the new literal node
/** * Create a new boolean literal * * @param token token * @param finish finish * @param value true or false * * @return the new literal node */
public static LiteralNode<Boolean> newInstance(final long token, final int finish, final boolean value) { return new BooleanLiteralNode(token, finish, value); }
Create a new boolean literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
  • value – true or false
Returns:the new literal node
/** * Create a new boolean literal based on a parent node (source, token, finish) * * @param parent parent node * @param value true or false * * @return the new literal node */
public static LiteralNode<?> newInstance(final Node parent, final boolean value) { return new BooleanLiteralNode(parent.getToken(), parent.getFinish(), value); } @Immutable private static final class NumberLiteralNode extends PrimitiveLiteralNode<Number> { private static final long serialVersionUID = 1L; private final Type type = numberGetType(value); private NumberLiteralNode(final long token, final int finish, final Number value) { super(Token.recast(token, TokenType.DECIMAL), finish, value); } private NumberLiteralNode(final NumberLiteralNode literalNode) { super(literalNode); } private static Type numberGetType(final Number number) { if (number instanceof Integer) { return Type.INT; } else if (number instanceof Double) { return Type.NUMBER; } else { assert false; } return null; } @Override public Type getType() { return type; } @Override public Type getWidestOperationType() { return getType(); } }
Create a new number literal
Params:
  • token – token
  • finish – finish
  • value – literal value
Returns:the new literal node
/** * Create a new number literal * * @param token token * @param finish finish * @param value literal value * * @return the new literal node */
public static LiteralNode<Number> newInstance(final long token, final int finish, final Number value) { assert !(value instanceof Long); return new NumberLiteralNode(token, finish, value); }
Create a new number literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
  • value – literal value
Returns:the new literal node
/** * Create a new number literal based on a parent node (source, token, finish) * * @param parent parent node * @param value literal value * * @return the new literal node */
public static LiteralNode<?> newInstance(final Node parent, final Number value) { return new NumberLiteralNode(parent.getToken(), parent.getFinish(), value); } private static class UndefinedLiteralNode extends PrimitiveLiteralNode<Undefined> { private static final long serialVersionUID = 1L; private UndefinedLiteralNode(final long token, final int finish) { super(Token.recast(token, TokenType.OBJECT), finish, ScriptRuntime.UNDEFINED); } private UndefinedLiteralNode(final UndefinedLiteralNode literalNode) { super(literalNode); } }
Create a new undefined literal
Params:
  • token – token
  • finish – finish
  • value – undefined value, passed only for polymorphism discrimination
Returns:the new literal node
/** * Create a new undefined literal * * @param token token * @param finish finish * @param value undefined value, passed only for polymorphism discrimination * * @return the new literal node */
public static LiteralNode<Undefined> newInstance(final long token, final int finish, final Undefined value) { return new UndefinedLiteralNode(token, finish); }
Create a new null literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
  • value – undefined value
Returns:the new literal node
/** * Create a new null literal based on a parent node (source, token, finish) * * @param parent parent node * @param value undefined value * * @return the new literal node */
public static LiteralNode<?> newInstance(final Node parent, final Undefined value) { return new UndefinedLiteralNode(parent.getToken(), parent.getFinish()); } @Immutable private static class StringLiteralNode extends PrimitiveLiteralNode<String> { private static final long serialVersionUID = 1L; private StringLiteralNode(final long token, final int finish, final String value) { super(Token.recast(token, TokenType.STRING), finish, value); } private StringLiteralNode(final StringLiteralNode literalNode) { super(literalNode); } @Override public void toString(final StringBuilder sb, final boolean printType) { sb.append('\"'); sb.append(value); sb.append('\"'); } }
Create a new string literal
Params:
  • token – token
  • finish – finish
  • value – string value
Returns:the new literal node
/** * Create a new string literal * * @param token token * @param finish finish * @param value string value * * @return the new literal node */
public static LiteralNode<String> newInstance(final long token, final int finish, final String value) { return new StringLiteralNode(token, finish, value); }
Create a new String literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
  • value – string value
Returns:the new literal node
/** * Create a new String literal based on a parent node (source, token, finish) * * @param parent parent node * @param value string value * * @return the new literal node */
public static LiteralNode<?> newInstance(final Node parent, final String value) { return new StringLiteralNode(parent.getToken(), parent.getFinish(), value); } @Immutable private static class LexerTokenLiteralNode extends LiteralNode<LexerToken> { private static final long serialVersionUID = 1L; private LexerTokenLiteralNode(final long token, final int finish, final LexerToken value) { super(Token.recast(token, TokenType.STRING), finish, value); //TODO is string the correct token type here? } private LexerTokenLiteralNode(final LexerTokenLiteralNode literalNode) { super(literalNode); } @Override public Type getType() { return Type.OBJECT; } @Override public void toString(final StringBuilder sb, final boolean printType) { sb.append(value.toString()); } }
Create a new literal node for a lexer token
Params:
  • token – token
  • finish – finish
  • value – lexer token value
Returns:the new literal node
/** * Create a new literal node for a lexer token * * @param token token * @param finish finish * @param value lexer token value * * @return the new literal node */
public static LiteralNode<LexerToken> newInstance(final long token, final int finish, final LexerToken value) { return new LexerTokenLiteralNode(token, finish, value); }
Create a new lexer token literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
  • value – lexer token
Returns:the new literal node
/** * Create a new lexer token literal based on a parent node (source, token, finish) * * @param parent parent node * @param value lexer token * * @return the new literal node */
public static LiteralNode<?> newInstance(final Node parent, final LexerToken value) { return new LexerTokenLiteralNode(parent.getToken(), parent.getFinish(), value); }
Get the constant value for an object, or LiteralNode<T>.POSTSET_MARKER if the value can't be statically computed.
Params:
  • object – a node or value object
Returns:the constant value or POSTSET_MARKER
/** * Get the constant value for an object, or {@link #POSTSET_MARKER} if the value can't be statically computed. * * @param object a node or value object * @return the constant value or {@code POSTSET_MARKER} */
public static Object objectAsConstant(final Object object) { if (object == null) { return null; } else if (object instanceof Number || object instanceof String || object instanceof Boolean) { return object; } else if (object instanceof LiteralNode) { return objectAsConstant(((LiteralNode<?>)object).getValue()); } return POSTSET_MARKER; }
Test whether object represents a constant value.
Params:
  • object – a node or value object
Returns:true if object is a constant value
/** * Test whether {@code object} represents a constant value. * @param object a node or value object * @return true if object is a constant value */
public static boolean isConstant(final Object object) { return objectAsConstant(object) != POSTSET_MARKER; } private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> { private static final long serialVersionUID = 1L; private NullLiteralNode(final long token, final int finish) { super(Token.recast(token, TokenType.OBJECT), finish, null); } @Override public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { if (visitor.enterLiteralNode(this)) { return visitor.leaveLiteralNode(this); } return this; } @Override public Type getType() { return Type.OBJECT; } @Override public Type getWidestOperationType() { return Type.OBJECT; } }
Array literal node class.
/** * Array literal node class. */
@Immutable public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode, Splittable { private static final long serialVersionUID = 1L;
Array element type.
/** Array element type. */
private final Type elementType;
Preset constant array.
/** Preset constant array. */
private final Object presets;
Indices of array elements requiring computed post sets.
/** Indices of array elements requiring computed post sets. */
private final int[] postsets;
Ranges for splitting up large literals in code generation
/** Ranges for splitting up large literals in code generation */
private final List<Splittable.SplitRange> splitRanges;
Does this array literal have a spread element?
/** Does this array literal have a spread element? */
private final boolean hasSpread;
Does this array literal have a trailing comma?
/** Does this array literal have a trailing comma?*/
private final boolean hasTrailingComma; @Override public boolean isArray() { return true; } private static final class ArrayLiteralInitializer { static ArrayLiteralNode initialize(final ArrayLiteralNode node) { final Type elementType = computeElementType(node.value); final int[] postsets = computePostsets(node.value); final Object presets = computePresets(node.value, elementType, postsets); return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.splitRanges); } private static Type computeElementType(final Expression[] value) { Type widestElementType = Type.INT; for (final Expression elem : value) { if (elem == null) { widestElementType = widestElementType.widest(Type.OBJECT); //no way to represent undefined as number break; } final Type type = elem.getType().isUnknown() ? Type.OBJECT : elem.getType(); if (type.isBoolean()) { //TODO fix this with explicit boolean types widestElementType = widestElementType.widest(Type.OBJECT); break; } widestElementType = widestElementType.widest(type); if (widestElementType.isObject()) { break; } } return widestElementType; } private static int[] computePostsets(final Expression[] value) { final int[] computed = new int[value.length]; int nComputed = 0; for (int i = 0; i < value.length; i++) { final Expression element = value[i]; if (element == null || !isConstant(element)) { computed[nComputed++] = i; } } return Arrays.copyOf(computed, nComputed); } private static boolean setArrayElement(final int[] array, final int i, final Object n) { if (n instanceof Number) { array[i] = ((Number)n).intValue(); return true; } return false; } private static boolean setArrayElement(final long[] array, final int i, final Object n) { if (n instanceof Number) { array[i] = ((Number)n).longValue(); return true; } return false; } private static boolean setArrayElement(final double[] array, final int i, final Object n) { if (n instanceof Number) { array[i] = ((Number)n).doubleValue(); return true; } return false; } private static int[] presetIntArray(final Expression[] value, final int[] postsets) { final int[] array = new int[value.length]; int nComputed = 0; for (int i = 0; i < value.length; i++) { if (!setArrayElement(array, i, objectAsConstant(value[i]))) { assert postsets[nComputed++] == i; } } assert postsets.length == nComputed; return array; } private static long[] presetLongArray(final Expression[] value, final int[] postsets) { final long[] array = new long[value.length]; int nComputed = 0; for (int i = 0; i < value.length; i++) { if (!setArrayElement(array, i, objectAsConstant(value[i]))) { assert postsets[nComputed++] == i; } } assert postsets.length == nComputed; return array; } private static double[] presetDoubleArray(final Expression[] value, final int[] postsets) { final double[] array = new double[value.length]; int nComputed = 0; for (int i = 0; i < value.length; i++) { if (!setArrayElement(array, i, objectAsConstant(value[i]))) { assert postsets[nComputed++] == i; } } assert postsets.length == nComputed; return array; } private static Object[] presetObjectArray(final Expression[] value, final int[] postsets) { final Object[] array = new Object[value.length]; int nComputed = 0; for (int i = 0; i < value.length; i++) { final Node node = value[i]; if (node == null) { assert postsets[nComputed++] == i; continue; } final Object element = objectAsConstant(node); if (element != POSTSET_MARKER) { array[i] = element; } else { assert postsets[nComputed++] == i; } } assert postsets.length == nComputed; return array; } static Object computePresets(final Expression[] value, final Type elementType, final int[] postsets) { assert !elementType.isUnknown(); if (elementType.isInteger()) { return presetIntArray(value, postsets); } else if (elementType.isNumeric()) { return presetDoubleArray(value, postsets); } else { return presetObjectArray(value, postsets); } } }
Constructor
Params:
  • token – token
  • finish – finish
  • value – array literal value, a Node array
/** * Constructor * * @param token token * @param finish finish * @param value array literal value, a Node array */
protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) { this(token, finish, value, false, false); }
Constructor
Params:
  • token – token
  • finish – finish
  • value – array literal value, a Node array
  • hasSpread – true if the array has a spread element
  • hasTrailingComma – true if the array literal has a comma after the last element
/** * Constructor * * @param token token * @param finish finish * @param value array literal value, a Node array * @param hasSpread true if the array has a spread element * @param hasTrailingComma true if the array literal has a comma after the last element */
protected ArrayLiteralNode(final long token, final int finish, final Expression[] value, final boolean hasSpread, final boolean hasTrailingComma) { super(Token.recast(token, TokenType.ARRAY), finish, value); this.elementType = Type.UNKNOWN; this.presets = null; this.postsets = null; this.splitRanges = null; this.hasSpread = hasSpread; this.hasTrailingComma = hasTrailingComma; }
Copy constructor
Params:
  • node – source array literal node
/** * Copy constructor * @param node source array literal node */
private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<Splittable.SplitRange> splitRanges) { super(node, value); this.elementType = elementType; this.postsets = postsets; this.presets = presets; this.splitRanges = splitRanges; this.hasSpread = node.hasSpread; this.hasTrailingComma = node.hasTrailingComma; }
Returns true if this array literal has a spread element.
Returns:true if this literal has a spread element
/** * Returns {@code true} if this array literal has a spread element. * @return true if this literal has a spread element */
public boolean hasSpread() { return hasSpread; }
Returns true if this array literal has a trailing comma.
Returns:true if this literal has a trailing comma
/** * Returns {@code true} if this array literal has a trailing comma. * @return true if this literal has a trailing comma */
public boolean hasTrailingComma() { return hasTrailingComma; }
Returns a list of array element expressions. Note that empty array elements manifest themselves as null.
Returns:a list of array element expressions.
/** * Returns a list of array element expressions. Note that empty array elements manifest themselves as * null. * @return a list of array element expressions. */
@Override public List<Expression> getElementExpressions() { return Collections.unmodifiableList(Arrays.asList(value)); }
Setter that initializes all code generation meta data for an ArrayLiteralNode. This acts a setter, so the return value may return a new node and must be handled
Params:
  • lc – lexical context
Returns:new array literal node with postsets, presets and element types initialized
/** * Setter that initializes all code generation meta data for an * ArrayLiteralNode. This acts a setter, so the return value may * return a new node and must be handled * * @param lc lexical context * @return new array literal node with postsets, presets and element types initialized */
@Override public ArrayLiteralNode initialize(final LexicalContext lc) { return Node.replaceInLexicalContext(lc, this, ArrayLiteralInitializer.initialize(this)); }
Get the array element type as Java format, e.g. [I
Returns:array element type
/** * Get the array element type as Java format, e.g. [I * @return array element type */
public ArrayType getArrayType() { return getArrayType(getElementType()); } private static ArrayType getArrayType(final Type elementType) { if (elementType.isInteger()) { return Type.INT_ARRAY; } else if (elementType.isNumeric()) { return Type.NUMBER_ARRAY; } else { return Type.OBJECT_ARRAY; } } @Override public Type getType() { return Type.typeFor(NativeArray.class); }
Get the element type of this array literal
Returns:element type
/** * Get the element type of this array literal * @return element type */
public Type getElementType() { assert !elementType.isUnknown() : this + " has elementType=unknown"; return elementType; }
Get indices of arrays containing computed post sets. post sets are things like non literals e.g. "x+y" instead of i or 17
Returns:post set indices
/** * Get indices of arrays containing computed post sets. post sets * are things like non literals e.g. "x+y" instead of i or 17 * @return post set indices */
public int[] getPostsets() { assert postsets != null : this + " elementType=" + elementType + " has no postsets"; return postsets; } private boolean presetsMatchElementType() { if (elementType == Type.INT) { return presets instanceof int[]; } else if (elementType == Type.NUMBER) { return presets instanceof double[]; } else { return presets instanceof Object[]; } }
Get presets constant array
Returns:presets array, always returns an array type
/** * Get presets constant array * @return presets array, always returns an array type */
public Object getPresets() { assert presets != null && presetsMatchElementType() : this + " doesn't have presets, or invalid preset type: " + presets; return presets; }
Get the split ranges for this ArrayLiteral, or null if this array does not have to be split.
See Also:
  • SplitRange
Returns:list of split ranges
/** * Get the split ranges for this ArrayLiteral, or null if this array does not have to be split. * @see Splittable.SplitRange * @return list of split ranges */
@Override public List<Splittable.SplitRange> getSplitRanges() { return splitRanges == null ? null : Collections.unmodifiableList(splitRanges); }
Set the SplitRanges that make up this ArrayLiteral
Params:
  • lc – lexical context
  • splitRanges – list of split ranges
See Also:
Returns:new or changed node
/** * Set the SplitRanges that make up this ArrayLiteral * @param lc lexical context * @see Splittable.SplitRange * @param splitRanges list of split ranges * @return new or changed node */
public ArrayLiteralNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) { if (this.splitRanges == splitRanges) { return this; } return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges)); } @Override public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { return Acceptor.accept(this, visitor); } @Override public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { if (visitor.enterLiteralNode(this)) { final List<Expression> oldValue = Arrays.asList(value); final List<Expression> newValue = Node.accept(visitor, oldValue); return visitor.leaveLiteralNode(oldValue != newValue ? setValue(lc, newValue) : this); } return this; } private ArrayLiteralNode setValue(final LexicalContext lc, final Expression[] value) { if (this.value == value) { return this; } return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges)); } private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) { return setValue(lc, value.toArray(new Expression[0])); } @Override public void toString(final StringBuilder sb, final boolean printType) { sb.append('['); boolean first = true; for (final Node node : value) { if (!first) { sb.append(','); sb.append(' '); } if (node == null) { sb.append("undefined"); } else { node.toString(sb, printType); } first = false; } sb.append(']'); } }
Create a new array literal of Nodes from a list of Node values
Params:
  • token – token
  • finish – finish
  • value – literal value list
Returns:the new literal node
/** * Create a new array literal of Nodes from a list of Node values * * @param token token * @param finish finish * @param value literal value list * * @return the new literal node */
public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final List<Expression> value) { return new ArrayLiteralNode(token, finish, valueToArray(value)); }
Create a new array literal based on a parent node (source, token, finish)
Params:
  • parent – parent node
  • value – literal value list
Returns:the new literal node
/** * Create a new array literal based on a parent node (source, token, finish) * * @param parent parent node * @param value literal value list * * @return the new literal node */
public static LiteralNode<?> newInstance(final Node parent, final List<Expression> value) { return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), valueToArray(value)); } /* * Create a new array literal of Nodes from a list of Node values * * @param token token * @param finish finish * @param value literal value list * @param hasSpread true if the array has a spread element * @param hasTrailingComma true if the array literal has a comma after the last element * * @return the new literal node */ public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final List<Expression> value, final boolean hasSpread, final boolean hasTrailingComma) { return new ArrayLiteralNode(token, finish, valueToArray(value), hasSpread, hasTrailingComma); }
Create a new array literal of Nodes
Params:
  • token – token
  • finish – finish
  • value – literal value array
Returns:the new literal node
/** * Create a new array literal of Nodes * * @param token token * @param finish finish * @param value literal value array * * @return the new literal node */
public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final Expression[] value) { return new ArrayLiteralNode(token, finish, value); } }