comparison truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java @ 22153:b59d06483580

PropertyMap refactoring
author Andreas Woess <andreas.woess@oracle.com>
date Mon, 14 Sep 2015 18:32:54 +0200
parents 9c8c0937da41
children dc83cc1f94f2
comparison
equal deleted inserted replaced
22152:291574f3e498 22153:b59d06483580
1 /* 1 /*
2 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
24 24
25 import java.util.*; 25 import java.util.*;
26 26
27 import com.oracle.truffle.api.object.*; 27 import com.oracle.truffle.api.object.*;
28 28
29 public final class PropertyMap implements Map<Object, Property> { 29 /**
30 private final PropertyMap car; 30 * Immutable property map.
31 private final Property cdr; 31 */
32 private final int size; 32 public abstract class PropertyMap implements ImmutableMap<Object, Property> {
33 33
34 private static final PropertyMap EMPTY = new PropertyMap(); 34 public static PropertyMap empty() {
35 35 return ConsListPropertyMap.empty();
36 private PropertyMap() {
37 this.car = null;
38 this.cdr = null;
39 this.size = 0;
40 } 36 }
41 37
42 private PropertyMap(PropertyMap parent, Property added) { 38 public abstract Iterator<Object> orderedKeyIterator();
43 this.car = Objects.requireNonNull(parent);
44 this.cdr = added;
45 this.size = parent.size + 1;
46 }
47 39
48 public static PropertyMap empty() { 40 public abstract Iterator<Object> reverseOrderedKeyIterator();
49 return EMPTY;
50 }
51 41
52 public int size() { 42 public abstract Iterator<Property> orderedValueIterator();
53 return size;
54 }
55 43
56 public boolean isEmpty() { 44 public abstract Iterator<Property> reverseOrderedValueIterator();
57 return size() == 0;
58 }
59 45
60 public boolean containsKey(Object key) { 46 public abstract Property getLastProperty();
61 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
62 if (entry.getKey().equals(key)) {
63 return true;
64 }
65 }
66 return false;
67 }
68 47
69 public boolean containsValue(Object value) { 48 public abstract PropertyMap putCopy(final Property element);
70 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
71 if (entry.getValue().equals(value)) {
72 return true;
73 }
74 }
75 return false;
76 }
77 49
78 public Property get(Object key) { 50 public abstract PropertyMap replaceCopy(final Property oldValue, final Property newValue);
79 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
80 if (entry.getKey().equals(key)) {
81 return entry.getValue();
82 }
83 }
84 return null;
85 }
86 51
87 public Property put(Object key, Property value) { 52 public abstract PropertyMap removeCopy(final Property value);
53
54 public abstract PropertyMap getParentMap();
55
56 @Override
57 public Property put(final Object key, final Property value) {
88 throw unmodifiableException(); 58 throw unmodifiableException();
89 } 59 }
90 60
91 public Property remove(Object key) { 61 @Override
62 public void putAll(final Map<? extends Object, ? extends Property> m) {
92 throw unmodifiableException(); 63 throw unmodifiableException();
93 } 64 }
94 65
95 public void putAll(Map<? extends Object, ? extends Property> m) { 66 @Override
67 public Property remove(final Object key) {
96 throw unmodifiableException(); 68 throw unmodifiableException();
97 } 69 }
98 70
71 @Override
99 public void clear() { 72 public void clear() {
100 throw unmodifiableException(); 73 throw unmodifiableException();
101 } 74 }
102 75
103 public Set<Object> keySet() { 76 protected static RuntimeException unmodifiableException() {
104 return new AbstractSet<Object>() { 77 throw new UnsupportedOperationException();
105 @Override
106 public Iterator<Object> iterator() {
107 Object[] keys = new Object[size()];
108 Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
109 for (int pos = size() - 1; pos >= 0; pos--) {
110 keys[pos] = iterator.next().getKey();
111 }
112 return Arrays.asList(keys).iterator();
113 }
114
115 @Override
116 public int size() {
117 return PropertyMap.this.size();
118 }
119 };
120 }
121
122 public Collection<Property> values() {
123 return new AbstractSet<Property>() {
124 @Override
125 public Iterator<Property> iterator() {
126 Property[] values = new Property[size()];
127 Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
128 for (int pos = size() - 1; pos >= 0; pos--) {
129 values[pos] = iterator.next().getValue();
130 }
131 return Arrays.asList(values).iterator();
132 }
133
134 @Override
135 public int size() {
136 return PropertyMap.this.size();
137 }
138 };
139 }
140
141 public Set<Map.Entry<Object, Property>> entrySet() {
142 return new AbstractSet<Map.Entry<Object, Property>>() {
143 @Override
144 public Iterator<Map.Entry<Object, Property>> iterator() {
145 @SuppressWarnings("unchecked")
146 Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()];
147 Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
148 for (int pos = size() - 1; pos >= 0; pos--) {
149 entries[pos] = iterator.next();
150 }
151 return Arrays.asList(entries).iterator();
152 }
153
154 @Override
155 public int size() {
156 return PropertyMap.this.size();
157 }
158 };
159 }
160
161 public Set<Map.Entry<Object, Property>> reverseOrderEntrySet() {
162 return new AbstractSet<Map.Entry<Object, Property>>() {
163 @Override
164 public Iterator<Map.Entry<Object, Property>> iterator() {
165 return new Iterator<Map.Entry<Object, Property>>() {
166 PropertyMap current = PropertyMap.this;
167
168 public Entry<Object, Property> next() {
169 if (hasNext()) {
170 try {
171 return new MapEntryImpl(current.cdr);
172 } finally {
173 current = current.car;
174 }
175 } else {
176 throw new NoSuchElementException();
177 }
178 }
179
180 public boolean hasNext() {
181 return current != empty();
182 }
183
184 public void remove() {
185 throw new UnsupportedOperationException();
186 }
187 };
188 }
189
190 @Override
191 public int size() {
192 return PropertyMap.this.size();
193 }
194 };
195 }
196
197 public Set<Object> reverseOrderKeys() {
198 return new AbstractSet<Object>() {
199 @Override
200 public Iterator<Object> iterator() {
201 return new Iterator<Object>() {
202 PropertyMap current = PropertyMap.this;
203
204 public Object next() {
205 if (hasNext()) {
206 try {
207 return current.cdr.getKey();
208 } finally {
209 current = current.car;
210 }
211 } else {
212 throw new NoSuchElementException();
213 }
214 }
215
216 public boolean hasNext() {
217 return current != empty();
218 }
219
220 public void remove() {
221 throw new UnsupportedOperationException();
222 }
223 };
224 }
225
226 @Override
227 public int size() {
228 return PropertyMap.this.size();
229 }
230 };
231 }
232
233 public Set<Property> reverseOrderValues() {
234 return new AbstractSet<Property>() {
235 @Override
236 public Iterator<Property> iterator() {
237 return new Iterator<Property>() {
238 PropertyMap current = PropertyMap.this;
239
240 public Property next() {
241 if (hasNext()) {
242 try {
243 return current.cdr;
244 } finally {
245 current = current.car;
246 }
247 } else {
248 throw new NoSuchElementException();
249 }
250 }
251
252 public boolean hasNext() {
253 return current != empty();
254 }
255
256 public void remove() {
257 throw new UnsupportedOperationException();
258 }
259 };
260 }
261
262 @Override
263 public int size() {
264 return PropertyMap.this.size();
265 }
266 };
267 }
268
269 private static final class MapEntryImpl implements Map.Entry<Object, Property> {
270 private final Property backingProperty;
271
272 public MapEntryImpl(Property backingProperty) {
273 this.backingProperty = backingProperty;
274 }
275
276 public Object getKey() {
277 return backingProperty.getKey();
278 }
279
280 public Property getValue() {
281 return backingProperty;
282 }
283
284 public Property setValue(Property value) {
285 throw unmodifiableException();
286 }
287 }
288
289 private static UnsupportedOperationException unmodifiableException() {
290 throw new UnsupportedOperationException("unmodifiable");
291 }
292
293 public PropertyMap putCopy(Property value) {
294 return new PropertyMap(this, value);
295 }
296
297 public PropertyMap removeCopy(Property value) {
298 Deque<Property> shelve = new ArrayDeque<>();
299 PropertyMap current = this;
300 while (!current.isEmpty()) {
301 if (current.getLastProperty().equals(value)) {
302 PropertyMap newMap = current.getParentMap();
303 for (Property property : shelve) {
304 newMap = newMap.putCopy(property);
305 }
306 return newMap;
307 } else {
308 shelve.push(current.getLastProperty());
309 current = current.getParentMap();
310 }
311 }
312 return this;
313 }
314
315 public PropertyMap replaceCopy(Property oldValue, Property newValue) {
316 Deque<Property> shelve = new ArrayDeque<>();
317 PropertyMap current = this;
318 while (!current.isEmpty()) {
319 if (current.getLastProperty().equals(oldValue)) {
320 PropertyMap newMap = current.getParentMap();
321 newMap = newMap.putCopy(newValue);
322 for (Property property : shelve) {
323 newMap = newMap.putCopy(property);
324 }
325 return newMap;
326 } else {
327 shelve.push(current.getLastProperty());
328 current = current.getParentMap();
329 }
330 }
331 return this;
332 }
333
334 public PropertyMap getOwningMap(Property value) {
335 PropertyMap current = this;
336 while (!current.isEmpty()) {
337 if (current.getLastProperty().equals(value)) {
338 return current;
339 }
340 current = current.getParentMap();
341 }
342 return null;
343 }
344
345 PropertyMap getParentMap() {
346 return car;
347 }
348
349 public Property getLastProperty() {
350 return cdr;
351 }
352
353 @Override
354 public String toString() {
355 return values().toString();
356 } 78 }
357 } 79 }