Mercurial > hg > graal-jvmci-8
diff graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java @ 18408:2c3666f44855
Truffle: initial commit of object API implementation
author | Andreas Woess <andreas.woess@jku.at> |
---|---|
date | Tue, 18 Nov 2014 23:19:43 +0100 |
parents | |
children | de8880bbf2e1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java Tue Nov 18 23:19:43 2014 +0100 @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2014, 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. + * + * 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 com.oracle.truffle.object; + +import java.util.*; + +import com.oracle.truffle.api.object.*; + +public final class PropertyMap implements Map<Object, Property> { + private final PropertyMap car; + private final Property cdr; + private final int size; + + private static final PropertyMap EMPTY = new PropertyMap(); + + private PropertyMap() { + this.car = null; + this.cdr = null; + this.size = 0; + } + + private PropertyMap(PropertyMap parent, Property added) { + this.car = Objects.requireNonNull(parent); + this.cdr = added; + this.size = parent.size + 1; + } + + public static PropertyMap empty() { + return EMPTY; + } + + public int size() { + return size; + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean containsKey(Object key) { + for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) { + if (entry.getKey().equals(key)) { + return true; + } + } + return false; + } + + public boolean containsValue(Object value) { + for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) { + if (entry.getValue().equals(value)) { + return true; + } + } + return false; + } + + public Property get(Object key) { + for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) { + if (entry.getKey().equals(key)) { + return entry.getValue(); + } + } + return null; + } + + public Property put(Object key, Property value) { + throw unmodifiableException(); + } + + public Property remove(Object key) { + throw unmodifiableException(); + } + + public void putAll(Map<? extends Object, ? extends Property> m) { + throw unmodifiableException(); + } + + public void clear() { + throw unmodifiableException(); + } + + public Set<Object> keySet() { + return new AbstractSet<Object>() { + @Override + public Iterator<Object> iterator() { + Object[] keys = new Object[size()]; + Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator(); + for (int pos = size() - 1; pos >= 0; pos--) { + keys[pos] = iterator.next().getKey(); + } + return Arrays.asList(keys).iterator(); + } + + @Override + public int size() { + return PropertyMap.this.size(); + } + }; + } + + public Collection<Property> values() { + return new AbstractSet<Property>() { + @Override + public Iterator<Property> iterator() { + Property[] values = new Property[size()]; + Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator(); + for (int pos = size() - 1; pos >= 0; pos--) { + values[pos] = iterator.next().getValue(); + } + return Arrays.asList(values).iterator(); + } + + @Override + public int size() { + return PropertyMap.this.size(); + } + }; + } + + public Set<Map.Entry<Object, Property>> entrySet() { + return new AbstractSet<Map.Entry<Object, Property>>() { + @Override + public Iterator<Map.Entry<Object, Property>> iterator() { + @SuppressWarnings("unchecked") + Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()]; + Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator(); + for (int pos = size() - 1; pos >= 0; pos--) { + entries[pos] = iterator.next(); + } + return Arrays.asList(entries).iterator(); + } + + @Override + public int size() { + return PropertyMap.this.size(); + } + }; + } + + public Set<Map.Entry<Object, Property>> reverseOrderEntrySet() { + return new AbstractSet<Map.Entry<Object, Property>>() { + @Override + public Iterator<Map.Entry<Object, Property>> iterator() { + return new Iterator<Map.Entry<Object, Property>>() { + PropertyMap current = PropertyMap.this; + + public Entry<Object, Property> next() { + if (hasNext()) { + try { + return new MapEntryImpl(current.cdr); + } finally { + current = current.car; + } + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return current != empty(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return PropertyMap.this.size(); + } + }; + } + + public Set<Object> reverseOrderKeys() { + return new AbstractSet<Object>() { + @Override + public Iterator<Object> iterator() { + return new Iterator<Object>() { + PropertyMap current = PropertyMap.this; + + public Object next() { + if (hasNext()) { + try { + return current.cdr.getKey(); + } finally { + current = current.car; + } + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return current != empty(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return PropertyMap.this.size(); + } + }; + } + + public Set<Property> reverseOrderValues() { + return new AbstractSet<Property>() { + @Override + public Iterator<Property> iterator() { + return new Iterator<Property>() { + PropertyMap current = PropertyMap.this; + + public Property next() { + if (hasNext()) { + try { + return current.cdr; + } finally { + current = current.car; + } + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return current != empty(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return PropertyMap.this.size(); + } + }; + } + + private static final class MapEntryImpl implements Map.Entry<Object, Property> { + private final Property backingProperty; + + public MapEntryImpl(Property backingProperty) { + this.backingProperty = backingProperty; + } + + public Object getKey() { + return backingProperty.getKey(); + } + + public Property getValue() { + return backingProperty; + } + + public Property setValue(Property value) { + throw unmodifiableException(); + } + } + + private static UnsupportedOperationException unmodifiableException() { + throw new UnsupportedOperationException("unmodifiable"); + } + + public PropertyMap putCopy(Property value) { + assert !this.containsValue(value); + return new PropertyMap(this, value); + } + + public PropertyMap removeCopy(Property value) { + LinkedList<Property> shelve = new LinkedList<>(); + PropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().equals(value)) { + PropertyMap newMap = current.getParentMap(); + for (Property property : shelve) { + newMap = newMap.putCopy(property); + } + return newMap; + } else { + shelve.push(current.getLastProperty()); + current = current.getParentMap(); + } + } + return this; + } + + public PropertyMap replaceCopy(Property oldValue, Property newValue) { + LinkedList<Property> shelve = new LinkedList<>(); + PropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().equals(oldValue)) { + PropertyMap newMap = current.getParentMap(); + newMap = newMap.putCopy(newValue); + for (Property property : shelve) { + newMap = newMap.putCopy(property); + } + return newMap; + } else { + shelve.push(current.getLastProperty()); + current = current.getParentMap(); + } + } + return this; + } + + public PropertyMap getOwningMap(Property value) { + PropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().equals(value)) { + return current; + } + current = current.getParentMap(); + } + return null; + } + + PropertyMap getParentMap() { + return car; + } + + public Property getLastProperty() { + return cdr; + } +}