/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. */
  28. package edu.vub.at.objects.natives;
  29. import edu.vub.at.objects.grammar.ATSymbol;
  30. import java.io.Serializable;
  31. /**
  32. * Instances of this class implement a so-called 'map' for an AmbientTalk object's fields.
  33. * The terminology stems from the language Self. A 'map' maps variable names to an integer index.
  34. * This index can be used to index an object's state vector to retrieve the value of a slot.
  35. *
  36. * The advantage of maps lies in their space effiency: clones can share maps, thereby enabling
  37. * the sharing of variable names (which are immutable).
  38. *
  39. * We implement a custom map from symbols to Java ints ourselves, because the java.util.HashMap
  40. * requires explicit boxing and unboxing of integers as java.lang.Integers, which is wasteful.
  41. *
  42. * @author tvc
  43. */
  44. public final class FieldMap implements Serializable {
  45. private static final int _DEFAULT_SIZE_ = 5;
  46. /*
  47. * Field maps are represented as a simple array of the field's names.
  48. * The indices of the fields are literally the indices of the field's names.
  49. */
  50. private ATSymbol[] varNames_;
  51. // next free position in the varNames_ array
  52. private int free_;
  53. /*
  54. * Set when a fieldmap is extended when it was already shared to be able to
  55. * track that both objects have a common heritage.
  56. */
  57. private FieldMap origin_ = null;
  58. public FieldMap() {
  59. varNames_ = new ATSymbol[_DEFAULT_SIZE_];
  60. free_ = 0;
  61. }
  62. // used for internal cloning purposes only
  63. private FieldMap(ATSymbol[] copiedNames, int copiedFree, FieldMap origin) {
  64. varNames_ = copiedNames;
  65. free_ = copiedFree;
  66. origin_ = origin;
  67. }
  68. /**
  69. * Add a new field to the field map. The field will be assigned
  70. * the index of the map's current size.
  71. *
  72. * If the field already exists, it will not be added twice.
  73. *
  74. * @return true if the field was added successfully, false if the field already existed
  75. */
  76. public boolean put(ATSymbol nam) {
  77. if (findName(nam) != -1) // if the name is found...
  78. return false;
  79. if(free_ == varNames_.length) {
  80. reAlloc();
  81. }
  82. varNames_[free_++] = nam; // increment free pointer after access
  83. return true;
  84. }
  85. /**
  86. * Retrieve the index of a field given its name.
  87. * @param nam the name of the field
  88. * @return the index of the field or -1 if the field cannot be found.
  89. */
  90. public int get(ATSymbol nam) {
  91. int namIdx = findName(nam);
  92. return (namIdx >= 0) ? namIdx : -1;
  93. }
  94. /**
  95. * Remove the given name from the field map.
  96. * @param nam the name of the field to be removed
  97. * @return the index of the removed field or -1 if the field cannot be found.
  98. */
  99. public int remove(ATSymbol nam) {
  100. int namIdx = findName(nam);
  101. if (namIdx >= 0) {
  102. for (int i = namIdx; i < free_ - 1; i++) {
  103. varNames_[i] = varNames_[i+1];
  104. }
  105. free_--;
  106. }
  107. return namIdx;
  108. }
  109. /**
  110. * Returns all field names.
  111. * @return an array of the field names stored in the map.
  112. */
  113. public ATSymbol[] listFields() {
  114. ATSymbol[] varnames = new ATSymbol[free_];
  115. for (int i = 0; i < varnames.length; i++) {
  116. varnames[i] = varNames_[i];
  117. }
  118. return varnames;
  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. * Checks whether both FieldMaps are equal or whether the passed object is a
  135. * FieldMap from which this one (indirectly) originates.
  136. */
  137. public boolean isDerivedFrom(FieldMap aFieldMap) {
  138. return (this == aFieldMap) ||
  139. ((origin_ != null) && origin_.isDerivedFrom(aFieldMap));
  140. }
  141. /**
  142. * Doubles the size of the map to make room for extra fields.
  143. */
  144. private void reAlloc() {
  145. // allocate the new array
  146. ATSymbol[] newVarNames = new ATSymbol[free_ * 2];
  147. // copy old content into new array
  148. System.arraycopy(varNames_, 0, newVarNames, 0, free_);
  149. // throw away the old array and replace it by the new one
  150. varNames_ = newVarNames;
  151. }
  152. /**
  153. * Searches for the name of a field in the varNames_ array.
  154. * Performs a simple sequential search, which is usually not a bottleneck
  155. * as maps are supposed to be rather small (< 50 elements).
  156. * @return the index of the field or -1 if not found.
  157. */
  158. private int findName(ATSymbol nam) {
  159. for (int i = 0; i < free_; i++) {
  160. if (varNames_[i] == nam)
  161. return i;
  162. }
  163. return -1;
  164. }
  165. public String toString() {
  166. StringBuffer buff = new StringBuffer("FieldMap{");
  167. if (free_ > 0) {
  168. buff.append(varNames_[0].toString()+":0");
  169. for (int i = 1; i < free_; i++) {
  170. buff.append(",").append(varNames_[i].toString()+":"+i);
  171. }
  172. }
  173. return buff.append("}").toString();
  174. }
  175. }