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    }