    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    }