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 }