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