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 }