001    /* This file was generated with JastAdd2 (http://jastadd.org) version 2.1.13-12-g880e696 */
002    package org.extendj.ast;
003    
004    import java.util.HashSet;
005    import java.io.File;
006    import java.util.Set;
007    import java.util.Collections;
008    import java.util.Collection;
009    import java.util.ArrayList;
010    import beaver.*;
011    import java.util.*;
012    import java.io.ByteArrayOutputStream;
013    import java.io.PrintStream;
014    import java.lang.reflect.InvocationTargetException;
015    import java.lang.reflect.Method;
016    import org.jastadd.util.*;
017    import java.util.zip.*;
018    import java.io.*;
019    import org.jastadd.util.PrettyPrintable;
020    import org.jastadd.util.PrettyPrinter;
021    import java.io.FileNotFoundException;
022    import java.io.BufferedInputStream;
023    import java.io.DataInputStream;
024    /**
025     * @ast node
026     * @declaredat /home/jesper/git/extendj/java4/grammar/Java.ast:203
027     * @production IfStmt : {@link Stmt} ::= <span class="component">Condition:{@link Expr}</span> <span class="component">Then:{@link Stmt}</span> <span class="component">[Else:{@link Stmt}]</span>;
028    
029     */
030    public class IfStmt extends Stmt implements Cloneable {
031      /**
032       * @aspect NodeConstructors
033       * @declaredat /home/jesper/git/extendj/java4/frontend/NodeConstructors.jrag:77
034       */
035      public IfStmt(Expr cond, Stmt thenBranch) {
036        this(cond, thenBranch, new Opt());
037      }
038      /**
039       * @aspect NodeConstructors
040       * @declaredat /home/jesper/git/extendj/java4/frontend/NodeConstructors.jrag:81
041       */
042      public IfStmt(Expr cond, Stmt thenBranch, Stmt elseBranch) {
043        this(cond, thenBranch, new Opt(elseBranch));
044      }
045      /**
046       * @aspect PrettyPrintUtil
047       * @declaredat /home/jesper/git/extendj/java4/frontend/PrettyPrintUtil.jrag:164
048       */
049      public void prettyPrint(PrettyPrinter out) {
050        out.print("if (");
051        out.print(getCondition());
052        out.print(") ");
053        if (getThen() instanceof Block) {
054          out.print(getThen());
055        } else {
056          out.print("{");
057          out.println();
058          out.indent(1);
059          out.print(getThen());
060          out.indent(0);
061          out.println();
062          out.print("}");
063        }
064        if (hasElse()) {
065          out.print(" else ");
066          if (getElse() instanceof Block) {
067            out.print(getElse());
068          } else {
069            out.print("{");
070            out.println();
071            out.indent(1);
072            out.print(getElse());
073            out.println();
074            out.print("}");
075          }
076        }
077      }
078      /**
079       * @aspect TypeCheck
080       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:371
081       */
082      public void typeCheck() {
083        TypeDecl cond = getCondition().type();
084        if (!cond.isBoolean()) {
085          errorf("the type of \"%s\" is %s which is not boolean",
086              getCondition().prettyPrint(), cond.name());
087        }
088      }
089      /**
090       * @aspect CreateBCode
091       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1539
092       */
093      public void createBCode(CodeGeneration gen) {
094        super.createBCode(gen);
095        int elseBranch = else_branch_label();
096        int thenBranch = then_branch_label();
097        int endBranch = end_label();
098        if (!getCondition().isConstant()) {
099          getCondition().branchFalse(gen, elseBranch);
100        }
101        gen.addLabel(thenBranch);
102        if (getCondition().canBeTrue()) {
103          getThen().createBCode(gen);
104          if (getThen().canCompleteNormally() && hasElse() && getCondition().canBeFalse()) {
105            gen.emitGoto(endBranch);
106          }
107        }
108        gen.addLabel(elseBranch);
109        if (hasElse() && getCondition().canBeFalse()) {
110          getElse().createBCode(gen);
111        }
112        gen.addLabel(endBranch);
113      }
114      /**
115       * @declaredat ASTNode:1
116       */
117      public IfStmt() {
118        super();
119      }
120      /**
121       * Initializes the child array to the correct size.
122       * Initializes List and Opt nta children.
123       * @apilevel internal
124       * @ast method
125       * @declaredat ASTNode:10
126       */
127      public void init$Children() {
128        children = new ASTNode[3];
129        setChild(new Opt(), 2);
130      }
131      /**
132       * @declaredat ASTNode:14
133       */
134      public IfStmt(Expr p0, Stmt p1, Opt<Stmt> p2) {
135        setChild(p0, 0);
136        setChild(p1, 1);
137        setChild(p2, 2);
138      }
139      /**
140       * @apilevel low-level
141       * @declaredat ASTNode:22
142       */
143      protected int numChildren() {
144        return 3;
145      }
146      /**
147       * @apilevel internal
148       * @declaredat ASTNode:28
149       */
150      public boolean mayHaveRewrite() {
151        return false;
152      }
153      /**
154       * @apilevel internal
155       * @declaredat ASTNode:34
156       */
157      public void flushAttrCache() {
158        super.flushAttrCache();
159        isDAafter_Variable_reset();
160        isDUafter_Variable_reset();
161        canCompleteNormally_reset();
162        else_branch_label_reset();
163        then_branch_label_reset();
164        end_label_reset();
165      }
166      /**
167       * @apilevel internal
168       * @declaredat ASTNode:46
169       */
170      public void flushCollectionCache() {
171        super.flushCollectionCache();
172      }
173      /**
174       * @apilevel internal
175       * @declaredat ASTNode:52
176       */
177      public void flushRewriteCache() {
178        super.flushRewriteCache();
179      }
180      /**
181       * @apilevel internal
182       * @declaredat ASTNode:58
183       */
184      public IfStmt clone() throws CloneNotSupportedException {
185        IfStmt node = (IfStmt) super.clone();
186        return node;
187      }
188      /**
189       * @apilevel internal
190       * @declaredat ASTNode:65
191       */
192      public IfStmt copy() {
193        try {
194          IfStmt node = (IfStmt) clone();
195          node.parent = null;
196          if (children != null) {
197            node.children = (ASTNode[]) children.clone();
198          }
199          return node;
200        } catch (CloneNotSupportedException e) {
201          throw new Error("Error: clone not supported for " + getClass().getName());
202        }
203      }
204      /**
205       * Create a deep copy of the AST subtree at this node.
206       * The copy is dangling, i.e. has no parent.
207       * @return dangling copy of the subtree at this node
208       * @apilevel low-level
209       * @deprecated Please use treeCopy or treeCopyNoTransform instead
210       * @declaredat ASTNode:84
211       */
212      @Deprecated
213      public IfStmt fullCopy() {
214        return treeCopyNoTransform();
215      }
216      /**
217       * Create a deep copy of the AST subtree at this node.
218       * The copy is dangling, i.e. has no parent.
219       * @return dangling copy of the subtree at this node
220       * @apilevel low-level
221       * @declaredat ASTNode:94
222       */
223      public IfStmt treeCopyNoTransform() {
224        IfStmt tree = (IfStmt) copy();
225        if (children != null) {
226          for (int i = 0; i < children.length; ++i) {
227            ASTNode child = (ASTNode) children[i];
228            if (child != null) {
229              child = child.treeCopyNoTransform();
230              tree.setChild(child, i);
231            }
232          }
233        }
234        return tree;
235      }
236      /**
237       * Create a deep copy of the AST subtree at this node.
238       * The subtree of this node is traversed to trigger rewrites before copy.
239       * The copy is dangling, i.e. has no parent.
240       * @return dangling copy of the subtree at this node
241       * @apilevel low-level
242       * @declaredat ASTNode:114
243       */
244      public IfStmt treeCopy() {
245        doFullTraversal();
246        return treeCopyNoTransform();
247      }
248      /**
249       * @apilevel internal
250       * @declaredat ASTNode:121
251       */
252      protected boolean is$Equal(ASTNode node) {
253        return super.is$Equal(node);    
254      }
255      /**
256       * Replaces the Condition child.
257       * @param node The new node to replace the Condition child.
258       * @apilevel high-level
259       */
260      public void setCondition(Expr node) {
261        setChild(node, 0);
262      }
263      /**
264       * Retrieves the Condition child.
265       * @return The current node used as the Condition child.
266       * @apilevel high-level
267       */
268      @ASTNodeAnnotation.Child(name="Condition")
269      public Expr getCondition() {
270        return (Expr) getChild(0);
271      }
272      /**
273       * Retrieves the Condition child.
274       * <p><em>This method does not invoke AST transformations.</em></p>
275       * @return The current node used as the Condition child.
276       * @apilevel low-level
277       */
278      public Expr getConditionNoTransform() {
279        return (Expr) getChildNoTransform(0);
280      }
281      /**
282       * Replaces the Then child.
283       * @param node The new node to replace the Then child.
284       * @apilevel high-level
285       */
286      public void setThen(Stmt node) {
287        setChild(node, 1);
288      }
289      /**
290       * Retrieves the Then child.
291       * @return The current node used as the Then child.
292       * @apilevel high-level
293       */
294      @ASTNodeAnnotation.Child(name="Then")
295      public Stmt getThen() {
296        return (Stmt) getChild(1);
297      }
298      /**
299       * Retrieves the Then child.
300       * <p><em>This method does not invoke AST transformations.</em></p>
301       * @return The current node used as the Then child.
302       * @apilevel low-level
303       */
304      public Stmt getThenNoTransform() {
305        return (Stmt) getChildNoTransform(1);
306      }
307      /**
308       * Replaces the optional node for the Else child. This is the <code>Opt</code>
309       * node containing the child Else, not the actual child!
310       * @param opt The new node to be used as the optional node for the Else child.
311       * @apilevel low-level
312       */
313      public void setElseOpt(Opt<Stmt> opt) {
314        setChild(opt, 2);
315      }
316      /**
317       * Replaces the (optional) Else child.
318       * @param node The new node to be used as the Else child.
319       * @apilevel high-level
320       */
321      public void setElse(Stmt node) {
322        getElseOpt().setChild(node, 0);
323      }
324      /**
325       * Check whether the optional Else child exists.
326       * @return {@code true} if the optional Else child exists, {@code false} if it does not.
327       * @apilevel high-level
328       */
329      public boolean hasElse() {
330        return getElseOpt().getNumChild() != 0;
331      }
332      /**
333       * Retrieves the (optional) Else child.
334       * @return The Else child, if it exists. Returns {@code null} otherwise.
335       * @apilevel low-level
336       */
337      public Stmt getElse() {
338        return (Stmt) getElseOpt().getChild(0);
339      }
340      /**
341       * Retrieves the optional node for the Else child. This is the <code>Opt</code> node containing the child Else, not the actual child!
342       * @return The optional node for child the Else child.
343       * @apilevel low-level
344       */
345      @ASTNodeAnnotation.OptChild(name="Else")
346      public Opt<Stmt> getElseOpt() {
347        return (Opt<Stmt>) getChild(2);
348      }
349      /**
350       * Retrieves the optional node for child Else. This is the <code>Opt</code> node containing the child Else, not the actual child!
351       * <p><em>This method does not invoke AST transformations.</em></p>
352       * @return The optional node for child Else.
353       * @apilevel low-level
354       */
355      public Opt<Stmt> getElseOptNoTransform() {
356        return (Opt<Stmt>) getChildNoTransform(2);
357      }
358      /**
359       * @apilevel internal
360       */
361      protected java.util.Map isDAafter_Variable_values;
362      /**
363       * @apilevel internal
364       */
365      private void isDAafter_Variable_reset() {
366        isDAafter_Variable_values = null;
367      }
368      /**
369       * @attribute syn
370       * @aspect DA
371       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:257
372       */
373      @ASTNodeAnnotation.Attribute
374      public boolean isDAafter(Variable v) {
375        Object _parameters = v;
376        if (isDAafter_Variable_values == null) isDAafter_Variable_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
377        ASTNode$State state = state();
378        if (isDAafter_Variable_values.containsKey(_parameters)) {
379          return (Boolean) isDAafter_Variable_values.get(_parameters);
380        }
381        boolean intermediate = state.INTERMEDIATE_VALUE;
382        state.INTERMEDIATE_VALUE = false;
383        int num = state.boundariesCrossed;
384        boolean isFinal = this.is$Final();
385        boolean isDAafter_Variable_value = hasElse() ? getThen().isDAafter(v) && getElse().isDAafter(v) : getThen().isDAafter(v) && getCondition().isDAafterFalse(v);
386        if (isFinal && num == state().boundariesCrossed) {
387          isDAafter_Variable_values.put(_parameters, isDAafter_Variable_value);
388        } else {
389        }
390        state.INTERMEDIATE_VALUE |= intermediate;
391    
392        return isDAafter_Variable_value;
393      }
394      /**
395       * @apilevel internal
396       */
397      protected java.util.Map isDUafter_Variable_values;
398      /**
399       * @apilevel internal
400       */
401      private void isDUafter_Variable_reset() {
402        isDUafter_Variable_values = null;
403      }
404      /**
405       * @attribute syn
406       * @aspect DU
407       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:781
408       */
409      @ASTNodeAnnotation.Attribute
410      public boolean isDUafter(Variable v) {
411        Object _parameters = v;
412        if (isDUafter_Variable_values == null) isDUafter_Variable_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
413        ASTNode$State state = state();
414        if (isDUafter_Variable_values.containsKey(_parameters)) {
415          return (Boolean) isDUafter_Variable_values.get(_parameters);
416        }
417        boolean intermediate = state.INTERMEDIATE_VALUE;
418        state.INTERMEDIATE_VALUE = false;
419        int num = state.boundariesCrossed;
420        boolean isFinal = this.is$Final();
421        boolean isDUafter_Variable_value = hasElse() ? getThen().isDUafter(v) && getElse().isDUafter(v) : getThen().isDUafter(v) && getCondition().isDUafterFalse(v);
422        if (isFinal && num == state().boundariesCrossed) {
423          isDUafter_Variable_values.put(_parameters, isDUafter_Variable_value);
424        } else {
425        }
426        state.INTERMEDIATE_VALUE |= intermediate;
427    
428        return isDUafter_Variable_value;
429      }
430      /**
431       * @apilevel internal
432       */
433      protected boolean canCompleteNormally_computed = false;
434      /**
435       * @apilevel internal
436       */
437      protected boolean canCompleteNormally_value;
438      /**
439       * @apilevel internal
440       */
441      private void canCompleteNormally_reset() {
442        canCompleteNormally_computed = false;
443      }
444      /**
445       * @attribute syn
446       * @aspect UnreachableStatements
447       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:53
448       */
449      @ASTNodeAnnotation.Attribute
450      public boolean canCompleteNormally() {
451        ASTNode$State state = state();
452        if (canCompleteNormally_computed) {
453          return canCompleteNormally_value;
454        }
455        boolean intermediate = state.INTERMEDIATE_VALUE;
456        state.INTERMEDIATE_VALUE = false;
457        int num = state.boundariesCrossed;
458        boolean isFinal = this.is$Final();
459        canCompleteNormally_value = (reachable() && !hasElse()) || (getThen().canCompleteNormally() ||
460            (hasElse() && getElse().canCompleteNormally()));
461        if (isFinal && num == state().boundariesCrossed) {
462          canCompleteNormally_computed = true;
463        } else {
464        }
465        state.INTERMEDIATE_VALUE |= intermediate;
466    
467        return canCompleteNormally_value;
468      }
469      /**
470       * @apilevel internal
471       */
472      protected boolean else_branch_label_computed = false;
473      /**
474       * @apilevel internal
475       */
476      protected int else_branch_label_value;
477      /**
478       * @apilevel internal
479       */
480      private void else_branch_label_reset() {
481        else_branch_label_computed = false;
482      }
483      /**
484       * @attribute syn
485       * @aspect CreateBCode
486       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1536
487       */
488      @ASTNodeAnnotation.Attribute
489      public int else_branch_label() {
490        ASTNode$State state = state();
491        if (else_branch_label_computed) {
492          return else_branch_label_value;
493        }
494        boolean intermediate = state.INTERMEDIATE_VALUE;
495        state.INTERMEDIATE_VALUE = false;
496        int num = state.boundariesCrossed;
497        boolean isFinal = this.is$Final();
498        else_branch_label_value = hostType().constantPool().newLabel();
499        if (isFinal && num == state().boundariesCrossed) {
500          else_branch_label_computed = true;
501        } else {
502        }
503        state.INTERMEDIATE_VALUE |= intermediate;
504    
505        return else_branch_label_value;
506      }
507      /**
508       * @apilevel internal
509       */
510      protected boolean then_branch_label_computed = false;
511      /**
512       * @apilevel internal
513       */
514      protected int then_branch_label_value;
515      /**
516       * @apilevel internal
517       */
518      private void then_branch_label_reset() {
519        then_branch_label_computed = false;
520      }
521      /**
522       * @attribute syn
523       * @aspect CreateBCode
524       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1537
525       */
526      @ASTNodeAnnotation.Attribute
527      public int then_branch_label() {
528        ASTNode$State state = state();
529        if (then_branch_label_computed) {
530          return then_branch_label_value;
531        }
532        boolean intermediate = state.INTERMEDIATE_VALUE;
533        state.INTERMEDIATE_VALUE = false;
534        int num = state.boundariesCrossed;
535        boolean isFinal = this.is$Final();
536        then_branch_label_value = hostType().constantPool().newLabel();
537        if (isFinal && num == state().boundariesCrossed) {
538          then_branch_label_computed = true;
539        } else {
540        }
541        state.INTERMEDIATE_VALUE |= intermediate;
542    
543        return then_branch_label_value;
544      }
545      /**
546       * @apilevel internal
547       */
548      protected boolean end_label_computed = false;
549      /**
550       * @apilevel internal
551       */
552      protected int end_label_value;
553      /**
554       * @apilevel internal
555       */
556      private void end_label_reset() {
557        end_label_computed = false;
558      }
559      /**
560       * @attribute syn
561       * @aspect CreateBCode
562       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1538
563       */
564      @ASTNodeAnnotation.Attribute
565      public int end_label() {
566        ASTNode$State state = state();
567        if (end_label_computed) {
568          return end_label_value;
569        }
570        boolean intermediate = state.INTERMEDIATE_VALUE;
571        state.INTERMEDIATE_VALUE = false;
572        int num = state.boundariesCrossed;
573        boolean isFinal = this.is$Final();
574        end_label_value = hostType().constantPool().newLabel();
575        if (isFinal && num == state().boundariesCrossed) {
576          end_label_computed = true;
577        } else {
578        }
579        state.INTERMEDIATE_VALUE |= intermediate;
580    
581        return end_label_value;
582      }
583      /**
584       * @attribute syn
585       * @aspect PreciseRethrow
586       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:84
587       */
588      @ASTNodeAnnotation.Attribute
589      public boolean modifiedInScope(Variable var) {
590        {
591            if (getThen().modifiedInScope(var)) {
592              return true;
593            }
594            return hasElse() && getElse().modifiedInScope(var);
595          }
596      }
597      /**
598       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:255
599       * @apilevel internal
600       */
601      public boolean Define_isDAbefore(ASTNode caller, ASTNode child, Variable v) {
602        if (caller == getElseOptNoTransform()) {
603          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:593
604          return getCondition().isDAafterFalse(v);
605        }
606        else if (caller == getThenNoTransform()) {
607          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:592
608          return getCondition().isDAafterTrue(v);
609        }
610        else if (caller == getConditionNoTransform()) {
611          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:591
612          return isDAbefore(v);
613        }
614        else {
615          return getParent().Define_isDAbefore(this, caller, v);
616        }
617      }
618      protected boolean canDefine_isDAbefore(ASTNode caller, ASTNode child, Variable v) {
619        return true;
620      }
621      /**
622       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:779
623       * @apilevel internal
624       */
625      public boolean Define_isDUbefore(ASTNode caller, ASTNode child, Variable v) {
626        if (caller == getElseOptNoTransform()) {
627          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1154
628          return getCondition().isDUafterFalse(v);
629        }
630        else if (caller == getThenNoTransform()) {
631          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1153
632          return getCondition().isDUafterTrue(v);
633        }
634        else if (caller == getConditionNoTransform()) {
635          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1152
636          return isDUbefore(v);
637        }
638        else {
639          return getParent().Define_isDUbefore(this, caller, v);
640        }
641      }
642      protected boolean canDefine_isDUbefore(ASTNode caller, ASTNode child, Variable v) {
643        return true;
644      }
645      /**
646       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:52
647       * @apilevel internal
648       */
649      public boolean Define_reachable(ASTNode caller, ASTNode child) {
650        if (caller == getElseOptNoTransform()) {
651          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:206
652          return reachable();
653        }
654        else if (caller == getThenNoTransform()) {
655          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:205
656          return reachable();
657        }
658        else {
659          return getParent().Define_reachable(this, caller);
660        }
661      }
662      protected boolean canDefine_reachable(ASTNode caller, ASTNode child) {
663        return true;
664      }
665      /**
666       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:283
667       * @apilevel internal
668       */
669      public boolean Define_reportUnreachable(ASTNode caller, ASTNode child) {
670        if (caller == getElseOptNoTransform()) {
671          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:212
672          return reachable();
673        }
674        else if (caller == getThenNoTransform()) {
675          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:211
676          return reachable();
677        }
678        else {
679          return getParent().Define_reportUnreachable(this, caller);
680        }
681      }
682      protected boolean canDefine_reportUnreachable(ASTNode caller, ASTNode child) {
683        return true;
684      }
685      /**
686       * @declaredat /home/jesper/git/extendj/java8/frontend/EffectivelyFinal.jrag:30
687       * @apilevel internal
688       */
689      public boolean Define_inhModifiedInScope(ASTNode caller, ASTNode child, Variable var) {
690        if (caller == getElseOptNoTransform()) {
691          // @declaredat /home/jesper/git/extendj/java8/frontend/EffectivelyFinal.jrag:53
692          return false;
693        }
694        else if (caller == getThenNoTransform()) {
695          // @declaredat /home/jesper/git/extendj/java8/frontend/EffectivelyFinal.jrag:52
696          return false;
697        }
698        else {
699          return getParent().Define_inhModifiedInScope(this, caller, var);
700        }
701      }
702      protected boolean canDefine_inhModifiedInScope(ASTNode caller, ASTNode child, Variable var) {
703        return true;
704      }
705      /**
706       * @apilevel internal
707       */
708      public ASTNode rewriteTo() {
709        return super.rewriteTo();
710      }
711    }