PageRenderTime 20ms CodeModel.GetById 12ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/at2dist220411/src/edu/vub/at/objects/natives/FieldMap.java

http://ambienttalk.googlecode.com/
Java | 196 lines | 79 code | 21 blank | 96 comment | 15 complexity | c052940bf686f1b057167b540c2bbeec MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * FieldMap.java created on 7-aug-2006 at 19:42:44
  4 * (c) Programming Technology Lab, 2006 - 2007
  5 * Authors: Tom Van Cutsem & Stijn Mostinckx
  6 * 
  7 * Permission is hereby granted, free of charge, to any person
  8 * obtaining a copy of this software and associated documentation
  9 * files (the "Software"), to deal in the Software without
 10 * restriction, including without limitation the rights to use,
 11 * copy, modify, merge, publish, distribute, sublicense, and/or
 12 * sell copies of the Software, and to permit persons to whom the
 13 * Software is furnished to do so, subject to the following
 14 * conditions:
 15 *
 16 * The above copyright notice and this permission notice shall be
 17 * included in all copies or substantial portions of the Software.
 18 *
 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 26 * OTHER DEALINGS IN THE SOFTWARE.
 27 */
 28package edu.vub.at.objects.natives;
 29
 30import edu.vub.at.objects.grammar.ATSymbol;
 31
 32import java.io.Serializable;
 33
 34/**
 35 * Instances of this class implement a so-called 'map' for an AmbientTalk object's fields.
 36 * The terminology stems from the language Self. A 'map' maps variable names to an integer index.
 37 * This index can be used to index an object's state vector to retrieve the value of a slot.
 38 * 
 39 * The advantage of maps lies in their space effiency: clones can share maps, thereby enabling
 40 * the sharing of variable names (which are immutable).
 41 * 
 42 * We implement a custom map from symbols to Java ints ourselves, because the java.util.HashMap
 43 * requires explicit boxing and unboxing of integers as java.lang.Integers, which is wasteful.
 44 * 
 45 * @author tvc
 46 */
 47public final class FieldMap implements Serializable {
 48
 49	private static final int _DEFAULT_SIZE_ = 5;
 50	
 51	/*
 52	 * Field maps are represented as a simple array of the field's names.
 53	 * The indices of the fields are literally the indices of the field's names.
 54	 */
 55	
 56	private ATSymbol[] varNames_;
 57	
 58	// next free position in the varNames_ array
 59	private int free_;
 60	
 61	/*
 62	 * Set when a fieldmap is extended when it was already shared to be able to 
 63	 * track that both objects have a common heritage.
 64	 */
 65	private FieldMap origin_ = null;
 66	
 67	public FieldMap() {
 68		varNames_ = new ATSymbol[_DEFAULT_SIZE_];
 69		free_ = 0;
 70	}
 71	
 72	// used for internal cloning purposes only
 73	private FieldMap(ATSymbol[] copiedNames, int copiedFree, FieldMap origin) {
 74		varNames_ = copiedNames;
 75		free_ = copiedFree;
 76		origin_ = origin;
 77	}
 78	
 79	/**
 80	 * Add a new field to the field map. The field will be assigned
 81	 * the index of the map's current size.
 82	 * 
 83	 * If the field already exists, it will not be added twice.
 84	 * 
 85	 * @return true if the field was added successfully, false if the field already existed
 86	 */
 87	public boolean put(ATSymbol nam) {
 88		if (findName(nam) != -1) // if the name is found...
 89			return false;
 90		
 91		if(free_ == varNames_.length) {
 92			reAlloc();
 93		}
 94		varNames_[free_++] = nam; // increment free pointer after access
 95		return true;
 96	}
 97	
 98	/**
 99	 * Retrieve the index of a field given its name.
100	 * @param nam the name of the field
101	 * @return the index of the field or -1 if the field cannot be found.
102	 */
103	public int get(ATSymbol nam) {		
104		int namIdx = findName(nam);
105		return (namIdx >= 0) ? namIdx : -1;
106	}
107	
108	/**
109	 * Remove the given name from the field map.
110	 * @param nam the name of the field to be removed
111	 * @return the index of the removed field or -1 if the field cannot be found.
112	 */
113	public int remove(ATSymbol nam) {		
114		int namIdx = findName(nam);
115		if (namIdx >= 0) {
116			for (int i = namIdx; i < free_ - 1; i++) {
117				varNames_[i] = varNames_[i+1];
118			}
119			free_--;
120		}
121		return namIdx;
122	}
123	
124	/**
125	 * Returns all field names.
126	 * @return an array of the field names stored in the map.
127	 */
128	public ATSymbol[] listFields() {
129		ATSymbol[] varnames = new ATSymbol[free_];
130		for (int i = 0; i < varnames.length; i++) {
131			varnames[i] = varNames_[i];
132		}
133		return varnames;
134	}
135	
136	/**
137	 * Creates a shallow copy of the field map. This operation is performed when a
138	 * new field is added in one object which shares its field map with others. To
139	 * allow tracking the origins of the new fieldMap, we need to store this as its
140	 * progenitor.
141	 */
142	FieldMap copy() {
143		// allocate a copy of the names array
144		ATSymbol[] newVarNames = new ATSymbol[varNames_.length];
145		// copy content into new array
146		System.arraycopy(varNames_, 0, newVarNames, 0, varNames_.length);
147		return new FieldMap(newVarNames, free_, this);
148	}
149	
150	/**
151	 * Checks whether both FieldMaps are equal or whether the passed object is a
152	 * FieldMap from which this one (indirectly) originates. 
153	 */
154	public boolean isDerivedFrom(FieldMap aFieldMap) {
155		return (this == aFieldMap) ||
156			((origin_ != null) && origin_.isDerivedFrom(aFieldMap));
157	}
158	
159	/**
160	 * Doubles the size of the map to make room for extra fields.
161	 */
162	private void reAlloc() {
163		// allocate the new array
164		ATSymbol[] newVarNames = new ATSymbol[free_ * 2];
165		// copy old content into new array
166		System.arraycopy(varNames_, 0, newVarNames, 0, free_);
167		// throw away the old array and replace it by the new one
168		varNames_ = newVarNames;
169	}
170	
171	/**
172	 * Searches for the name of a field in the varNames_ array.
173	 * Performs a simple sequential search, which is usually not a bottleneck
174	 * as maps are supposed to be rather small (< 50 elements).
175	 * @return the index of the field or -1 if not found.
176	 */
177	private int findName(ATSymbol nam) {
178		for (int i = 0; i < free_; i++) {
179			if (varNames_[i] == nam)
180				return i;
181		}
182		return -1;
183	}
184	
185	public String toString() {
186		StringBuffer buff = new StringBuffer("FieldMap{");
187		if (free_ > 0) {
188			buff.append(varNames_[0].toString()+":0");
189			for (int i = 1; i < free_; i++) {
190				buff.append(",").append(varNames_[i].toString()+":"+i);
191			}
192		}
193		return buff.append("}").toString();
194	}
195
196}