001 /* Copyright (c) 2013, Jesper Öqvist <jesper.oqvist@cs.lth.se> 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 aspect NTAFinally { 032 /** 033 * @return a copy of the block as an NTAFinallyBlock 034 */ 035 protected static NTAFinallyBlock ASTNode.ntaFinallyBlock(FinallyHost origin, Stmt branch, Block block) { 036 NTAFinallyBlock ntaBlock = new NTAFinallyBlock(origin); 037 ntaBlock.addStmt((Block) block.treeCopyNoTransform()); 038 /*if (!block.canCompleteNormally()) { 039 * // the target block's exit will replace our own exit code 040 * // so we can just goto that block! 041 * ntaBlock.addGoto(block); 042 * } else ... 043 */ 044 if (block.canCompleteNormally()) { 045 FinallyHost enclosing = block.enclosingFinally(branch); 046 if (enclosing != null) { 047 ntaBlock.addStmt(ntaFinallyBlock(enclosing, branch, enclosing.getFinallyBlock())); 048 } 049 } 050 return ntaBlock; 051 } 052 053 syn lazy Opt<Block> BreakStmt.getFinallyOpt() { 054 return branchFinallyOpt(); 055 } 056 057 syn lazy Opt<Block> ContinueStmt.getFinallyOpt() { 058 return branchFinallyOpt(); 059 } 060 061 syn lazy Opt<Block> ReturnStmt.getFinallyOpt() { 062 return branchFinallyOpt(); 063 } 064 065 /** 066 * Copy of the finally block for catch-all exception handling. 067 */ 068 syn lazy Block TryStmt.getExceptionHandler() { 069 if (hasNonEmptyFinally()) { 070 NTAFinallyBlock ntaBlock = new NTAFinallyBlock(this); 071 ntaBlock.addStmt((Block) getFinally().treeCopyNoTransform()); 072 return ntaBlock; 073 } else { 074 return new NTAFinallyBlock(); 075 } 076 } 077 078 /** 079 * @return An Opt node containing the finally and monitor exit blocks 080 * from the list of enclosing try-statements and synchronized blocks. 081 */ 082 public Opt<Block> Stmt.branchFinallyOpt() { 083 FinallyHost enclosing = enclosingFinally(this); 084 if (enclosing != null) { 085 return new Opt<Block>(ntaFinallyBlock(enclosing, this, enclosing.getFinallyBlock())); 086 } else { 087 return new Opt<Block>(); 088 } 089 } 090 091 private FinallyHost NTAFinallyBlock.origin; 092 093 public NTAFinallyBlock.NTAFinallyBlock(FinallyHost finallyHost) { 094 this.origin = finallyHost; 095 } 096 }