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/java7/grammar/BasicTWR.ast:1 027 * @production BasicTWR : {@link Stmt} ::= <span class="component">Resource:{@link ResourceDeclaration}</span> <span class="component">{@link Block}</span>; 028 029 */ 030 public class BasicTWR extends Stmt implements Cloneable, VariableScope { 031 /** 032 * The general structure of the basic try-with-resources: 033 * 034 * <pre><code> 035 * RESOURCE 036 * BLOCK 037 * 038 * Primary Exception Handler 039 * Automatic Closing of Resource 040 * Suppressed Exception Handler 041 * re-throw primary exception 042 * Automatic Closing of Resource 043 * </pre></code> 044 * 045 * Pseudocode for basic try-with-resources: 046 * 047 * <pre><code> 048 * 0 .resourceBegin 049 * 1 emit RESOURCE 050 * 0 store resource 051 * 0 .resourceEnd 052 * 053 * 0 .blockBegin 054 * 0 emit BLOCK 055 * 0 .blockEnd 056 * 0 goto outerFinally 057 * 058 * 1 .resourceException 059 * 1 throw 060 * 061 * #if BLOCK is not empty: 062 * 063 * 1 .catchPrimary 064 * 0 store primary 065 * 066 * 0 .tryCloseBegin 067 * 1 load resource 068 * 0 ifnull innerFinally 069 * 1 load resource 070 * 0 invoke java.lang.AutoCloseable.close() 071 * 0 .tryCloseEnd 072 * 073 * 0 goto innerFinally 074 * 075 * 1 .catchSuppressed 076 * 0 store suppressed 077 * 1 load primary 078 * 2 load suppressed 079 * 0 invoke java.lang.Throwable.addSuppressed(Throwable) 080 * 081 * 0 .innerFinally 082 * 1 load primary 083 * 1 throw 084 * 085 * #endif BLOCK is not empty 086 * 087 * 0 .outerFinally 088 * 1 load resource 089 * 0 ifnull tryEnd 090 * 1 load resource 091 * 0 invoke java.lang.AutoCloseable.close() 092 * 093 * 0 .tryEnd 094 * 095 * Exception Table: 096 * resourceBegin .. resourceEnd : resourceException 097 * blockBegin .. blockEnd : catchPrimary 098 * tryCloseBegin .. tryCloseEnd : catchSuppressed 099 * </pre></code> 100 * 101 * @aspect TryWithResources 102 * @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:157 103 */ 104 public void createBCode(CodeGeneration gen) { 105 ResourceDeclaration resource = getResource(); 106 107 int resourceBeginLbl = gen.constantPool().newLabel(); 108 int resourceEndLbl = gen.constantPool().newLabel(); 109 int blockBeginLbl = gen.constantPool().newLabel(); 110 int blockEndLbl = gen.constantPool().newLabel(); 111 int tryCloseBeginLbl = gen.constantPool().newLabel(); 112 int tryCloseEndLbl = gen.constantPool().newLabel(); 113 114 int resourceExceptionLbl = gen.constantPool().newLabel(); 115 int catchPrimaryLbl = gen.constantPool().newLabel(); 116 int catchSuppressedLbl = gen.constantPool().newLabel(); 117 int innerFinallyLbl = gen.constantPool().newLabel(); 118 int outerFinallyLbl = gen.constantPool().newLabel(); 119 int tryEndLbl = gen.constantPool().newLabel(); 120 121 TypeDecl throwableType = lookupType("java.lang", "Throwable"); 122 TypeDecl resourceType = resource.type(); 123 TypeDecl autoCloseableType = lookupType("java.lang", "AutoCloseable"); 124 125 gen.changeStackDepth(3); 126 int resourceIndex = resource.localNum(); 127 int primaryIndex = resourceIndex+resourceType.variableSize(); 128 int suppressedIndex = primaryIndex+throwableType.variableSize(); 129 130 // store the resource in local 131 gen.addLabel(resourceBeginLbl); 132 resource.createBCode(gen); 133 gen.addLabel(resourceEndLbl); 134 gen.emit(Bytecode.NOP); 135 136 gen.addLabel(blockBeginLbl); 137 getBlock().createBCode(gen); 138 gen.addLabel(blockEndLbl); 139 gen.emitGoto(outerFinallyLbl); 140 141 // If there was an exception when initializing the resource 142 // we need to directly rethrow the exception 143 gen.addLabel(resourceExceptionLbl); 144 gen.emitThrow(); 145 gen.addException( 146 resourceBeginLbl, 147 resourceEndLbl, 148 resourceExceptionLbl, 149 CodeGeneration.ExceptionEntry.CATCH_ALL); 150 151 if (gen.addressOf(blockBeginLbl) != gen.addressOf(blockEndLbl)) { 152 153 // catch primary exception 154 // operand stack: .., #primary 155 gen.addLabel(catchPrimaryLbl); 156 throwableType.emitStoreLocal(gen, primaryIndex); 157 158 // try-close resource 159 gen.addLabel(tryCloseBeginLbl); 160 { 161 // if resource != null 162 resourceType.emitLoadLocal(gen, resourceIndex); 163 gen.emitCompare(Bytecode.IFNULL, innerFinallyLbl); 164 resourceType.emitLoadLocal(gen, resourceIndex); 165 closeMethod().emitInvokeMethod(gen, autoCloseableType); 166 } 167 gen.addLabel(tryCloseEndLbl); 168 gen.emitGoto(innerFinallyLbl); 169 170 // catch suppressed exception 171 // operand stack: .., #primary, #suppressed 172 gen.addLabel(catchSuppressedLbl); 173 throwableType.emitStoreLocal(gen, suppressedIndex); 174 throwableType.emitLoadLocal(gen, primaryIndex); 175 throwableType.emitLoadLocal(gen, suppressedIndex); 176 addSuppressedMethod().emitInvokeMethod(gen, throwableType); 177 178 // inner finally 179 // operand stack: .., #primary 180 gen.addLabel(innerFinallyLbl); 181 throwableType.emitLoadLocal(gen, primaryIndex); 182 gen.emitThrow(); 183 184 // If there was an exception during the block of the try 185 // statement, then we should try to close the resource 186 gen.addException( 187 blockBeginLbl, 188 blockEndLbl, 189 catchPrimaryLbl, 190 CodeGeneration.ExceptionEntry.CATCH_ALL); 191 192 // If an exception occurrs during the automatic closing 193 // of a resource after an exception in the try block... 194 gen.addException( 195 tryCloseBeginLbl, 196 tryCloseEndLbl, 197 catchSuppressedLbl, 198 CodeGeneration.ExceptionEntry.CATCH_ALL); 199 } 200 201 // outer finally 202 gen.addLabel(outerFinallyLbl); 203 { 204 // if resource != null 205 resourceType.emitLoadLocal(gen, resourceIndex); 206 gen.emitCompare(Bytecode.IFNULL, tryEndLbl); 207 resourceType.emitLoadLocal(gen, resourceIndex); 208 closeMethod().emitInvokeMethod(gen, autoCloseableType); 209 } 210 211 gen.addLabel(tryEndLbl); 212 gen.emit(Bytecode.NOP); 213 } 214 /** 215 * Lookup the java.lang.Throwable.close() method. 216 * @aspect TryWithResources 217 * @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:271 218 */ 219 private MethodDecl closeMethod() { 220 TypeDecl autoCloseableType = lookupType("java.lang", "AutoCloseable"); 221 if (autoCloseableType.isUnknown()) { 222 throw new Error("Could not find java.lang.AutoCloseable"); 223 } 224 for (MethodDecl method : (Collection<MethodDecl>) 225 autoCloseableType.memberMethods("close")) { 226 if (method.getNumParameter() == 0) { 227 return method; 228 } 229 } 230 throw new Error("Could not find java.lang.AutoCloseable.close()"); 231 } 232 /** 233 * Lookup the java.lang.Throwable.addSuppressed(Throwable) method. 234 * @aspect TryWithResources 235 * @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:288 236 */ 237 private MethodDecl addSuppressedMethod() { 238 TypeDecl throwableType = lookupType("java.lang", "Throwable"); 239 if (throwableType.isUnknown()) { 240 throw new Error("Could not find java.lang.Throwable"); 241 } 242 for (MethodDecl method : (Collection<MethodDecl>) 243 throwableType.memberMethods("addSuppressed")) { 244 if (method.getNumParameter() == 1 && 245 method.getParameter(0).getTypeAccess().type() == throwableType) { 246 return method; 247 } 248 } 249 throw new Error("Could not find java.lang.Throwable.addSuppressed()"); 250 } 251 /** 252 * @declaredat ASTNode:1 253 */ 254 public BasicTWR() { 255 super(); 256 } 257 /** 258 * Initializes the child array to the correct size. 259 * Initializes List and Opt nta children. 260 * @apilevel internal 261 * @ast method 262 * @declaredat ASTNode:10 263 */ 264 public void init$Children() { 265 children = new ASTNode[2]; 266 } 267 /** 268 * @declaredat ASTNode:13 269 */ 270 public BasicTWR(ResourceDeclaration p0, Block p1) { 271 setChild(p0, 0); 272 setChild(p1, 1); 273 } 274 /** 275 * @apilevel low-level 276 * @declaredat ASTNode:20 277 */ 278 protected int numChildren() { 279 return 2; 280 } 281 /** 282 * @apilevel internal 283 * @declaredat ASTNode:26 284 */ 285 public boolean mayHaveRewrite() { 286 return false; 287 } 288 /** 289 * @apilevel internal 290 * @declaredat ASTNode:32 291 */ 292 public void flushAttrCache() { 293 super.flushAttrCache(); 294 localLookup_String_reset(); 295 localVariableDeclaration_String_reset(); 296 lookupVariable_String_reset(); 297 } 298 /** 299 * @apilevel internal 300 * @declaredat ASTNode:41 301 */ 302 public void flushCollectionCache() { 303 super.flushCollectionCache(); 304 } 305 /** 306 * @apilevel internal 307 * @declaredat ASTNode:47 308 */ 309 public void flushRewriteCache() { 310 super.flushRewriteCache(); 311 } 312 /** 313 * @apilevel internal 314 * @declaredat ASTNode:53 315 */ 316 public BasicTWR clone() throws CloneNotSupportedException { 317 BasicTWR node = (BasicTWR) super.clone(); 318 return node; 319 } 320 /** 321 * @apilevel internal 322 * @declaredat ASTNode:60 323 */ 324 public BasicTWR copy() { 325 try { 326 BasicTWR node = (BasicTWR) clone(); 327 node.parent = null; 328 if (children != null) { 329 node.children = (ASTNode[]) children.clone(); 330 } 331 return node; 332 } catch (CloneNotSupportedException e) { 333 throw new Error("Error: clone not supported for " + getClass().getName()); 334 } 335 } 336 /** 337 * Create a deep copy of the AST subtree at this node. 338 * The copy is dangling, i.e. has no parent. 339 * @return dangling copy of the subtree at this node 340 * @apilevel low-level 341 * @deprecated Please use treeCopy or treeCopyNoTransform instead 342 * @declaredat ASTNode:79 343 */ 344 @Deprecated 345 public BasicTWR fullCopy() { 346 return treeCopyNoTransform(); 347 } 348 /** 349 * Create a deep copy of the AST subtree at this node. 350 * The copy is dangling, i.e. has no parent. 351 * @return dangling copy of the subtree at this node 352 * @apilevel low-level 353 * @declaredat ASTNode:89 354 */ 355 public BasicTWR treeCopyNoTransform() { 356 BasicTWR tree = (BasicTWR) copy(); 357 if (children != null) { 358 for (int i = 0; i < children.length; ++i) { 359 ASTNode child = (ASTNode) children[i]; 360 if (child != null) { 361 child = child.treeCopyNoTransform(); 362 tree.setChild(child, i); 363 } 364 } 365 } 366 return tree; 367 } 368 /** 369 * Create a deep copy of the AST subtree at this node. 370 * The subtree of this node is traversed to trigger rewrites before copy. 371 * The copy is dangling, i.e. has no parent. 372 * @return dangling copy of the subtree at this node 373 * @apilevel low-level 374 * @declaredat ASTNode:109 375 */ 376 public BasicTWR treeCopy() { 377 doFullTraversal(); 378 return treeCopyNoTransform(); 379 } 380 /** 381 * @apilevel internal 382 * @declaredat ASTNode:116 383 */ 384 protected boolean is$Equal(ASTNode node) { 385 return super.is$Equal(node); 386 } 387 /** 388 * Replaces the Resource child. 389 * @param node The new node to replace the Resource child. 390 * @apilevel high-level 391 */ 392 public void setResource(ResourceDeclaration node) { 393 setChild(node, 0); 394 } 395 /** 396 * Retrieves the Resource child. 397 * @return The current node used as the Resource child. 398 * @apilevel high-level 399 */ 400 @ASTNodeAnnotation.Child(name="Resource") 401 public ResourceDeclaration getResource() { 402 return (ResourceDeclaration) getChild(0); 403 } 404 /** 405 * Retrieves the Resource child. 406 * <p><em>This method does not invoke AST transformations.</em></p> 407 * @return The current node used as the Resource child. 408 * @apilevel low-level 409 */ 410 public ResourceDeclaration getResourceNoTransform() { 411 return (ResourceDeclaration) getChildNoTransform(0); 412 } 413 /** 414 * Replaces the Block child. 415 * @param node The new node to replace the Block child. 416 * @apilevel high-level 417 */ 418 public void setBlock(Block node) { 419 setChild(node, 1); 420 } 421 /** 422 * Retrieves the Block child. 423 * @return The current node used as the Block child. 424 * @apilevel high-level 425 */ 426 @ASTNodeAnnotation.Child(name="Block") 427 public Block getBlock() { 428 return (Block) getChild(1); 429 } 430 /** 431 * Retrieves the Block child. 432 * <p><em>This method does not invoke AST transformations.</em></p> 433 * @return The current node used as the Block child. 434 * @apilevel low-level 435 */ 436 public Block getBlockNoTransform() { 437 return (Block) getChildNoTransform(1); 438 } 439 /** 440 * @apilevel internal 441 */ 442 protected java.util.Map localLookup_String_values; 443 /** 444 * @apilevel internal 445 */ 446 private void localLookup_String_reset() { 447 localLookup_String_values = null; 448 } 449 /** 450 * @attribute syn 451 * @aspect MultiCatch 452 * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:100 453 */ 454 @ASTNodeAnnotation.Attribute 455 public SimpleSet localLookup(String name) { 456 Object _parameters = name; 457 if (localLookup_String_values == null) localLookup_String_values = new org.jastadd.util.RobustMap(new java.util.HashMap()); 458 ASTNode$State state = state(); 459 if (localLookup_String_values.containsKey(_parameters)) { 460 return (SimpleSet) localLookup_String_values.get(_parameters); 461 } 462 boolean intermediate = state.INTERMEDIATE_VALUE; 463 state.INTERMEDIATE_VALUE = false; 464 int num = state.boundariesCrossed; 465 boolean isFinal = this.is$Final(); 466 SimpleSet localLookup_String_value = localLookup_compute(name); 467 if (isFinal && num == state().boundariesCrossed) { 468 localLookup_String_values.put(_parameters, localLookup_String_value); 469 } else { 470 } 471 state.INTERMEDIATE_VALUE |= intermediate; 472 473 return localLookup_String_value; 474 } 475 /** 476 * @apilevel internal 477 */ 478 private SimpleSet localLookup_compute(String name) { 479 VariableDeclaration v = localVariableDeclaration(name); 480 if (v != null) { 481 return v; 482 } 483 return lookupVariable(name); 484 } 485 /** 486 * @apilevel internal 487 */ 488 protected java.util.Map localVariableDeclaration_String_values; 489 /** 490 * @apilevel internal 491 */ 492 private void localVariableDeclaration_String_reset() { 493 localVariableDeclaration_String_values = null; 494 } 495 /** 496 * @attribute syn 497 * @aspect MultiCatch 498 * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:107 499 */ 500 @ASTNodeAnnotation.Attribute 501 public VariableDeclaration localVariableDeclaration(String name) { 502 Object _parameters = name; 503 if (localVariableDeclaration_String_values == null) localVariableDeclaration_String_values = new org.jastadd.util.RobustMap(new java.util.HashMap()); 504 ASTNode$State state = state(); 505 if (localVariableDeclaration_String_values.containsKey(_parameters)) { 506 return (VariableDeclaration) localVariableDeclaration_String_values.get(_parameters); 507 } 508 boolean intermediate = state.INTERMEDIATE_VALUE; 509 state.INTERMEDIATE_VALUE = false; 510 int num = state.boundariesCrossed; 511 boolean isFinal = this.is$Final(); 512 VariableDeclaration localVariableDeclaration_String_value = getResource().declaresVariable(name) ? getResource() : null; 513 if (isFinal && num == state().boundariesCrossed) { 514 localVariableDeclaration_String_values.put(_parameters, localVariableDeclaration_String_value); 515 } else { 516 } 517 state.INTERMEDIATE_VALUE |= intermediate; 518 519 return localVariableDeclaration_String_value; 520 } 521 /** 522 * @attribute syn 523 * @aspect PreciseRethrow 524 * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:84 525 */ 526 @ASTNodeAnnotation.Attribute 527 public boolean modifiedInScope(Variable var) { 528 boolean modifiedInScope_Variable_value = getBlock().modifiedInScope(var); 529 530 return modifiedInScope_Variable_value; 531 } 532 /** 533 * @attribute inh 534 * @aspect MultiCatch 535 * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:111 536 */ 537 /** 538 * @attribute inh 539 * @aspect MultiCatch 540 * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:111 541 */ 542 @ASTNodeAnnotation.Attribute 543 public SimpleSet lookupVariable(String name) { 544 Object _parameters = name; 545 if (lookupVariable_String_values == null) lookupVariable_String_values = new org.jastadd.util.RobustMap(new java.util.HashMap()); 546 ASTNode$State state = state(); 547 if (lookupVariable_String_values.containsKey(_parameters)) { 548 return (SimpleSet) lookupVariable_String_values.get(_parameters); 549 } 550 boolean intermediate = state.INTERMEDIATE_VALUE; 551 state.INTERMEDIATE_VALUE = false; 552 int num = state.boundariesCrossed; 553 boolean isFinal = this.is$Final(); 554 SimpleSet lookupVariable_String_value = getParent().Define_lookupVariable(this, null, name); 555 if (isFinal && num == state().boundariesCrossed) { 556 lookupVariable_String_values.put(_parameters, lookupVariable_String_value); 557 } else { 558 } 559 state.INTERMEDIATE_VALUE |= intermediate; 560 561 return lookupVariable_String_value; 562 } 563 /** 564 * @apilevel internal 565 */ 566 protected java.util.Map lookupVariable_String_values; 567 /** 568 * @apilevel internal 569 */ 570 private void lookupVariable_String_reset() { 571 lookupVariable_String_values = null; 572 } 573 /** 574 * @declaredat /home/jesper/git/extendj/java8/frontend/LookupVariable.jrag:30 575 * @apilevel internal 576 */ 577 public SimpleSet Define_lookupVariable(ASTNode caller, ASTNode child, String name) { 578 if (caller == getBlockNoTransform()) { 579 // @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:99 580 return localLookup(name); 581 } 582 else { 583 return getParent().Define_lookupVariable(this, caller, name); 584 } 585 } 586 protected boolean canDefine_lookupVariable(ASTNode caller, ASTNode child, String name) { 587 return true; 588 } 589 /** 590 * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:64 591 * @apilevel internal 592 */ 593 public int Define_localNum(ASTNode caller, ASTNode child) { 594 if (caller == getBlockNoTransform()) { 595 // @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:315 596 return getResource().localNum() 597 + getResource().type().variableSize() 598 + 2 * lookupType("java.lang", "Throwable").variableSize(); 599 } 600 else if (caller == getResourceNoTransform()) { 601 // @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:306 602 return localNum(); 603 } 604 else { 605 return getParent().Define_localNum(this, caller); 606 } 607 } 608 protected boolean canDefine_localNum(ASTNode caller, ASTNode child) { 609 return true; 610 } 611 /** 612 * @apilevel internal 613 */ 614 public ASTNode rewriteTo() { 615 return super.rewriteTo(); 616 } 617 }