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