PageRenderTime 41ms CodeModel.GetById 15ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

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

http://ambienttalk.googlecode.com/
Java | 169 lines | 59 code | 19 blank | 91 comment | 11 complexity | 544d434592ee43ab79e0e1f66f4bc166 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	 * Returns all field names.
110	 * @return an array of the field names stored in the map.
111	 */
112	public ATSymbol[] listFields() {
113		ATSymbol[] varnames = new ATSymbol[free_];
114		for (int i = 0; i < varnames.length; i++) {
115			varnames[i] = varNames_[i];
116		}
117		return varnames;
118	}
119	
120	/**
121	 * Creates a shallow copy of the field map. This operation is performed when a
122	 * new field is added in one object which shares its field map with others. To
123	 * allow tracking the origins of the new fieldMap, we need to store this as its
124	 * progenitor.
125	 */
126	FieldMap copy() {
127		// allocate a copy of the names array
128		ATSymbol[] newVarNames = new ATSymbol[varNames_.length];
129		// copy content into new array
130		System.arraycopy(varNames_, 0, newVarNames, 0, varNames_.length);
131		return new FieldMap(newVarNames, free_, this);
132	}
133	
134	/**
135	 * Checks whether both FieldMaps are equal or whether the passed object is a
136	 * FieldMap from which this one (indirectly) originates. 
137	 */
138	public boolean isDerivedFrom(FieldMap aFieldMap) {
139		return (this == aFieldMap) ||
140			((origin_ != null) && origin_.isDerivedFrom(aFieldMap));
141	}
142	
143	/**
144	 * Doubles the size of the map to make room for extra fields.
145	 */
146	private void reAlloc() {
147		// allocate the new array
148		ATSymbol[] newVarNames = new ATSymbol[free_ * 2];
149		// copy old content into new array
150		System.arraycopy(varNames_, 0, newVarNames, 0, free_);
151		// throw away the old array and replace it by the new one
152		varNames_ = newVarNames;
153	}
154	
155	/**
156	 * Searches for the name of a field in the varNames_ array.
157	 * Performs a simple sequential search, which is usually not a bottleneck
158	 * as maps are supposed to be rather small (< 50 elements).
159	 * @return the index of the field or -1 if not found.
160	 */
161	private int findName(ATSymbol nam) {
162		for (int i = 0; i < free_; i++) {
163			if (varNames_[i] == nam)
164				return i;
165		}
166		return -1;
167	}
168
169}