001 // -*- mode: java -*-
002 /* Copyright 2000, 2001, Compaq Computer Corporation */
003
004 /* IF THIS IS A JAVA FILE, DO NOT EDIT IT!
005
006 Most Java files in this directory which are part of the Javafe AST
007 are automatically generated using the astgen comment (see
008 ESCTools/Javafe/astgen) from the input file 'hierarchy.h'. If you
009 wish to modify AST classes or introduce new ones, modify
010 'hierarchy.j.'
011 */
012
013 package javafe.ast;
014
015 import javafe.util.Assert;
016 import javafe.util.Location;
017 import javafe.util.ErrorSet;
018
019 // Convention: unless otherwise noted, integer fields named "loc" refer
020 // to the location of the first character of the syntactic unit
021
022
023 public class CompoundName extends Name
024 {
025 //@ invariant length>1;
026
027 //@ invariant ids != null;
028 //@ invariant ids.count == length;
029 public /*@ non_null @*/ IdentifierVec ids;
030
031
032 //@ invariant locIds.length == length;
033 /*@ invariant (\forall int i; (0 <= i && i<locIds.length)
034 ==> locIds[i] != Location.NULL); */
035 public /*@ non_null @*/ int[] locIds;
036
037
038 //@ invariant locDots.length == length-1;
039 /*@ invariant (\forall int i; (0 <= i && i<locDots.length)
040 ==> locDots[i] != Location.NULL); */
041 public /*@ non_null @*/ int[] locDots;
042
043
044 /** Ensure there's at least two identifiers in this name. */
045 private void postMake() {
046 Assert.notFalse(locIds.length > 1);
047 }
048
049 /** Check invariants on sizes. */
050 private void postCheck() {
051 Assert.notFalse(ids.size() == locIds.length);
052 Assert.notFalse(locIds.length > 1);
053 Assert.notFalse(locIds.length == locDots.length+1);
054 }
055
056 /**
057 * @return a String representation of <code>this</code> in Java's
058 * syntax.
059 */
060 public /*@non_null*/ String printName() {
061 int sz = ids.size();
062 StringBuffer result = new StringBuffer(10*sz);
063 for(int i = 0; i < sz; i++) {
064 if (i != 0) result.append('.');
065 result.append(ids.elementAt(i).toString());
066 }
067 return result.toString();
068 }
069
070 /** Return true if <code>other</code> is a <code>Name</code> that
071 is component-wise equal to <code>this</code>. */
072
073 public boolean equals(Object other) {
074 if (other instanceof CompoundName) {
075 Name o = (CompoundName)other;
076 int sz = this.ids.size();
077 if (sz != o.size()) return false;
078 for(int i = 0; i < sz; i++) {
079 if (this.ids.elementAt(i) != o.identifierAt(i)) return false;
080 }
081 return true;
082 } else
083 return false;
084 }
085
086 /** Return a <code>Name</code> consisting of the first
087 <code>len</code> identifiers of <code>this</code>. Requires that
088 <code>len</code> is greater than zero and less than the length of
089 <code>this</code>. */
090
091 public /*@non_null*/ Name prefix(int len) {
092 Assert.precondition(len > 0 && len <= ids.size());
093 if (len == 1)
094 return SimpleName.make(ids.elementAt(0), locIds[0]);
095
096 Identifier[] newIds = new Identifier[len];
097 int[] newLocIds = new int[len];
098 int[] newLocDots = new int[len-1];
099 for(int i = 0; i < len; i++) newIds[i] = this.ids.elementAt(i);
100 System.arraycopy(locIds, 0, newLocIds, 0, len);
101 System.arraycopy(locDots, 0, newLocDots, 0, len-1);
102 return make(IdentifierVec.make(newIds), newLocIds, newLocDots);
103 }
104
105 /** Return a hash code for <code>this</code> such that two
106 <code>Name</code>s that are <code>equals</code> have the same hash
107 code. */
108
109 public int hashCode() {
110 int result = 0;
111 for(int i = 0, sz = ids.size(); i < sz; i++)
112 result += ids.elementAt(i).hashCode();
113 return result;
114 }
115
116 /**
117 * @return the first <code>len</code> identifiers in
118 * <code>this</code> in an array. Requires that <code>len</code> be
119 * between 0 and length of <code>this</code> inclusive.
120 */
121 public String[] toStrings(int len) {
122 Assert.precondition(0 <= len && len <= ids.size());
123 if (len == 0) return emptyStringArray;
124 String[] result = new String[len];
125 for(int i = 0; i < len; i++)
126 result[i] = ids.elementAt(i).toString();
127 return result;
128 }
129
130 /** Return the number of identifiers in <code>this</code>. */
131 public int size() { return ids.size(); }
132
133 /** Return the ith identifier of <code>this</code>. */
134 public /*@non_null*/ Identifier identifierAt(int i)
135 /*throws ArrayIndexOutOfBoundsException*/ {
136 return ids.elementAt(i);
137 }
138
139 /** Return the location of the ith identifier of <code>this</code>. */
140 public int locIdAt(int i) { return locIds[i]; }
141
142 /** Return the location of the dot after the ith identifier of
143 <code>this</code>. */
144 public int locDotAfter(int i) { return locDots[i]; }
145
146 //@ public represents startLoc <- locIds[0];
147 public /*@ pure @*/ int getStartLoc() { return locIds[0]; }
148
149 //@ requires ids.count>1;
150 //@ requires locIds.length == ids.count;
151 /*@ requires (\forall int i; (0 <= i && i<locIds.length)
152 ==> locIds[i] != Location.NULL); */
153 //@ requires locDots.length == ids.count-1;
154 /*@ requires (\forall int i; (0 <= i && i<locDots.length)
155 ==> locDots[i] != Location.NULL); */
156 //
157 public static /*@non_null*/ CompoundName make(/*@ non_null @*/ IdentifierVec ids,
158 /*@ non_null @*/ int[] locIds,
159 /*@ non_null @*/ int[] locDots) {
160 CompoundName result = new CompoundName(ids, locIds, locDots);
161
162 //@ set result.length = ids.count;
163 result.postMake();
164 return result;
165 }
166
167
168 // Generated boilerplate constructors:
169
170 //@ ensures this.ids == ids;
171 //@ ensures this.locIds == locIds;
172 //@ ensures this.locDots == locDots;
173 protected CompoundName(/*@ non_null @*/ IdentifierVec ids, /*@ non_null @*/ int[] locIds, /*@ non_null @*/ int[] locDots) {
174 super();
175 this.ids = ids;
176 this.locIds = locIds;
177 this.locDots = locDots;
178 }
179
180 // Generated boilerplate methods:
181
182 public final int childCount() {
183 int sz = 0;
184 if (this.ids != null) sz += this.ids.size();
185 return sz + 2;
186 }
187
188 public final Object childAt(int index) {
189 /*throws IndexOutOfBoundsException*/
190 if (index < 0)
191 throw new IndexOutOfBoundsException("AST child index " + index);
192 int indexPre = index;
193
194 int sz;
195
196 sz = (this.ids == null ? 0 : this.ids.size());
197 if (0 <= index && index < sz)
198 return this.ids.elementAt(index);
199 else index -= sz;
200
201 if (index == 0) return this.locIds;
202 else index--;
203
204 if (index == 0) return this.locDots;
205 else index--;
206
207 throw new IndexOutOfBoundsException("AST child index " + indexPre);
208 } //@ nowarn Exception;
209
210 public final /*@non_null*/String toString() {
211 return "[CompoundName"
212 + " ids = " + this.ids
213 + " locIds = " + this.locIds
214 + " locDots = " + this.locDots
215 + "]";
216 }
217
218 public final int getTag() {
219 return TagConstants.COMPOUNDNAME;
220 }
221
222 public final void accept(Visitor v) { v.visitCompoundName(this); }
223
224 public final Object accept(VisitorArgResult v, Object o) {return v.visitCompoundName(this, o); }
225
226 public void check() {
227 super.check();
228 if (this.ids == null) throw new RuntimeException();
229 if (this.locIds == null) throw new RuntimeException();
230 if (this.locDots == null) throw new RuntimeException();
231 postCheck();
232 }
233
234 }