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 java.util.Collections; 29 import java.util.List; 30 import java.util.RandomAccess; 31 import jdk.nashorn.internal.codegen.types.Type; 32 import jdk.nashorn.internal.ir.annotations.Ignore; 33 import jdk.nashorn.internal.ir.annotations.Immutable; 34 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 35 36 /** 37 * IR representation of an object literal. 38 */ 39 @Immutable 40 public final class ObjectNode extends Expression implements LexicalContextNode, Splittable { 41 private static final long serialVersionUID = 1L; 42 43 /** Literal elements. */ 44 private final List<PropertyNode> elements; 45 46 /** Ranges for splitting large literals over multiple compile units in codegen. */ 47 @Ignore 48 private final List<Splittable.SplitRange> splitRanges; 49 50 /** 51 * Constructor 52 * 53 * @param token token 54 * @param finish finish 55 * @param elements the elements used to initialize this ObjectNode 56 */ 57 public ObjectNode(final long token, final int finish, final List<PropertyNode> elements) { 58 super(token, finish); 59 this.elements = elements; 60 this.splitRanges = null; 61 assert elements instanceof RandomAccess : "Splitting requires random access lists"; 62 } 63 64 private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements, 65 final List<Splittable.SplitRange> splitRanges ) { 66 super(objectNode); 67 this.elements = elements; 68 this.splitRanges = splitRanges; 69 } 70 71 @Override 72 public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 73 return Acceptor.accept(this, visitor); 74 } 75 76 @Override 77 public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 78 if (visitor.enterObjectNode(this)) { 79 return visitor.leaveObjectNode(setElements(lc, Node.accept(visitor, elements))); 80 } 81 return this; 82 } 83 84 @Override 85 public Type getType() { 86 return Type.OBJECT; 87 } 88 89 @Override 90 public void toString(final StringBuilder sb, final boolean printType) { 91 sb.append('{'); 92 93 if (!elements.isEmpty()) { 94 sb.append(' '); 95 96 boolean first = true; 97 for (final Node element : elements) { 98 if (!first) { 99 sb.append(", "); 100 } 101 first = false; 102 103 element.toString(sb, printType); 104 } 105 sb.append(' '); 106 } 107 108 sb.append('}'); 109 } 110 111 /** 112 * Get the elements of this literal node 113 * @return a list of elements 114 */ 115 public List<PropertyNode> getElements() { 116 return Collections.unmodifiableList(elements); 117 } 118 119 private ObjectNode setElements(final LexicalContext lc, final List<PropertyNode> elements) { 120 if (this.elements == elements) { 121 return this; 122 } 123 return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, this.splitRanges)); 124 } 125 126 /** 127 * Set the split ranges for this ObjectNode 128 * @see Splittable.SplitRange 129 * @param lc the lexical context 130 * @param splitRanges list of split ranges 131 * @return new or changed object node 132 */ 133 public ObjectNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) { 134 if (this.splitRanges == splitRanges) { 135 return this; 136 } 137 return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, splitRanges)); 138 } 139 140 /** 141 * Get the split ranges for this ObjectNode, or null if the object is not split. 142 * @see Splittable.SplitRange 143 * @return list of split ranges 144 */ 145 @Override 146 public List<Splittable.SplitRange> getSplitRanges() { 147 return splitRanges == null ? null : Collections.unmodifiableList(splitRanges); 148 } 149 150 }