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    }