001    /* Copyright (c) 2011, 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 MultiCatch {
032    
033      /**
034       * The Multi-Catch clause has two or more exception table entries
035       * which all point to the same exception handler.
036       */
037      public void MultiCatch.exceptionTableEntries(CodeGeneration gen, int begin_lbl, int end_lbl) {
038        for (int i = 0; i < getParameter().getNumTypeAccess(); ++i) {
039          TypeDecl type = getParameter().getTypeAccess(i).type();
040    
041          gen.addException(
042            begin_lbl,
043            end_lbl,
044            label(),
045            gen.constantPool().addClass(type.constantPoolName())
046            );
047        }
048      }
049    
050      /**
051       * Code gen.
052       */
053      public void MultiCatch.createBCode(CodeGeneration gen) {
054        gen.addLabel(label());
055        // add 1 to stack depth
056        gen.changeStackDepth(1);
057        getParameter().type().emitStoreLocal(gen, localNum());
058        getBlock().createBCode(gen);
059      }
060    
061      /**
062       * Local number used to store the exception parameter.
063       */
064      inh lazy int CatchParameterDeclaration.localNum();
065      inh lazy int MultiCatch.localNum();
066    
067      eq MultiCatch.getBlock().localNum() = localNum() + getParameter().type().variableSize();
068      eq MultiCatch.getParameter().localNum() = localNum();
069    
070      refine GenericsCodegen
071      public void VarAccess.createAssignLoadDest(CodeGeneration gen) {
072        Variable v = decl();
073        if (v instanceof CatchParameterDeclaration) {
074          if (v.isInstanceVariable()) {
075            gen.emitDup();
076          }
077          CatchParameterDeclaration decl = (CatchParameterDeclaration) v;
078          decl.type().emitLoadLocal(gen, decl.localNum());
079        } else {
080          refined(gen);
081        }
082      }
083    
084      refine GenericsCodegen
085      public void VarAccess.createBCode(CodeGeneration gen) {
086        Variable v = decl();
087        if (v instanceof CatchParameterDeclaration) {
088          CatchParameterDeclaration decl = (CatchParameterDeclaration) v;
089          if (decl.hostType() == hostType()) {
090            decl.type().emitLoadLocal(gen, decl.localNum());
091          } else {
092            emitLoadLocalInNestedClass(gen, decl);
093          }
094        } else {
095          refined(gen);
096        }
097      }
098    
099      eq BasicTWR.getBlock().lookupVariable(String name) = localLookup(name);
100      syn lazy SimpleSet BasicTWR.localLookup(String name) {
101        VariableDeclaration v = localVariableDeclaration(name);
102        if (v != null) {
103          return v;
104        }
105        return lookupVariable(name);
106      }
107      syn lazy VariableDeclaration BasicTWR.localVariableDeclaration(String name) =
108          getResource().declaresVariable(name) ? getResource() : null;
109    
110      BasicTWR implements VariableScope;
111      inh lazy SimpleSet BasicTWR.lookupVariable(String name);
112    }