/******************************************************************************* * Copyright (c) 2009 Centrum Wiskunde en Informatica (CWI) * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Arnold Lankamp - interfaces and implementation *******************************************************************************/ package org.rascalmpl.value.impl.fast; import java.util.Iterator; import org.rascalmpl.value.IList; import org.rascalmpl.value.IListWriter; import org.rascalmpl.value.IValue; import org.rascalmpl.value.impl.util.collections.ShareableValuesList; import org.rascalmpl.value.type.Type; import org.rascalmpl.value.type.TypeFactory; // TODO Add checking. /** * Implementation of IListWriter. * * @author Arnold Lankamp */ /*package*/ class ListWriter implements IListWriter{ protected Type elementType; protected final boolean inferred; protected final ShareableValuesList data; protected IList constructedList; /*package*/ ListWriter(Type elementType){ super(); this.elementType = elementType; this.inferred = false; data = new ShareableValuesList(); constructedList = null; } /*package*/ ListWriter(){ super(); this.elementType = TypeFactory.getInstance().voidType(); this.inferred = true; data = new ShareableValuesList(); constructedList = null; } /*package*/ ListWriter(Type elementType, ShareableValuesList data){ super(); this.elementType = elementType; this.inferred = false; this.data = data; constructedList = null; } public void append(IValue element){ checkMutation(); updateType(element); data.append(element); } private void updateType(IValue element) { if (inferred) { elementType = elementType.lub(element.getType()); } } public void append(IValue... elems){ checkMutation(); for(IValue elem : elems){ updateType(elem); } data.appendAll(elems); } public void appendAll(Iterable<? extends IValue> collection){ checkMutation(); Iterator<? extends IValue> collectionIterator = collection.iterator(); while(collectionIterator.hasNext()){ IValue next = collectionIterator.next(); updateType(next); data.append(next); } } public void insert(IValue elem){ checkMutation(); updateType(elem); data.insert(elem); } public void insert(IValue... elements){ insert(elements, 0, elements.length); } public void insert(IValue[] elements, int start, int length){ checkMutation(); checkBounds(elements, start, length); for(int i = start + length - 1; i >= start; i--){ updateType(elements[i]); data.insert(elements[i]); } } public void insertAll(Iterable<? extends IValue> collection){ checkMutation(); Iterator<? extends IValue> collectionIterator = collection.iterator(); while(collectionIterator.hasNext()){ IValue next = collectionIterator.next(); updateType(next); data.insert(next); } } public void insertAt(int index, IValue element){ checkMutation(); updateType(element); data.insertAt(index, element); } public void insertAt(int index, IValue... elements){ insertAt(index, elements, 0, 0); } public void insertAt(int index, IValue[] elements, int start, int length){ checkMutation(); checkBounds(elements, start, length); for(int i = start + length - 1; i >= start; i--){ updateType(elements[i]); data.insertAt(index, elements[i]); } } public IValue replaceAt(int index, IValue element){ checkMutation(); updateType(element); return data.set(index, element); } @Override public IValue get(int i) throws IndexOutOfBoundsException { return data.get(i); } @Override public int length() { return data.size(); } protected void checkMutation(){ if(constructedList != null) throw new UnsupportedOperationException("Mutation of a finalized list is not supported."); } private void checkBounds(IValue[] elems, int start, int length){ if(start < 0) throw new ArrayIndexOutOfBoundsException("start < 0"); if((start + length) > elems.length) throw new ArrayIndexOutOfBoundsException("(start + length) > elems.length"); } @Override public IList done() { if (constructedList == null) { constructedList = List.newList(data.isEmpty() ? TypeFactory.getInstance().voidType() : elementType, data); } return constructedList; } }