001    /* This file was generated with JastAdd2 (http://jastadd.org) version 2.1.13-9-g0922917 */
002    package org.jastadd.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 org.jastadd.util.*;
013    import java.util.zip.*;
014    import java.io.*;
015    import org.jastadd.util.PrettyPrintable;
016    import org.jastadd.util.PrettyPrinter;
017    import java.io.FileNotFoundException;
018    import java.io.BufferedInputStream;
019    import java.io.DataInputStream;
020    /**
021     * @ast node
022     * @declaredat /home/jesper/git/extendj/java4/grammar/Java.ast:198
023     * @production SwitchStmt : {@link BranchTargetStmt} ::= <span class="component">{@link Expr}</span> <span class="component">{@link Block}</span>;
024    
025     */
026    public class SwitchStmt extends BranchTargetStmt implements Cloneable {
027      /**
028       * @aspect Java4PrettyPrint
029       * @declaredat /home/jesper/git/extendj/java4/frontend/PrettyPrint.jadd:238
030       */
031      public void prettyPrint(PrettyPrinter out) {
032        out.print("switch (");
033        out.print(getExpr());
034        out.print(") ");
035        out.print(getBlock());
036      }
037      /**
038       * @aspect CreateBCode
039       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1504
040       */
041      private int emitPad(CodeGeneration gen) {
042        int pad = (4 - (gen.pos() % 4)) % 4;
043        for (int i = 0; i < pad; i++) {
044          gen.emit(Bytecode.NOP);
045        }
046        if (gen.pos() % 4 != 0) {
047          throw new Error("Switch not at 4-byte boundary:" + gen.pos());
048        }
049        return pad;
050      }
051      /**
052       * Calculate offset to the default label.
053       * @return bytecode offset to default label (or zero if there is no
054       * default label)
055       * @aspect CreateBCode
056       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1520
057       */
058      private int defaultOffset(CodeGeneration gen, int switch_label) {
059        DefaultCase defaultCase = defaultCase();
060        if (defaultCase != null) {
061          int offset = gen.addressOf(defaultCase.label())
062            - gen.addressOf(switch_label);
063          return offset;
064        }
065        return 0;
066      }
067      /**
068       * @aspect EnumsCodegen
069       * @declaredat /home/jesper/git/extendj/java5/backend/EnumsCodegen.jrag:38
070       */
071      public void transformation() {
072        if (getExpr().type().isEnumDecl()) {
073          TypeDecl type = getExpr().type();
074          hostType().createEnumArray(type);
075          hostType().createEnumMethod(type);
076          setExpr(
077            hostType().createEnumMethod(type).createBoundAccess(new List()).qualifiesAccess(
078            new ArrayAccess(
079              ((Expr) getExpr().treeCopyNoTransform()).qualifiesAccess(new MethodAccess("ordinal", new List()))
080            ))
081          );
082        }
083        super.transformation();
084      }
085      /**
086       * @aspect StringsInSwitch
087       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:170
088       */
089      private void genFirstSwitch(
090          CodeGeneration gen,
091          TreeMap<Integer, CaseGroup> groups,
092          int index_a) {
093        int switch_label = gen.constantPool().newLabel();
094        int end_label1 = gen.constantPool().newLabel();
095        int index_b = localNumB();
096    
097        // Initialize switch variable for second switch
098        IntegerLiteral.push(gen, 0);
099        typeInt().emitStoreLocal(gen, index_a);
100    
101        // Store the value of the switch expr so that it is only evaluated once!
102        getExpr().createBCode(gen);
103    
104        // Push the hash code for the switch instruction
105        if (getExpr().isConstant()) {
106          typeString().emitStoreLocal(gen, index_b);
107    
108          int hashCode = getExpr().constant().stringValue().hashCode();
109          IntegerLiteral.push(gen, hashCode);
110        } else {
111          typeString().emitDup(gen);
112          typeString().emitStoreLocal(gen, index_b);
113          hashCodeMethod().emitInvokeMethod(gen,
114              lookupType("java.lang", "Object"));
115        }
116    
117        // Emit switch instruction
118        int low = groups.isEmpty() ? 0 : groups.firstKey();
119        int high = groups.isEmpty() ? 0 : groups.lastKey();
120    
121        int tableSwitchSize = 4 * (3 + (high - low + 1));
122        int lookupSwitchSize = 4 * (2 + 2 * groups.size());
123        int pad;
124        int switchSize;
125        int switchPos;
126        boolean tableSwitch = tableSwitchSize < lookupSwitchSize;
127    
128        gen.addLabel(switch_label);
129    
130        // Select the switch type which produces the smallest switch instr.
131        if (tableSwitch) {
132          // TABLESWITCH
133          gen.emit(Bytecode.TABLESWITCH);
134          switchSize = tableSwitchSize;
135        } else {
136          // LOOKUPSWITCH
137          gen.emit(Bytecode.LOOKUPSWITCH);
138          switchSize = lookupSwitchSize;
139        }
140    
141        pad = emitPad(gen);
142        switchPos = gen.pos();
143    
144        // leave room for the address table
145        gen.skip(switchSize);
146    
147        // Code generation for switch body
148        for (CaseGroup group : groups.values()) {
149          gen.addLabel(group.lbl);
150    
151          // Possible hash miss. Check for equality.
152          Iterator<CaseLbl> iter = group.lbls.iterator();
153          while (iter.hasNext()) {
154            CaseLbl lbl = iter.next();
155            int thenLbl;
156            if (iter.hasNext()) {
157              thenLbl = gen.constantPool().newLabel();
158            } else
159              // last conditional branches to end label
160              thenLbl = end_label1;
161    
162            typeString().emitLoadLocal(gen, index_b);
163            StringLiteral.push(gen, lbl.value);
164            equalsMethod().emitInvokeMethod(gen,
165                lookupType("java.lang", "Object"));
166            gen.emitCompare(Bytecode.IFEQ, thenLbl);
167            IntegerLiteral.push(gen, lbl.serial);
168            typeInt().emitStoreLocal(gen, index_a);
169            gen.emitGoto(end_label1);
170    
171            if (iter.hasNext()) {
172              gen.addLabel(thenLbl);
173            }
174          }
175        }
176    
177        // write jump address table
178        int endpos = gen.pos();
179        gen.setPos(switchPos);
180        if (tableSwitch) {
181          int defaultOffset = 1 + pad + switchSize;
182          gen.add4(defaultOffset);
183          gen.add4(low);
184          gen.add4(high);
185          for (int i = low; i <= high; i++) {
186            if (groups.containsKey(i)) {
187              CaseGroup group = groups.get(i);
188              int offset = labelOffset(gen, group.lbl, switch_label);
189              gen.add4(offset);
190            } else {
191              gen.add4(defaultOffset);
192            }
193          }
194        } else {
195          int defaultOffset = 1 + pad + switchSize;
196          gen.add4(defaultOffset);
197          gen.add4(groups.size());
198          for (CaseGroup group : groups.values()) {
199            gen.add4(group.hashCode);
200            int offset = labelOffset(gen, group.lbl, switch_label);
201            gen.add4(offset);
202          }
203        }
204        gen.setPos(endpos);
205    
206        gen.addLabel(end_label1);
207      }
208      /**
209       * @aspect StringsInSwitch
210       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:290
211       */
212      private void genSecondSwitch(
213          CodeGeneration gen,
214          java.util.List<CaseLbl> labels,
215          int index_a,
216          CaseLbl defaultLbl) {
217        int switch_label = gen.constantPool().newLabel();
218        int default_label = gen.constantPool().newLabel();
219    
220        // push the switch variable
221        typeInt().emitLoadLocal(gen, index_a);
222    
223        // Emit switch instruction
224        gen.addLabel(switch_label);
225        gen.emit(Bytecode.TABLESWITCH);
226        int high = labels.size();
227        int low = 0;
228        int pad;
229        int switchSize = 4 * (3 + (high - low + 1));
230        int switchPos;
231    
232        pad = emitPad(gen);
233        switchPos = gen.pos();
234        gen.skip(switchSize);
235    
236        // Code generation for case labels
237    
238        for (CaseLbl lbl : labels) {
239          gen.addLabel(lbl.lbl);
240          lbl.createBCode(gen);
241        }
242    
243        gen.addLabel(default_label);
244        if (defaultLbl != null) {
245          defaultLbl.createBCode(gen);
246        }
247    
248        int endpos = gen.pos();
249        gen.setPos(switchPos);
250        int defaultOffset = 1 + pad + switchSize;
251        gen.add4(defaultOffset);
252        gen.add4(low);
253        gen.add4(high);
254        int offset = labelOffset(gen, default_label, switch_label);
255        gen.add4(offset);
256        for (CaseLbl lbl : labels) {
257          offset = labelOffset(gen, lbl.lbl, switch_label);
258          gen.add4(offset);
259        }
260        gen.setPos(endpos);
261    
262        gen.addLabel(end_label());
263      }
264      /**
265       * Generate invocation of method
266       * {@code java.lang.Object.hashCode()}.
267       * @aspect StringsInSwitch
268       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:347
269       */
270      private MethodDecl hashCodeMethod() {
271        TypeDecl objectType = lookupType("java.lang", "Object");
272        if (objectType.isUnknown()) {
273          throw new Error("Could not find java.lang.Object");
274        }
275        for (MethodDecl method :
276            (Collection<MethodDecl>) objectType.memberMethods("hashCode")) {
277          if (method.getNumParameter() == 0) {
278            return method;
279          }
280        }
281        throw new Error("Could not find java.lang.Object.hashCode()");
282      }
283      /**
284       * Generate invocation of method
285       * {@code java.lang.Object.equals(java.lang.Object)}.
286       * @aspect StringsInSwitch
287       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:365
288       */
289      private MethodDecl equalsMethod() {
290        TypeDecl objectType = lookupType("java.lang", "Object");
291        if (objectType.isUnknown()) {
292          throw new Error("Could not find java.lang.Object");
293        }
294        for (MethodDecl method :
295            (Collection<MethodDecl>) objectType.memberMethods("equals")) {
296          if (method.getNumParameter() == 1 &&
297              method.getParameter(0).getTypeAccess().type() == objectType)
298            return method;
299        }
300        throw new Error("Could not find java.lang.Object.equals()");
301      }
302      /**
303       * @declaredat ASTNode:1
304       */
305      public SwitchStmt() {
306        super();
307      }
308      /**
309       * Initializes the child array to the correct size.
310       * Initializes List and Opt nta children.
311       * @apilevel internal
312       * @ast method
313       * @declaredat ASTNode:10
314       */
315      public void init$Children() {
316        children = new ASTNode[2];
317      }
318      /**
319       * @declaredat ASTNode:13
320       */
321      public SwitchStmt(Expr p0, Block p1) {
322        setChild(p0, 0);
323        setChild(p1, 1);
324      }
325      /**
326       * @apilevel low-level
327       * @declaredat ASTNode:20
328       */
329      protected int numChildren() {
330        return 2;
331      }
332      /**
333       * @apilevel internal
334       * @declaredat ASTNode:26
335       */
336      public boolean mayHaveRewrite() {
337        return false;
338      }
339      /**
340       * @apilevel internal
341       * @declaredat ASTNode:32
342       */
343      public void flushAttrCache() {
344        super.flushAttrCache();
345        isDAafter_Variable_reset();
346        isDUafter_Variable_reset();
347        canCompleteNormally_reset();
348        defaultCase_reset();
349        end_label_reset();
350        typeInt_reset();
351        typeLong_reset();
352      }
353      /**
354       * @apilevel internal
355       * @declaredat ASTNode:45
356       */
357      public void flushCollectionCache() {
358        super.flushCollectionCache();
359      }
360      /**
361       * @apilevel internal
362       * @declaredat ASTNode:51
363       */
364      public void flushRewriteCache() {
365        super.flushRewriteCache();
366      }
367      /**
368       * @apilevel internal
369       * @declaredat ASTNode:57
370       */
371      public SwitchStmt clone() throws CloneNotSupportedException {
372        SwitchStmt node = (SwitchStmt) super.clone();
373        return node;
374      }
375      /**
376       * @apilevel internal
377       * @declaredat ASTNode:64
378       */
379      public SwitchStmt copy() {
380        try {
381          SwitchStmt node = (SwitchStmt) clone();
382          node.parent = null;
383          if (children != null) {
384            node.children = (ASTNode[]) children.clone();
385          }
386          return node;
387        } catch (CloneNotSupportedException e) {
388          throw new Error("Error: clone not supported for " + getClass().getName());
389        }
390      }
391      /**
392       * Create a deep copy of the AST subtree at this node.
393       * The copy is dangling, i.e. has no parent.
394       * @return dangling copy of the subtree at this node
395       * @apilevel low-level
396       * @deprecated Please use treeCopy or treeCopyNoTransform instead
397       * @declaredat ASTNode:83
398       */
399      @Deprecated
400      public SwitchStmt fullCopy() {
401        return treeCopyNoTransform();
402      }
403      /**
404       * Create a deep copy of the AST subtree at this node.
405       * The copy is dangling, i.e. has no parent.
406       * @return dangling copy of the subtree at this node
407       * @apilevel low-level
408       * @declaredat ASTNode:93
409       */
410      public SwitchStmt treeCopyNoTransform() {
411        SwitchStmt tree = (SwitchStmt) copy();
412        if (children != null) {
413          for (int i = 0; i < children.length; ++i) {
414            ASTNode child = (ASTNode) children[i];
415            if (child != null) {
416              child = child.treeCopyNoTransform();
417              tree.setChild(child, i);
418            }
419          }
420        }
421        return tree;
422      }
423      /**
424       * Create a deep copy of the AST subtree at this node.
425       * The subtree of this node is traversed to trigger rewrites before copy.
426       * The copy is dangling, i.e. has no parent.
427       * @return dangling copy of the subtree at this node
428       * @apilevel low-level
429       * @declaredat ASTNode:113
430       */
431      public SwitchStmt treeCopy() {
432        doFullTraversal();
433        return treeCopyNoTransform();
434      }
435      /**
436       * @apilevel internal
437       * @declaredat ASTNode:120
438       */
439      protected boolean is$Equal(ASTNode node) {
440        return super.is$Equal(node);    
441      }
442      /**
443       * Replaces the Expr child.
444       * @param node The new node to replace the Expr child.
445       * @apilevel high-level
446       */
447      public void setExpr(Expr node) {
448        setChild(node, 0);
449      }
450      /**
451       * Retrieves the Expr child.
452       * @return The current node used as the Expr child.
453       * @apilevel high-level
454       */
455      @ASTNodeAnnotation.Child(name="Expr")
456      public Expr getExpr() {
457        return (Expr) getChild(0);
458      }
459      /**
460       * Retrieves the Expr child.
461       * <p><em>This method does not invoke AST transformations.</em></p>
462       * @return The current node used as the Expr child.
463       * @apilevel low-level
464       */
465      public Expr getExprNoTransform() {
466        return (Expr) getChildNoTransform(0);
467      }
468      /**
469       * Replaces the Block child.
470       * @param node The new node to replace the Block child.
471       * @apilevel high-level
472       */
473      public void setBlock(Block node) {
474        setChild(node, 1);
475      }
476      /**
477       * Retrieves the Block child.
478       * @return The current node used as the Block child.
479       * @apilevel high-level
480       */
481      @ASTNodeAnnotation.Child(name="Block")
482      public Block getBlock() {
483        return (Block) getChild(1);
484      }
485      /**
486       * Retrieves the Block child.
487       * <p><em>This method does not invoke AST transformations.</em></p>
488       * @return The current node used as the Block child.
489       * @apilevel low-level
490       */
491      public Block getBlockNoTransform() {
492        return (Block) getChildNoTransform(1);
493      }
494      /**
495       * @aspect AutoBoxingCodegen
496       * @declaredat /home/jesper/git/extendj/java5/backend/AutoBoxingCodegen.jrag:174
497       */
498        public void refined_AutoBoxingCodegen_SwitchStmt_createBCode(CodeGeneration gen) {
499        super.createBCode(gen);
500        int cond_label = gen.constantPool().newLabel();
501        int switch_label = gen.constantPool().newLabel();
502    
503        gen.emitGoto(cond_label);
504        getBlock().createBCode(gen);
505        if (canCompleteNormally()) {
506          gen.emitGoto(end_label());
507        }
508        gen.addLabel(cond_label);
509        getExpr().createBCode(gen);
510        if (getExpr().type().isReferenceType()) {
511          getExpr().type().emitUnboxingOperation(gen);
512        }
513    
514        TreeMap map = new TreeMap();
515        for (int i = 0; i < getBlock().getNumStmt(); i++) {
516          if (getBlock().getStmt(i) instanceof ConstCase) {
517            ConstCase ca = (ConstCase) getBlock().getStmt(i);
518            map.put(new Integer(ca.getValue().constant().intValue()), ca);
519          }
520        }
521    
522        long low = map.isEmpty() ? 0 : ((Integer) map.firstKey()).intValue();
523        long high = map.isEmpty() ? 0 : ((Integer) map.lastKey()).intValue();
524    
525        long tableSwitchSize = 8L + (high - low + 1L) * 4L;
526        long lookupSwitchSize = 4L + map.size() * 8L;
527    
528        gen.addLabel(switch_label);
529        if (tableSwitchSize < lookupSwitchSize) {
530          gen.emit(Bytecode.TABLESWITCH);
531          int pad = emitPad(gen);
532          int defaultOffset = defaultOffset(gen, switch_label);
533          if (defaultOffset == 0) {
534            defaultOffset = 1 + pad + 4 + 4 + 4 + 4 * (int)(high - low + 1);
535          }
536          gen.add4(defaultOffset);
537          gen.add4((int) low);
538          gen.add4((int) high);
539          for (long i = low; i <= high; i++) {
540            ConstCase ca = (ConstCase) map.get(new Integer((int) i));
541            if (ca != null) {
542              int offset = gen.addressOf(ca.label())
543                - gen.addressOf(switch_label);
544              gen.add4(offset);
545            } else {
546              gen.add4(defaultOffset);
547            }
548          }
549        } else {
550          gen.emit(Bytecode.LOOKUPSWITCH);
551          int pad = emitPad(gen);
552          int defaultOffset = defaultOffset(gen, switch_label);
553          if (defaultOffset == 0) {
554            defaultOffset = 1 + pad + 4 + 4 + 8 * numCase();
555          }
556          gen.add4(defaultOffset);
557          gen.add4(map.size());
558          for (Iterator iter = map.values().iterator(); iter.hasNext(); ) {
559            ConstCase ca = (ConstCase) iter.next();
560            gen.add4(ca.getValue().constant().intValue());
561            int offset = gen.addressOf(ca.label())
562              - gen.addressOf(switch_label);
563            gen.add4(offset);
564          }
565        }
566        gen.addLabel(end_label());
567      }
568      /**
569       * @aspect Enums
570       * @declaredat /home/jesper/git/extendj/java5/frontend/Enums.jrag:566
571       */
572        public void refined_Enums_SwitchStmt_typeCheck() {
573         TypeDecl type = getExpr().type();
574        if ((!type.isIntegralType() || type.isLong()) && !type.isEnumDecl()) {
575          error("Switch expression must be of char, byte, short, int, or enum type");
576        }
577      }
578      /**
579       * Overrides the type checking of the switch statement's expression.
580       * 
581       * <p>In JSR 334 a switch statement may use an expression of type String.
582       * @aspect StringsInSwitch
583       * @declaredat /home/jesper/git/extendj/java7/frontend/StringsInSwitch.jrag:47
584       */
585        public void typeCheck() {
586        TypeDecl type = getExpr().type();
587        if ((!type.isIntegralType() || type.isLong()) && !type.isEnumDecl() && !type.isString()) {
588          error("Switch expression must be of type char, byte, short, int, enum, or string");
589        }
590      }
591      /**
592       * Two switch statements are generated.
593       * The first switch will switch on the hash code of the switch expression.
594       * The first switch statement computes a value for a variable that selects
595       * a case in the second switch statement.
596       * 
597       * @aspect StringsInSwitch
598       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:126
599       */
600       
601        public void createBCode(CodeGeneration gen) {
602        if (getExpr().type().isString()) {
603          // add line number for start of statement
604          super.createBCode(gen);
605    
606          // Enumerate case labels with same hash value
607          TreeMap< Integer, CaseGroup > groups = new TreeMap< Integer, CaseGroup >();
608          java.util.List<CaseLbl> labels = new LinkedList<CaseLbl>();
609    
610          CaseLbl defaultLbl = null;
611          CaseLbl caseLbl = null;
612          int serial = 1;
613          for (Stmt stmt : getBlock().getStmts()) {
614            if (stmt instanceof ConstCase) {
615              ConstCase cc = (ConstCase) stmt;
616              caseLbl = new CaseLbl(cc, gen);
617              caseLbl.serial = serial++;
618              labels.add(caseLbl);
619              int key = caseLbl.value.hashCode();
620              if (groups.containsKey(key)) {
621                groups.get(key).addCase(caseLbl);
622              } else {
623                CaseGroup group = new CaseGroup(this, key);
624                group.addCase(caseLbl);
625                groups.put(key, group);
626              }
627            } else if (stmt instanceof DefaultCase) {
628              defaultLbl = new CaseLbl(hostType().constantPool().newLabel());
629              caseLbl = defaultLbl;
630            } else if (caseLbl != null) {
631              caseLbl.addStmt(stmt);
632            }
633          }
634    
635          int index_a = localNumA();
636          genFirstSwitch(gen, groups, index_a);
637          genSecondSwitch(gen, labels, index_a, defaultLbl);
638    
639        } else {
640          refined_AutoBoxingCodegen_SwitchStmt_createBCode(gen);
641        }
642      }
643      /**
644       * @return <code>true</code> if this statement is a potential
645       * branch target of the given branch statement.
646       * @attribute syn
647       * @aspect BranchTarget
648       * @declaredat /home/jesper/git/extendj/java4/frontend/BranchTarget.jrag:217
649       */
650      @ASTNodeAnnotation.Attribute
651      public boolean potentialTargetOf(Stmt branch) {
652        boolean potentialTargetOf_Stmt_value = branch.canBranchTo(this);
653    
654        return potentialTargetOf_Stmt_value;
655      }
656      /**
657       * @apilevel internal
658       */
659      protected java.util.Map isDAafter_Variable_values;
660      /**
661       * @apilevel internal
662       */
663      private void isDAafter_Variable_reset() {
664        isDAafter_Variable_values = null;
665      }
666      /**
667       * @attribute syn
668       * @aspect DA
669       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:257
670       */
671      @ASTNodeAnnotation.Attribute
672      public boolean isDAafter(Variable v) {
673        Object _parameters = v;
674        if (isDAafter_Variable_values == null) isDAafter_Variable_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
675        ASTNode$State state = state();
676        if (isDAafter_Variable_values.containsKey(_parameters)) {
677          return (Boolean) isDAafter_Variable_values.get(_parameters);
678        }
679        boolean intermediate = state.INTERMEDIATE_VALUE;
680        state.INTERMEDIATE_VALUE = false;
681        int num = state.boundariesCrossed;
682        boolean isFinal = this.is$Final();
683        boolean isDAafter_Variable_value = isDAafter_compute(v);
684        if (isFinal && num == state().boundariesCrossed) {
685          isDAafter_Variable_values.put(_parameters, isDAafter_Variable_value);
686        } else {
687        }
688        state.INTERMEDIATE_VALUE |= intermediate;
689    
690        return isDAafter_Variable_value;
691      }
692      /**
693       * @apilevel internal
694       */
695      private boolean isDAafter_compute(Variable v) {
696          if (!(!noDefaultLabel() || getExpr().isDAafter(v))) {
697            return false;
698          }
699          if (!(!switchLabelEndsBlock() || getExpr().isDAafter(v))) {
700            return false;
701          }
702          if (!assignedAfterLastStmt(v)) {
703            return false;
704          }
705          for (Iterator iter = targetBreaks().iterator(); iter.hasNext(); ) {
706            BreakStmt stmt = (BreakStmt) iter.next();
707            if (!stmt.isDAafterReachedFinallyBlocks(v)) {
708              return false;
709            }
710          }
711          return true;
712        }
713      /**
714       * @attribute syn
715       * @aspect DA
716       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:615
717       */
718      @ASTNodeAnnotation.Attribute
719      public boolean assignedAfterLastStmt(Variable v) {
720        boolean assignedAfterLastStmt_Variable_value = getBlock().isDAafter(v);
721    
722        return assignedAfterLastStmt_Variable_value;
723      }
724      /**
725       * @apilevel internal
726       */
727      protected java.util.Map isDUafter_Variable_values;
728      /**
729       * @apilevel internal
730       */
731      private void isDUafter_Variable_reset() {
732        isDUafter_Variable_values = null;
733      }
734      /**
735       * @attribute syn
736       * @aspect DU
737       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:781
738       */
739      @ASTNodeAnnotation.Attribute
740      public boolean isDUafter(Variable v) {
741        Object _parameters = v;
742        if (isDUafter_Variable_values == null) isDUafter_Variable_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
743        ASTNode$State state = state();
744        if (isDUafter_Variable_values.containsKey(_parameters)) {
745          return (Boolean) isDUafter_Variable_values.get(_parameters);
746        }
747        boolean intermediate = state.INTERMEDIATE_VALUE;
748        state.INTERMEDIATE_VALUE = false;
749        int num = state.boundariesCrossed;
750        boolean isFinal = this.is$Final();
751        boolean isDUafter_Variable_value = isDUafter_compute(v);
752        if (isFinal && num == state().boundariesCrossed) {
753          isDUafter_Variable_values.put(_parameters, isDUafter_Variable_value);
754        } else {
755        }
756        state.INTERMEDIATE_VALUE |= intermediate;
757    
758        return isDUafter_Variable_value;
759      }
760      /**
761       * @apilevel internal
762       */
763      private boolean isDUafter_compute(Variable v) {
764          if (!(!noDefaultLabel() || getExpr().isDUafter(v))) {
765            return false;
766          }
767          if (!(!switchLabelEndsBlock() || getExpr().isDUafter(v))) {
768            return false;
769          }
770          if (!unassignedAfterLastStmt(v)) {
771            return false;
772          }
773          for (Iterator iter = targetBreaks().iterator(); iter.hasNext(); ) {
774            BreakStmt stmt = (BreakStmt) iter.next();
775            if (!stmt.isDUafterReachedFinallyBlocks(v)) {
776              return false;
777            }
778          }
779          return true;
780        }
781      /**
782       * @attribute syn
783       * @aspect DU
784       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1176
785       */
786      @ASTNodeAnnotation.Attribute
787      public boolean unassignedAfterLastStmt(Variable v) {
788        boolean unassignedAfterLastStmt_Variable_value = getBlock().isDUafter(v);
789    
790        return unassignedAfterLastStmt_Variable_value;
791      }
792      /**
793       * @attribute syn
794       * @aspect DU
795       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1179
796       */
797      @ASTNodeAnnotation.Attribute
798      public boolean switchLabelEndsBlock() {
799        boolean switchLabelEndsBlock_value = getBlock().getNumStmt() > 0
800              && getBlock().getStmt(getBlock().getNumStmt()-1) instanceof ConstCase;
801    
802        return switchLabelEndsBlock_value;
803      }
804      /**
805       * @attribute syn
806       * @aspect UnreachableStatements
807       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:98
808       */
809      @ASTNodeAnnotation.Attribute
810      public boolean lastStmtCanCompleteNormally() {
811        boolean lastStmtCanCompleteNormally_value = getBlock().canCompleteNormally();
812    
813        return lastStmtCanCompleteNormally_value;
814      }
815      /**
816       * @attribute syn
817       * @aspect UnreachableStatements
818       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:100
819       */
820      @ASTNodeAnnotation.Attribute
821      public boolean noStmts() {
822        {
823            for (int i = 0; i < getBlock().getNumStmt(); i++) {
824              if (!(getBlock().getStmt(i) instanceof Case)) {
825                return false;
826              }
827            }
828            return true;
829          }
830      }
831      /**
832       * @attribute syn
833       * @aspect UnreachableStatements
834       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:109
835       */
836      @ASTNodeAnnotation.Attribute
837      public boolean noStmtsAfterLastLabel() {
838        boolean noStmtsAfterLastLabel_value = getBlock().getNumStmt() > 0
839              && getBlock().getStmt(getBlock().getNumStmt()-1) instanceof Case;
840    
841        return noStmtsAfterLastLabel_value;
842      }
843      /**
844       * @attribute syn
845       * @aspect UnreachableStatements
846       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:113
847       */
848      @ASTNodeAnnotation.Attribute
849      public boolean noDefaultLabel() {
850        {
851            for (int i = 0; i < getBlock().getNumStmt(); i++) {
852              if (getBlock().getStmt(i) instanceof DefaultCase) {
853                return false;
854              }
855            }
856            return true;
857          }
858      }
859      /**
860       * @apilevel internal
861       */
862      protected boolean canCompleteNormally_computed = false;
863      /**
864       * @apilevel internal
865       */
866      protected boolean canCompleteNormally_value;
867      /**
868       * @apilevel internal
869       */
870      private void canCompleteNormally_reset() {
871        canCompleteNormally_computed = false;
872      }
873      /**
874       * @attribute syn
875       * @aspect UnreachableStatements
876       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:53
877       */
878      @ASTNodeAnnotation.Attribute
879      public boolean canCompleteNormally() {
880        ASTNode$State state = state();
881        if (canCompleteNormally_computed) {
882          return canCompleteNormally_value;
883        }
884        boolean intermediate = state.INTERMEDIATE_VALUE;
885        state.INTERMEDIATE_VALUE = false;
886        int num = state.boundariesCrossed;
887        boolean isFinal = this.is$Final();
888        canCompleteNormally_value = lastStmtCanCompleteNormally() || noStmts()
889              || noStmtsAfterLastLabel()
890              || noDefaultLabel() || reachableBreak();
891        if (isFinal && num == state().boundariesCrossed) {
892          canCompleteNormally_computed = true;
893        } else {
894        }
895        state.INTERMEDIATE_VALUE |= intermediate;
896    
897        return canCompleteNormally_value;
898      }
899      /**
900       * @apilevel internal
901       */
902      protected boolean defaultCase_computed = false;
903      /**
904       * @apilevel internal
905       */
906      protected DefaultCase defaultCase_value;
907      /**
908       * @apilevel internal
909       */
910      private void defaultCase_reset() {
911        defaultCase_computed = false;
912        defaultCase_value = null;
913      }
914      /**
915       * @attribute syn
916       * @aspect CreateBCode
917       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1397
918       */
919      @ASTNodeAnnotation.Attribute
920      public DefaultCase defaultCase() {
921        ASTNode$State state = state();
922        if (defaultCase_computed) {
923          return defaultCase_value;
924        }
925        boolean intermediate = state.INTERMEDIATE_VALUE;
926        state.INTERMEDIATE_VALUE = false;
927        int num = state.boundariesCrossed;
928        boolean isFinal = this.is$Final();
929        defaultCase_value = defaultCase_compute();
930        if (isFinal && num == state().boundariesCrossed) {
931          defaultCase_computed = true;
932        } else {
933        }
934        state.INTERMEDIATE_VALUE |= intermediate;
935    
936        return defaultCase_value;
937      }
938      /**
939       * @apilevel internal
940       */
941      private DefaultCase defaultCase_compute() {
942          for (int i= 0; i < getBlock().getNumStmt(); i++) {
943            if (getBlock().getStmt(i) instanceof DefaultCase) {
944              return (DefaultCase) getBlock().getStmt(i);
945            }
946          }
947          return null;
948        }
949      /**
950       * @apilevel internal
951       */
952      protected boolean end_label_computed = false;
953      /**
954       * @apilevel internal
955       */
956      protected int end_label_value;
957      /**
958       * @apilevel internal
959       */
960      private void end_label_reset() {
961        end_label_computed = false;
962      }
963      /**
964       * @attribute syn
965       * @aspect CreateBCode
966       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1406
967       */
968      @ASTNodeAnnotation.Attribute
969      public int end_label() {
970        ASTNode$State state = state();
971        if (end_label_computed) {
972          return end_label_value;
973        }
974        boolean intermediate = state.INTERMEDIATE_VALUE;
975        state.INTERMEDIATE_VALUE = false;
976        int num = state.boundariesCrossed;
977        boolean isFinal = this.is$Final();
978        end_label_value = hostType().constantPool().newLabel();
979        if (isFinal && num == state().boundariesCrossed) {
980          end_label_computed = true;
981        } else {
982        }
983        state.INTERMEDIATE_VALUE |= intermediate;
984    
985        return end_label_value;
986      }
987      /**
988       * @attribute syn
989       * @aspect CreateBCode
990       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1494
991       */
992      @ASTNodeAnnotation.Attribute
993      public int numCase() {
994        {
995            int result = 0;
996            for (int i = 0; i < getBlock().getNumStmt(); i++) {
997              if (getBlock().getStmt(i) instanceof Case) {
998                result++;
999              }
1000            }
1001            return result;
1002          }
1003      }
1004      /**
1005       * @attribute syn
1006       * @aspect CreateBCode
1007       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1621
1008       */
1009      @ASTNodeAnnotation.Attribute
1010      public int break_label() {
1011        int break_label_value = end_label();
1012    
1013        return break_label_value;
1014      }
1015      /**
1016       * @attribute syn
1017       * @aspect PreciseRethrow
1018       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:84
1019       */
1020      @ASTNodeAnnotation.Attribute
1021      public boolean modifiedInScope(Variable var) {
1022        boolean modifiedInScope_Variable_value = getBlock().modifiedInScope(var);
1023    
1024        return modifiedInScope_Variable_value;
1025      }
1026      /**
1027       * @attribute syn
1028       * @aspect StringsInSwitch
1029       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:42
1030       */
1031      @ASTNodeAnnotation.Attribute
1032      public boolean isSwitchWithString() {
1033        boolean isSwitchWithString_value = getExpr().type().isString();
1034    
1035        return isSwitchWithString_value;
1036      }
1037      /**
1038       * Local index for the first switch variable.
1039       * @attribute syn
1040       * @aspect StringsInSwitch
1041       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:56
1042       */
1043      @ASTNodeAnnotation.Attribute
1044      public int localNumA() {
1045        int localNumA_value = localNum();
1046    
1047        return localNumA_value;
1048      }
1049      /**
1050       * Local index for the second switch variable.
1051       * @attribute syn
1052       * @aspect StringsInSwitch
1053       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:61
1054       */
1055      @ASTNodeAnnotation.Attribute
1056      public int localNumB() {
1057        int localNumB_value = localNum() + typeInt().variableSize();
1058    
1059        return localNumB_value;
1060      }
1061      /**
1062       * Utility method to compute offsets between labels.
1063       * @attribute syn
1064       * @aspect StringsInSwitch
1065       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:116
1066       */
1067      @ASTNodeAnnotation.Attribute
1068      public int labelOffset(CodeGeneration gen, int lbl1, int lbl2) {
1069        int labelOffset_CodeGeneration_int_int_value = gen.addressOf(lbl1) - gen.addressOf(lbl2);
1070    
1071        return labelOffset_CodeGeneration_int_int_value;
1072      }
1073      /**
1074       * @attribute inh
1075       * @aspect SpecialClasses
1076       * @declaredat /home/jesper/git/extendj/java4/frontend/LookupType.jrag:86
1077       */
1078      /**
1079       * @attribute inh
1080       * @aspect SpecialClasses
1081       * @declaredat /home/jesper/git/extendj/java4/frontend/LookupType.jrag:86
1082       */
1083      @ASTNodeAnnotation.Attribute
1084      public TypeDecl typeInt() {
1085        ASTNode$State state = state();
1086        if (typeInt_computed) {
1087          return typeInt_value;
1088        }
1089        boolean intermediate = state.INTERMEDIATE_VALUE;
1090        state.INTERMEDIATE_VALUE = false;
1091        int num = state.boundariesCrossed;
1092        boolean isFinal = this.is$Final();
1093        typeInt_value = getParent().Define_typeInt(this, null);
1094        if (isFinal && num == state().boundariesCrossed) {
1095          typeInt_computed = true;
1096        } else {
1097        }
1098        state.INTERMEDIATE_VALUE |= intermediate;
1099    
1100        return typeInt_value;
1101      }
1102      /**
1103       * @apilevel internal
1104       */
1105      protected boolean typeInt_computed = false;
1106      /**
1107       * @apilevel internal
1108       */
1109      protected TypeDecl typeInt_value;
1110      /**
1111       * @apilevel internal
1112       */
1113      private void typeInt_reset() {
1114        typeInt_computed = false;
1115        typeInt_value = null;
1116      }
1117      /**
1118       * @attribute inh
1119       * @aspect SpecialClasses
1120       * @declaredat /home/jesper/git/extendj/java4/frontend/LookupType.jrag:88
1121       */
1122      /**
1123       * @attribute inh
1124       * @aspect SpecialClasses
1125       * @declaredat /home/jesper/git/extendj/java4/frontend/LookupType.jrag:88
1126       */
1127      @ASTNodeAnnotation.Attribute
1128      public TypeDecl typeLong() {
1129        ASTNode$State state = state();
1130        if (typeLong_computed) {
1131          return typeLong_value;
1132        }
1133        boolean intermediate = state.INTERMEDIATE_VALUE;
1134        state.INTERMEDIATE_VALUE = false;
1135        int num = state.boundariesCrossed;
1136        boolean isFinal = this.is$Final();
1137        typeLong_value = getParent().Define_typeLong(this, null);
1138        if (isFinal && num == state().boundariesCrossed) {
1139          typeLong_computed = true;
1140        } else {
1141        }
1142        state.INTERMEDIATE_VALUE |= intermediate;
1143    
1144        return typeLong_value;
1145      }
1146      /**
1147       * @apilevel internal
1148       */
1149      protected boolean typeLong_computed = false;
1150      /**
1151       * @apilevel internal
1152       */
1153      protected TypeDecl typeLong_value;
1154      /**
1155       * @apilevel internal
1156       */
1157      private void typeLong_reset() {
1158        typeLong_computed = false;
1159        typeLong_value = null;
1160      }
1161      /**
1162       * @attribute inh
1163       * @aspect StringsInSwitch
1164       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:45
1165       */
1166      /**
1167       * @attribute inh
1168       * @aspect StringsInSwitch
1169       * @declaredat /home/jesper/git/extendj/java7/backend/StringsInSwitch.jrag:45
1170       */
1171      @ASTNodeAnnotation.Attribute
1172      public TypeDecl typeString() {
1173        TypeDecl typeString_value = getParent().Define_typeString(this, null);
1174    
1175        return typeString_value;
1176      }
1177      /**
1178       * @declaredat /home/jesper/git/extendj/java4/frontend/BranchTarget.jrag:227
1179       * @apilevel internal
1180       */
1181      public Stmt Define_branchTarget(ASTNode caller, ASTNode child, Stmt branch) {
1182        int childIndex = this.getIndexOfChild(caller);
1183        return branch.canBranchTo(this) ? this : branchTarget(branch);
1184      }
1185      protected boolean canDefine_branchTarget(ASTNode caller, ASTNode child, Stmt branch) {
1186        return true;
1187      }
1188      /**
1189       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:255
1190       * @apilevel internal
1191       */
1192      public boolean Define_isDAbefore(ASTNode caller, ASTNode child, Variable v) {
1193        if (caller == getBlockNoTransform()) {
1194          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:637
1195          return getExpr().isDAafter(v);
1196        }
1197        else if (caller == getExprNoTransform()) {
1198          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:619
1199          {
1200              if (((ASTNode) v).isDescendantTo(this)) {
1201                return false;
1202              }
1203              boolean result = isDAbefore(v);
1204              return result;
1205            }
1206        }
1207        else {
1208          return getParent().Define_isDAbefore(this, caller, v);
1209        }
1210      }
1211      protected boolean canDefine_isDAbefore(ASTNode caller, ASTNode child, Variable v) {
1212        return true;
1213      }
1214      /**
1215       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:779
1216       * @apilevel internal
1217       */
1218      public boolean Define_isDUbefore(ASTNode caller, ASTNode child, Variable v) {
1219        if (caller == getBlockNoTransform()) {
1220          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1185
1221          return getExpr().isDUafter(v);
1222        }
1223        else if (caller == getExprNoTransform()) {
1224          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1184
1225          return isDUbefore(v);
1226        }
1227        else {
1228          return getParent().Define_isDUbefore(this, caller, v);
1229        }
1230      }
1231      protected boolean canDefine_isDUbefore(ASTNode caller, ASTNode child, Variable v) {
1232        return true;
1233      }
1234      /**
1235       * @declaredat /home/jesper/git/extendj/java4/frontend/NameCheck.jrag:449
1236       * @apilevel internal
1237       */
1238      public boolean Define_insideSwitch(ASTNode caller, ASTNode child) {
1239        if (caller == getBlockNoTransform()) {
1240          // @declaredat /home/jesper/git/extendj/java4/frontend/NameCheck.jrag:452
1241          return true;
1242        }
1243        else {
1244          return getParent().Define_insideSwitch(this, caller);
1245        }
1246      }
1247      protected boolean canDefine_insideSwitch(ASTNode caller, ASTNode child) {
1248        return true;
1249      }
1250      /**
1251       * @declaredat /home/jesper/git/extendj/java4/frontend/NameCheck.jrag:496
1252       * @apilevel internal
1253       */
1254      public Case Define_bind(ASTNode caller, ASTNode child, Case c) {
1255        if (caller == getBlockNoTransform()) {
1256          // @declaredat /home/jesper/git/extendj/java4/frontend/NameCheck.jrag:497
1257          {
1258              Block b = getBlock();
1259              for (int i = 0; i < b.getNumStmt(); i++) {
1260                if (b.getStmt(i) instanceof Case && ((Case) b.getStmt(i)).constValue(c)) {
1261                  return (Case) b.getStmt(i);
1262                }
1263              }
1264              return null;
1265            }
1266        }
1267        else {
1268          return getParent().Define_bind(this, caller, c);
1269        }
1270      }
1271      protected boolean canDefine_bind(ASTNode caller, ASTNode child, Case c) {
1272        return true;
1273      }
1274      /**
1275       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:420
1276       * @apilevel internal
1277       */
1278      public TypeDecl Define_switchType(ASTNode caller, ASTNode child) {
1279        if (caller == getBlockNoTransform()) {
1280          // @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:421
1281          return getExpr().type();
1282        }
1283        else {
1284          return getParent().Define_switchType(this, caller);
1285        }
1286      }
1287      protected boolean canDefine_switchType(ASTNode caller, ASTNode child) {
1288        return true;
1289      }
1290      /**
1291       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:52
1292       * @apilevel internal
1293       */
1294      public boolean Define_reachable(ASTNode caller, ASTNode child) {
1295        if (caller == getBlockNoTransform()) {
1296          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:127
1297          return reachable();
1298        }
1299        else {
1300          return getParent().Define_reachable(this, caller);
1301        }
1302      }
1303      protected boolean canDefine_reachable(ASTNode caller, ASTNode child) {
1304        return true;
1305      }
1306      /**
1307       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:283
1308       * @apilevel internal
1309       */
1310      public boolean Define_reportUnreachable(ASTNode caller, ASTNode child) {
1311        if (caller == getBlockNoTransform()) {
1312          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:220
1313          return reachable();
1314        }
1315        else {
1316          return getParent().Define_reportUnreachable(this, caller);
1317        }
1318      }
1319      protected boolean canDefine_reportUnreachable(ASTNode caller, ASTNode child) {
1320        return true;
1321      }
1322      /**
1323       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:64
1324       * @apilevel internal
1325       */
1326      public int Define_localNum(ASTNode caller, ASTNode child) {
1327        int childIndex = this.getIndexOfChild(caller);
1328        return localNum() + typeInt().variableSize() + typeString().variableSize();
1329      }
1330      protected boolean canDefine_localNum(ASTNode caller, ASTNode child) {
1331        return true;
1332      }
1333      /**
1334       * @apilevel internal
1335       */
1336      public ASTNode rewriteTo() {
1337        return super.rewriteTo();
1338      }
1339    }