package common.interpreters;
import java.util.Enumeration;
import java.util.LinkedList;
import common.AbstractEnvironment;
import expressions.Expression;
import expressions.Location;
/**
* Mutable implementation of the <code>Store</code> interface, used
* for the big and small step interpreters.
*
* @author Benedikt Meurer
* @version $Id: MutableStore.java 168 2006-06-15 13:41:38Z benny $
*/
public final class MutableStore extends AbstractEnvironment<Location, Expression> implements Store {
//
// Constructor
//
/**
* Allocates a new store, based on the items from the specified <code>store</code>.
*
* @param store the {@link Store}, whose items should be copied.
*
* @throws ClassCastException if <code>store</code> is not a {@link MutableStore}.
* @throws NullPointerException if <code>store</code> is <code>null</code>.
*/
public MutableStore(Store store) {
this((MutableStore)store);
}
/**
* Allocates a new store, based on the items from the specified <code>store</code>.
*
* @param store the {@link MutableStore}, whose mappings should be copied.
*
* @throws NullPointerException if <code>store</code> is <code>null</code>.
*/
public MutableStore(MutableStore store) {
super(store);
}
//
// Constructor (packaged)
//
/**
* Allocates a new empty default store.
*/
MutableStore() {
super();
}
//
// Store queries
//
/**
* {@inheritDoc}
*
* @see common.interpreters.Store#containsLocation(expressions.Location)
*/
public boolean containsLocation(Location location) {
return containsSymbol(location);
}
/**
* {@inheritDoc}
*
* @see common.interpreters.Store#locations()
*/
public Enumeration<Location> locations() {
return symbols();
}
//
// Store modification
//
/**
* Allocates a new {@link Location} within this store. This method is
* used to implement the <code>ref</code> operator, which requires a
* new location that has not been allocated before.
*
* @return a new {@link Location} within this store.
*
* @see #put(Location, Expression)
*/
public Location alloc() {
// try to find a new unique location
for (String suffix = "";; suffix = suffix + "'") {
for (int n = 0; n < 26; ++n) {
// generate the location base character
char c = (char)('A' + ((('X' - 'A') + n) % 26));
// try the location with this name
Location location = new Location(c + suffix);
if (!containsLocation(location)) {
return location;
}
}
}
}
/**
* Adds a new mapping for the <code>expression</code> to the <code>location</code>.
* If there's already a mapping for the <code>location</code> the previous
* mapping is deleted.
*
* @param location the {@link Location} for the <code>value</code>.
* @param expression the new {@link Expression}.
*
* @throws IllegalArgumentException if either <code>location</code> or
* <code>expression</code> is <code>null</code>.
*
* @see #alloc()
* @see #get(Location)
*/
public void put(Location location, Expression expression) {
// verify the location and expression
if (location == null) {
throw new IllegalArgumentException("location is null");
}
if (expression == null) {
throw new IllegalArgumentException("expression is null");
}
// generate the new list with the new mapping
LinkedList<Mapping<Location, Expression>> newMappings = new LinkedList<Mapping<Location, Expression>>();
newMappings.add(new Mapping<Location, Expression>(location, expression));
// add remaining entries
for (Mapping<Location, Expression> mapping : this.mappings) {
if (!location.equals(mapping.getSymbol())) {
newMappings.add(mapping);
}
}
// use the new mappings
this.mappings = newMappings;
}
}