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     * @declaredat /home/csz-naf/examples/PicoJava/spec/picojava.ast:8
010     * @production ClassDecl : {@link TypeDecl} ::= <span class="component">[Superclass:{@link IdUse}]</span> <span class="component">Body:{@link Block}</span>;
011    
012     */
013    public class ClassDecl extends TypeDecl implements Cloneable {
014      /**
015       * @apilevel internal
016       */
017      public ClassDecl clone() throws CloneNotSupportedException {
018        ClassDecl node = (ClassDecl) super.clone();
019        node.remoteLookup_String_visited = null;
020        node.isSubtypeOf_TypeDecl_visited = null;
021        node.isSubtypeOf_TypeDecl_values = null;
022        node.superClass_visited = -1;
023        node.superClass_computed = false;
024        node.superClass_value = null;
025        node.hasCycleOnSuperclassChain_visited = -1;
026        node.hasCycleOnSuperclassChain_computed = false;
027        node.hasCycleOnSuperclassChain_initialized = false;
028        node.in$Circle(false);
029        node.is$Final(false);
030        return node;
031      }
032      /**
033       * @apilevel internal
034       */
035      public ClassDecl copy() {
036        try {
037          ClassDecl node = (ClassDecl) clone();
038          node.parent = null;
039          if(children != null) {
040            node.children = (ASTNode[]) children.clone();
041          }
042          return node;
043        } catch (CloneNotSupportedException e) {
044          throw new Error("Error: clone not supported for " + getClass().getName());
045        }
046      }
047      /**
048       * Create a deep copy of the AST subtree at this node.
049       * The copy is dangling, i.e. has no parent.
050       * @return dangling copy of the subtree at this node
051       * @apilevel low-level
052       */
053      public ClassDecl fullCopy() {
054        ClassDecl tree = (ClassDecl) copy();
055        if (children != null) {
056          for (int i = 0; i < children.length; ++i) {
057            ASTNode child = (ASTNode) children[i];
058            if(child != null) {
059              child = child.fullCopy();
060              tree.setChild(child, i);
061            }
062          }
063        }
064        return tree;
065      }
066      /**
067       * @aspect ErrorCheck
068       * @declaredat /home/csz-naf/examples/PicoJava/spec/ErrorCheck.jadd:32
069       */
070      public void collectErrors(Collection c) {
071        super.collectErrors(c);
072        if(hasCycleOnSuperclassChain())
073          error(c, "Cyclic inheritance chain for class " + getName());
074      }
075      /**
076       * @aspect PrettyPrint
077       * @declaredat /home/csz-naf/examples/PicoJava/spec/PrettyPrint.jadd:40
078       */
079      public void prettyPrint(StringBuilder sb, int t) {
080                sb.append(getIndent(t)).append("class ").append(getName());
081                if (hasSuperclass()) {
082                        sb.append(" extends ").append(getSuperclass());
083                }
084                sb.append(" ");
085                getBody().prettyPrint(sb, t);
086        }
087      /**
088       */
089      public ClassDecl() {
090        super();
091      }
092      /**
093       * Initializes the child array to the correct size.
094       * Initializes List and Opt nta children.
095       * @apilevel internal
096       * @ast method
097       */
098      public void init$Children() {
099        children = new ASTNode[2];
100        setChild(new Opt(), 0);
101      }
102      /**
103       */
104      public ClassDecl(String p0, Opt<IdUse> p1, Block p2) {
105        setName(p0);
106        setChild(p1, 0);
107        setChild(p2, 1);
108      }
109      /**
110       * @apilevel low-level
111       */
112      protected int numChildren() {
113        return 2;
114      }
115      /**
116       * @apilevel internal
117       */
118      public boolean mayHaveRewrite() {
119        return false;
120      }
121      /**
122       * @apilevel low-level
123       */
124      public void flushCache() {
125        super.flushCache();
126        remoteLookup_String_visited = null;
127        isSubtypeOf_TypeDecl_visited = null;
128        isSubtypeOf_TypeDecl_values = null;
129        superClass_visited = -1;
130        superClass_computed = false;
131        superClass_value = null;
132        hasCycleOnSuperclassChain_visited = -1;
133        hasCycleOnSuperclassChain_computed = false;
134        hasCycleOnSuperclassChain_initialized = false;
135      }
136      /**
137       * @apilevel internal
138       */
139      public void flushCollectionCache() {
140        super.flushCollectionCache();
141      }
142      /**
143       * Replaces the lexeme Name.
144       * @param value The new value for the lexeme Name.
145       * @apilevel high-level
146       */
147      public void setName(String value) {
148        tokenString_Name = value;
149      }
150      /**
151       * Retrieves the value for the lexeme Name.
152       * @return The value for the lexeme Name.
153       * @apilevel high-level
154       */
155      public String getName() {
156        return tokenString_Name != null ? tokenString_Name : "";
157      }
158      /**
159       * Replaces the optional node for the Superclass child. This is the <code>Opt</code>
160       * node containing the child Superclass, not the actual child!
161       * @param opt The new node to be used as the optional node for the Superclass child.
162       * @apilevel low-level
163       */
164      public void setSuperclassOpt(Opt<IdUse> opt) {
165        setChild(opt, 0);
166      }
167      /**
168       * Replaces the (optional) Superclass child.
169       * @param node The new node to be used as the Superclass child.
170       * @apilevel high-level
171       */
172      public void setSuperclass(IdUse node) {
173        getSuperclassOpt().setChild(node, 0);
174      }
175      /**
176       * Check whether the optional Superclass child exists.
177       * @return {@code true} if the optional Superclass child exists, {@code false} if it does not.
178       * @apilevel high-level
179       */
180      public boolean hasSuperclass() {
181        return getSuperclassOpt().getNumChild() != 0;
182      }
183      /**
184       * Retrieves the (optional) Superclass child.
185       * @return The Superclass child, if it exists. Returns {@code null} otherwise.
186       * @apilevel low-level
187       */
188      public IdUse getSuperclass() {
189        return (IdUse) getSuperclassOpt().getChild(0);
190      }
191      /**
192       * Retrieves the optional node for the Superclass child. This is the <code>Opt</code> node containing the child Superclass, not the actual child!
193       * @return The optional node for child the Superclass child.
194       * @apilevel low-level
195       */
196      public Opt<IdUse> getSuperclassOpt() {
197        return (Opt<IdUse>) getChild(0);
198      }
199      /**
200       * Retrieves the optional node for child Superclass. This is the <code>Opt</code> node containing the child Superclass, not the actual child!
201       * <p><em>This method does not invoke AST transformations.</em></p>
202       * @return The optional node for child Superclass.
203       * @apilevel low-level
204       */
205      public Opt<IdUse> getSuperclassOptNoTransform() {
206        return (Opt<IdUse>) getChildNoTransform(0);
207      }
208      /**
209       * Replaces the Body child.
210       * @param node The new node to replace the Body child.
211       * @apilevel high-level
212       */
213      public void setBody(Block node) {
214        setChild(node, 1);
215      }
216      /**
217       * Retrieves the Body child.
218       * @return The current node used as the Body child.
219       * @apilevel high-level
220       */
221      public Block getBody() {
222        return (Block) getChild(1);
223      }
224      /**
225       * Retrieves the Body child.
226       * <p><em>This method does not invoke AST transformations.</em></p>
227       * @return The current node used as the Body child.
228       * @apilevel low-level
229       */
230      public Block getBodyNoTransform() {
231        return (Block) getChildNoTransform(1);
232      }
233      /**
234       * @apilevel internal
235       */
236      protected java.util.Map remoteLookup_String_visited;
237      /**
238       * @attribute syn
239       * @aspect NameResolution
240       * @declaredat /home/csz-naf/examples/PicoJava/spec/NameResolution.jrag:62
241       */
242      public Decl remoteLookup(String name) {
243        Object _parameters = name;
244        if(remoteLookup_String_visited == null) remoteLookup_String_visited = new java.util.HashMap(4);
245        ASTNode$State state = state();
246        if (Integer.valueOf(state().boundariesCrossed).equals(remoteLookup_String_visited.get(_parameters))) {
247          throw new RuntimeException("Circular definition of attr: remoteLookup in class: org.jastadd.ast.AST.SynDecl");
248        }
249        remoteLookup_String_visited.put(_parameters, Integer.valueOf(state().boundariesCrossed));
250        try {
251            // First, look in local declarations
252            if (!getBody().localLookup(name).isUnknown())
253              return getBody().localLookup(name); 
254            // Then, look in the superclass chain
255            if (superClass() != null && superClass().remoteLookup(name) != null 
256               && !superClass().remoteLookup(name).isUnknown())
257              return superClass().remoteLookup(name);
258            // Otherwise, return null object unknown
259            return unknownDecl();
260          }
261        finally {
262          remoteLookup_String_visited.remove(_parameters);
263        }
264      }
265      /**
266       * @apilevel internal
267       */
268      protected java.util.Map isSubtypeOf_TypeDecl_visited;
269      protected java.util.Map isSubtypeOf_TypeDecl_values;
270      /**
271       * @attribute syn
272       * @aspect TypeAnalysis
273       * @declaredat /home/csz-naf/examples/PicoJava/spec/TypeAnalysis.jrag:44
274       */
275      public boolean isSubtypeOf(TypeDecl typeDecl) {
276        Object _parameters = typeDecl;
277        if(isSubtypeOf_TypeDecl_visited == null) isSubtypeOf_TypeDecl_visited = new java.util.HashMap(4);
278        if(isSubtypeOf_TypeDecl_values == null) isSubtypeOf_TypeDecl_values = new java.util.HashMap(4);
279        if(isSubtypeOf_TypeDecl_values.containsKey(_parameters)) {
280          return ((Boolean)isSubtypeOf_TypeDecl_values.get(_parameters)).booleanValue();
281        }
282        ASTNode$State state = state();
283        if (Integer.valueOf(state().boundariesCrossed).equals(isSubtypeOf_TypeDecl_visited.get(_parameters))) {
284          throw new RuntimeException("Circular definition of attr: isSubtypeOf in class: org.jastadd.ast.AST.SynDecl");
285        }
286        isSubtypeOf_TypeDecl_visited.put(_parameters, Integer.valueOf(state().boundariesCrossed));
287        int num = state.boundariesCrossed;
288        boolean isFinal = this.is$Final();
289        boolean isSubtypeOf_TypeDecl_value = isSubtypeOf_compute(typeDecl);
290        if(isFinal && num == state().boundariesCrossed) {
291          isSubtypeOf_TypeDecl_values.put(_parameters, Boolean.valueOf(isSubtypeOf_TypeDecl_value));
292        } else {
293        }
294    
295        isSubtypeOf_TypeDecl_visited.remove(_parameters);
296        return isSubtypeOf_TypeDecl_value;
297      }
298      /**
299       * @apilevel internal
300       */
301      private boolean isSubtypeOf_compute(TypeDecl typeDecl) {  return typeDecl.isSuperTypeOfClassDecl(this);  }
302      /**
303       * @apilevel internal
304       */
305      protected int superClass_visited = -1;
306      /**
307       * @apilevel internal
308       */
309      protected boolean superClass_computed = false;
310      /**
311       * @apilevel internal
312       */
313      protected ClassDecl superClass_value;
314      /**
315       * @attribute syn
316       * @aspect TypeAnalysis
317       * @declaredat /home/csz-naf/examples/PicoJava/spec/TypeAnalysis.jrag:51
318       */
319      public ClassDecl superClass() {
320        if(superClass_computed) {
321          return superClass_value;
322        }
323        ASTNode$State state = state();
324        if (superClass_visited == state().boundariesCrossed) {
325          throw new RuntimeException("Circular definition of attr: superClass in class: org.jastadd.ast.AST.SynDecl");
326        }
327        superClass_visited = state().boundariesCrossed;
328        int num = state.boundariesCrossed;
329        boolean isFinal = this.is$Final();
330        superClass_value = superClass_compute();
331        if(isFinal && num == state().boundariesCrossed) {
332          superClass_computed = true;
333        } else {
334        }
335    
336        superClass_visited = -1;
337        return superClass_value;
338      }
339      /**
340       * @apilevel internal
341       */
342      private ClassDecl superClass_compute() {
343          if (hasSuperclass() && getSuperclass().decl() instanceof ClassDecl && !hasCycleOnSuperclassChain())
344            return (ClassDecl) getSuperclass().decl();
345          else
346            return null;
347        }
348      /**
349       * @apilevel internal
350       */
351      protected int hasCycleOnSuperclassChain_visited = -1;
352      /**
353       * @apilevel internal
354       */
355      protected boolean hasCycleOnSuperclassChain_computed = false;
356      /**
357       * @apilevel internal
358       */
359      protected boolean hasCycleOnSuperclassChain_initialized = false;
360      /**
361       * @apilevel internal
362       */
363      protected boolean hasCycleOnSuperclassChain_value;
364      /**
365       * @attribute syn
366       * @aspect TypeAnalysis
367       * @declaredat /home/csz-naf/examples/PicoJava/spec/TypeAnalysis.jrag:59
368       */
369      public boolean hasCycleOnSuperclassChain() {
370        if(hasCycleOnSuperclassChain_computed) {
371          return hasCycleOnSuperclassChain_value;
372        }
373        ASTNode$State state = state();
374        if (!hasCycleOnSuperclassChain_initialized) {
375          hasCycleOnSuperclassChain_initialized = true;
376          hasCycleOnSuperclassChain_value = true;
377        }
378        if (!state.IN_CIRCLE) {
379          state.IN_CIRCLE = true;
380          int num = state.boundariesCrossed;
381          boolean isFinal = this.is$Final();
382          // TODO: fixme
383          // state().CIRCLE_INDEX = 1;
384          do {
385            hasCycleOnSuperclassChain_visited = state.CIRCLE_INDEX;
386            state.CHANGE = false;
387            boolean new_hasCycleOnSuperclassChain_value = hasCycleOnSuperclassChain_compute();
388            if (new_hasCycleOnSuperclassChain_value != hasCycleOnSuperclassChain_value) {
389              state.CHANGE = true;
390            }
391            hasCycleOnSuperclassChain_value = new_hasCycleOnSuperclassChain_value;
392            state.CIRCLE_INDEX++;
393          } while (state.CHANGE);
394          if(isFinal && num == state().boundariesCrossed) {
395            hasCycleOnSuperclassChain_computed = true;
396            state.LAST_CYCLE = true;
397            hasCycleOnSuperclassChain_compute();
398            state.LAST_CYCLE = false;
399          } else {
400            state.RESET_CYCLE = true;
401            hasCycleOnSuperclassChain_compute();
402            state.RESET_CYCLE = false;
403            hasCycleOnSuperclassChain_computed = false;
404            hasCycleOnSuperclassChain_initialized = false;
405          }
406          state.IN_CIRCLE = false;
407          return hasCycleOnSuperclassChain_value;
408        }
409        if(hasCycleOnSuperclassChain_visited != state.CIRCLE_INDEX) {
410          hasCycleOnSuperclassChain_visited = state.CIRCLE_INDEX;
411          if (state.LAST_CYCLE) {
412          hasCycleOnSuperclassChain_computed = true;
413            boolean new_hasCycleOnSuperclassChain_value = hasCycleOnSuperclassChain_compute();
414            return new_hasCycleOnSuperclassChain_value;
415          }
416          if (state.RESET_CYCLE) {
417            hasCycleOnSuperclassChain_computed = false;
418            hasCycleOnSuperclassChain_initialized = false;
419            hasCycleOnSuperclassChain_visited = -1;
420            return hasCycleOnSuperclassChain_value;
421          }
422          boolean new_hasCycleOnSuperclassChain_value = hasCycleOnSuperclassChain_compute();
423          if (new_hasCycleOnSuperclassChain_value != hasCycleOnSuperclassChain_value) {
424            state.CHANGE = true;
425          }
426          hasCycleOnSuperclassChain_value = new_hasCycleOnSuperclassChain_value;
427          return hasCycleOnSuperclassChain_value;
428        }
429        return hasCycleOnSuperclassChain_value;
430      }
431      /**
432       * @apilevel internal
433       */
434      private boolean hasCycleOnSuperclassChain_compute() {
435          if (hasSuperclass() && getSuperclass().decl() instanceof ClassDecl) //First, check if there is a superclass
436            return ((ClassDecl) getSuperclass().decl()).hasCycleOnSuperclassChain();
437          else
438            return false;
439        }
440      /**
441       * @declaredat /home/csz-naf/examples/PicoJava/spec/NameResolution.jrag:31
442       * @apilevel internal
443       */
444      public Decl Define_Decl_lookup(ASTNode caller, ASTNode child, String name) {
445        if (caller == getBodyNoTransform()){
446        // First, look in superclass chain
447        
448        // EMMA: alternative impl. for debugging
449        ClassDecl superClass = superClass();
450        if (superClass != null) {
451               Decl remoteDecl = ((TypeDecl)superClass).remoteLookup(name);
452               if (remoteDecl != null) {
453                       if (!remoteDecl.isUnknown()) 
454                               return remoteDecl;      
455               }
456        } 
457        return lookup(name);
458        
459        
460        /*
461        EMMA: old impl before debugging
462        if (superClass() != null && !superClass().remoteLookup(name).isUnknown())
463          return superClass().remoteLookup(name);
464        // Then, look in surrounding context
465        return lookup(name);
466        */
467      }
468        else {
469          return getParent().Define_Decl_lookup(this, caller, name);
470        }
471      }
472      /**
473       * @apilevel internal
474       */
475      public ASTNode rewriteTo() {    return super.rewriteTo();
476      }}