001    /* This file was generated with JastAdd2 (http://jastadd.org) version 2.1.3 */
002    package AST;
003    
004    import java.util.Collection;
005    import java.util.ArrayList;
006    import java.util.HashSet;
007    /**
008     * @ast node
009     * @production ASTNode;
010    
011     */
012    public class ASTNode<T extends ASTNode> implements Cloneable, Iterable<T> {
013      /**
014       * @apilevel internal
015       */
016      public ASTNode<T> clone() throws CloneNotSupportedException {
017        ASTNode node = (ASTNode) super.clone();
018        node.in$Circle(false);
019        node.is$Final(false);
020        return node;
021      }
022      /**
023       * @apilevel internal
024       */
025      public ASTNode<T> copy() {
026        try {
027          ASTNode node = (ASTNode) clone();
028          node.parent = null;
029          if(children != null) {
030            node.children = (ASTNode[]) children.clone();
031          }
032          return node;
033        } catch (CloneNotSupportedException e) {
034          throw new Error("Error: clone not supported for " + getClass().getName());
035        }
036      }
037      /**
038       * Create a deep copy of the AST subtree at this node.
039       * The copy is dangling, i.e. has no parent.
040       * @return dangling copy of the subtree at this node
041       * @apilevel low-level
042       */
043      public ASTNode<T> fullCopy() {
044        ASTNode tree = (ASTNode) copy();
045        if (children != null) {
046          for (int i = 0; i < children.length; ++i) {
047            ASTNode child = (ASTNode) children[i];
048            if(child != null) {
049              child = child.fullCopy();
050              tree.setChild(child, i);
051            }
052          }
053        }
054        return tree;
055      }
056      /**
057       * @aspect ErrorCheck
058       * @declaredat /home/csz-naf/examples/PicoJava/spec/ErrorCheck.jadd:12
059       */
060      public void collectErrors(Collection c) {
061        for(int i = 0; i < getNumChild(); i++)
062          getChild(i).collectErrors(c);
063      }
064      /**
065       * @aspect ErrorCheck
066       * @declaredat /home/csz-naf/examples/PicoJava/spec/ErrorCheck.jadd:18
067       */
068      protected void error(Collection c, String s) {
069        //c.add(getLine(getStart()) + ": " + s);
070        c.add(s);
071      }
072      /** 
073       * Print AST
074       * @aspect PrettyPrint
075       * @declaredat /home/csz-naf/examples/PicoJava/spec/PrettyPrint.jadd:5
076       */
077      public String printAST() {
078                StringBuilder sb = new StringBuilder();
079                printAST(sb);
080                return sb.toString();
081        }
082      /**
083       * @aspect PrettyPrint
084       * @declaredat /home/csz-naf/examples/PicoJava/spec/PrettyPrint.jadd:10
085       */
086      public void printAST(StringBuilder sb) {
087                printAST(sb, 0);
088        }
089      /**
090       * @aspect PrettyPrint
091       * @declaredat /home/csz-naf/examples/PicoJava/spec/PrettyPrint.jadd:13
092       */
093      public void printAST(StringBuilder sb, int t) {
094                for (int j = 0; j < t; j++) {
095                        sb.append((j%2==0) ? " |" : " !");
096                }
097                sb.append(getClass().getName() + "\n");
098                for (int i = 0; i < getNumChild(); i++) {
099                        getChild(i).printAST(sb, t+1);
100               }
101       }
102      /**
103       * @aspect PrettyPrint
104       * @declaredat /home/csz-naf/examples/PicoJava/spec/PrettyPrint.jadd:78
105       */
106      public String getIndent(int t) {
107               String s = "";
108               for (int i = 0; i < t; i++) {
109                       s += "\t";
110               }
111               return s;
112       }
113      /**
114       */
115      public ASTNode() {
116        super();
117        init$Children();
118      }
119      /**
120       * Initializes the child array to the correct size.
121       * Initializes List and Opt nta children.
122       * @apilevel internal
123       * @ast method
124       */
125      public void init$Children() {
126      }
127      /**
128       * @apilevel internal
129       */
130      private int childIndex;
131      /**
132       * @apilevel low-level
133       */
134      public int getIndexOfChild(ASTNode node) {
135        if (node == null) {
136          return -1;
137        }
138        if (node.childIndex < numChildren && node == children[node.childIndex]) {
139          return node.childIndex;
140        }
141        for(int i = 0; children != null && i < children.length; i++) {
142          if(children[i] == node) {
143            node.childIndex = i;
144            return i;
145          }
146        }
147        return -1;
148      }
149      /**
150       * @apilevel internal
151       */
152      public static final boolean generatedWithCircularEnabled = true;
153      /**
154       * @apilevel internal
155       */
156      public static final boolean generatedWithCacheCycle = true;
157      /**
158       * @apilevel internal
159       */
160      public static final boolean generatedWithComponentCheck = false;
161      /**
162       * Parent pointer
163       * @apilevel low-level
164       */
165      protected ASTNode parent;
166      /**
167       * Child array
168       * @apilevel low-level
169       */
170      protected ASTNode[] children;
171      /**
172       * @apilevel internal
173       */
174      protected static ASTNode$State state = new ASTNode$State();
175      /**
176       * @apilevel internal
177       */
178      public final ASTNode$State state() {
179        return state;
180      }
181      /**
182       * @apilevel internal
183       */
184      public boolean in$Circle = false;
185      /**
186       * @apilevel internal
187       */
188      public boolean in$Circle() {
189        return in$Circle;
190      }
191      /**
192       * @apilevel internal
193       */
194      public void in$Circle(boolean b) {
195        in$Circle = b;
196      }
197      /**
198       * @apilevel internal
199       */
200      public boolean is$Final = false;
201      /**
202       * @apilevel internal
203       */
204      public boolean is$Final() { return is$Final; }
205      /**
206       * @apilevel internal
207       */
208      public void is$Final(boolean b) { is$Final = b; }
209      /**
210       * @apilevel low-level
211       */
212      public T getChild(int i) {
213    
214        ASTNode node = this.getChildNoTransform(i);
215        if(node == null) {
216          return null;
217        }
218        if(node.is$Final()) {
219          return (T) node;
220        }
221        if(!node.mayHaveRewrite()) {
222          node.is$Final(this.is$Final());
223          return (T) node;
224        }
225        if(!node.in$Circle()) {
226          int rewriteState;
227          int num = this.state().boundariesCrossed;
228          do {
229            this.state().push(ASTNode$State.REWRITE_CHANGE);
230            ASTNode oldNode = node;
231            oldNode.in$Circle(true);
232            node = node.rewriteTo();
233            if(node != oldNode) {
234              this.setChild(node, i);
235            }
236            oldNode.in$Circle(false);
237            rewriteState = this.state().pop();
238          } while(rewriteState == ASTNode$State.REWRITE_CHANGE);
239          if(rewriteState == ASTNode$State.REWRITE_NOCHANGE && this.is$Final()) {
240            node.is$Final(true);
241            this.state().boundariesCrossed = num;
242          } else {
243          }
244        } else if(this.is$Final() != node.is$Final()) {
245          this.state().boundariesCrossed++;
246        } else {
247        }
248        return (T) node;
249    
250    
251      }
252      /**
253       * @apilevel low-level
254       */
255      public void addChild(T node) {
256        setChild(node, getNumChildNoTransform());
257      }
258      /**
259       * <p><em>This method does not invoke AST transformations.</em></p>
260       * @apilevel low-level
261       */
262      public final T getChildNoTransform(int i) {
263        if (children == null) {
264          return null;
265        }
266        T child = (T)children[i];
267        return child;
268      }
269      /**
270       * @apilevel low-level
271       */
272      protected int numChildren;
273      /**
274       * @apilevel low-level
275       */
276      protected int numChildren() {
277        return numChildren;
278      }
279      /**
280       * @apilevel low-level
281       */
282      public int getNumChild() {
283        return numChildren();
284      }
285      /**
286       * <p><em>This method does not invoke AST transformations.</em></p>
287       * @apilevel low-level
288       */
289      public final int getNumChildNoTransform() {
290        return numChildren();
291      }
292      /**
293       * @apilevel low-level
294       */
295      public void setChild(ASTNode node, int i) {
296        if(children == null) {
297          children = new ASTNode[(i+1>4 || !(this instanceof List))?i+1:4];
298        } else if (i >= children.length) {
299          ASTNode c[] = new ASTNode[i << 1];
300          System.arraycopy(children, 0, c, 0, children.length);
301          children = c;
302        }
303        children[i] = node;
304        if(i >= numChildren) {
305          numChildren = i+1;
306        }
307        if(node != null) {
308          node.setParent(this);
309          node.childIndex = i;
310        }
311      }
312      /**
313       * @apilevel low-level
314       */
315      public void insertChild(ASTNode node, int i) {
316        if(children == null) {
317          children = new ASTNode[(i+1>4 || !(this instanceof List))?i+1:4];
318          children[i] = node;
319        } else {
320          ASTNode c[] = new ASTNode[children.length + 1];
321          System.arraycopy(children, 0, c, 0, i);
322          c[i] = node;
323          if(i < children.length) {
324            System.arraycopy(children, i, c, i+1, children.length-i);
325            for(int j = i+1; j < c.length; ++j) {
326              if(c[j] != null) {
327                c[j].childIndex = j;
328              }
329            }
330          }
331          children = c;
332        }
333        numChildren++;
334        if(node != null) {
335          node.setParent(this);
336          node.childIndex = i;
337        }
338      }
339      /**
340       * @apilevel low-level
341       */
342      public void removeChild(int i) {
343        if(children != null) {
344          ASTNode child = (ASTNode) children[i];
345          if(child != null) {
346            child.parent = null;
347            child.childIndex = -1;
348          }
349          // Adding a check of this instance to make sure its a List, a move of children doesn't make
350          // any sense for a node unless its a list. Also, there is a problem if a child of a non-List node is removed
351          // and siblings are moved one step to the right, with null at the end.
352          if (this instanceof List || this instanceof Opt) {
353            System.arraycopy(children, i+1, children, i, children.length-i-1);
354            children[children.length-1] = null;
355            numChildren--;
356            // fix child indices
357            for(int j = i; j < numChildren; ++j) {
358              if(children[j] != null) {
359                child = (ASTNode) children[j];
360                child.childIndex = j;
361              }
362            }
363          } else {
364            children[i] = null;
365          }
366        }
367      }
368      /**
369       * @apilevel low-level
370       */
371      public ASTNode getParent() {
372        if(parent != null && ((ASTNode) parent).is$Final() != is$Final()) {
373          state().boundariesCrossed++;
374        }
375        ;
376        return (ASTNode) parent;
377      }
378      /**
379       * @apilevel low-level
380       */
381      public void setParent(ASTNode node) {
382        parent = node;
383      }
384      /**
385       * Line and column information.
386       */
387      protected int startLine;
388      /**
389       */
390      protected short startColumn;
391      /**
392       */
393      protected int endLine;
394      /**
395       */
396      protected short endColumn;
397      /**
398       */
399      public int getStartLine() {
400        return startLine;
401      }
402      /**
403       */
404      public short getStartColumn() {
405        return startColumn;
406      }
407      /**
408       */
409      public int getEndLine() {
410        return endLine;
411      }
412      /**
413       */
414      public short getEndColumn() {
415        return endColumn;
416      }
417      /**
418       */
419      public void setStart(int startLine, short startColumn) {
420        this.startLine = startLine;
421        this.startColumn = startColumn;
422      }
423      /**
424       */
425      public void setEnd(int endLine, short endColumn) {
426        this.endLine = endLine;
427        this.endColumn = endColumn;
428      }
429      /**
430       */
431      protected boolean duringTypeAnalysis() {
432      if(state().duringTypeAnalysis == 0) {
433        return false;
434      } else {
435        state().pop();
436        state().push(ASTNode$State.REWRITE_INTERRUPT);
437        return true;
438      }
439    }
440      /**
441       * @apilevel low-level
442       */
443      public java.util.Iterator<T> iterator() {
444        return new java.util.Iterator<T>() {
445          private int counter = 0;
446          public boolean hasNext() {
447            return counter < getNumChild();
448          }
449          public T next() {
450            if(hasNext())
451              return (T)getChild(counter++);
452            else
453              return null;
454          }
455          public void remove() {
456            throw new UnsupportedOperationException();
457          }
458        };
459      }
460      /**
461       * @apilevel internal
462       */
463      public boolean mayHaveRewrite() {
464        return false;
465      }
466      /**
467       * @apilevel low-level
468       */
469      public void flushCache() {
470      }
471      /**
472       * @apilevel internal
473       */
474      public void flushCollectionCache() {
475      }
476      /**
477       * @apilevel internal
478       */
479      public ASTNode rewriteTo() {    if(state().peek() == ASTNode$State.REWRITE_CHANGE) {
480          state().pop();
481          state().push(ASTNode$State.REWRITE_NOCHANGE);
482        }
483        return this;
484      }  /**
485       * @apilevel internal
486       */
487      public boolean Define_boolean_isQualified(ASTNode caller, ASTNode child) {
488        return getParent().Define_boolean_isQualified(this, caller);
489      }
490      /**
491       * @apilevel internal
492       */
493      public Access Define_Access_qualifier(ASTNode caller, ASTNode child) {
494        return getParent().Define_Access_qualifier(this, caller);
495      }
496      /**
497       * @apilevel internal
498       */
499      public Decl Define_Decl_lookup(ASTNode caller, ASTNode child, String name) {
500        return getParent().Define_Decl_lookup(this, caller, name);
501      }
502      /**
503       * @apilevel internal
504       */
505      public Decl Define_Decl_unknownDecl(ASTNode caller, ASTNode child) {
506        return getParent().Define_Decl_unknownDecl(this, caller);
507      }
508      /**
509       * @apilevel internal
510       */
511      public PrimitiveDecl Define_PrimitiveDecl_booleanType(ASTNode caller, ASTNode child) {
512        return getParent().Define_PrimitiveDecl_booleanType(this, caller);
513      }
514    }