001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * 2013, Jesper Öqvist <jesper.oqvist@cs.lth.se> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions are met: 007 * 008 * 1. Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * 2. Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * 3. Neither the name of the copyright holder nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 029 * POSSIBILITY OF SUCH DAMAGE. 030 */ 031 032 aspect LocalNum { 033 /** 034 * Computes size required for local variables of this statement. 035 * NB: only relevant for variable declaration statements. 036 * @return local size for declared variables 037 */ 038 syn lazy int Stmt.localSize() = 0; 039 040 eq VarDeclStmt.localSize() { 041 int size = 0; 042 for (VariableDeclaration decl: getSingleDeclList()) { 043 size += decl.localSize(); 044 } 045 return size; 046 } 047 048 syn lazy int VariableDeclaration.localSize() = type().variableSize(); 049 050 inh lazy int VariableDeclaration.localNum(); 051 052 eq VarDeclStmt.getSingleDecl(int index).localNum() { 053 if (index == 0) { 054 return localNum(); 055 } else { 056 return getSingleDecl(index-1).localNum() + getSingleDecl(index-1).localSize(); 057 } 058 } 059 060 /** 061 * @return The next available local variable index. 062 */ 063 inh lazy int Stmt.localNum(); 064 065 inh lazy int ParameterDeclaration.localNum(); 066 067 eq Program.getChild(int index).localNum() = 0; 068 069 syn lazy int MethodDecl.offsetBeforeParameters() = isStatic() ? 0 : 1; 070 071 syn lazy int MethodDecl.offsetAfterParameters() { 072 if (getNumParameter() == 0) { 073 return offsetBeforeParameters(); 074 } else { 075 ParameterDeclaration last = getParameter(getNumParameter()-1); 076 return last.localNum() + last.type().variableSize(); 077 } 078 } 079 080 eq MethodDecl.getParameter(int index).localNum() { 081 if (index == 0) { 082 return offsetBeforeParameters(); 083 } else { 084 ParameterDeclaration last = getParameter(index-1); 085 return last.localNum() + last.type().variableSize(); 086 } 087 } 088 089 eq InstanceInitializer.getBlock().localNum() { 090 int localNum = 1; 091 for (Iterator iter = hostType().constructors().iterator(); iter.hasNext(); ) { 092 ConstructorDecl c = (ConstructorDecl)iter.next(); 093 int num = c.offsetAfterParameters(); 094 if (num > localNum) { 095 localNum = num; 096 } 097 } 098 return localNum; 099 } 100 101 inh lazy int ReturnStmt.resultSaveLocalNum(); 102 eq MethodDecl.getBlock().resultSaveLocalNum() = offsetAfterParameters(); 103 eq Program.getChild().resultSaveLocalNum() { 104 throw new Error("Unsupported operation resultSaveLocalNum"); 105 } 106 107 syn lazy int MethodDecl.resultOffset() = type().isVoid() ? 0 : type().variableSize(); 108 109 eq MethodDecl.getBlock().localNum() = offsetAfterParameters() + resultOffset(); 110 111 syn lazy int ConstructorDecl.offsetBeforeParameters() { 112 int i = 1; 113 if (hostType().needsEnclosing()) { 114 i++; 115 } 116 if (hostType().needsSuperEnclosing()) { 117 i++; 118 } 119 return i; 120 } 121 122 syn lazy int ConstructorDecl.offsetFirstEnclosingVariable() { 123 int localIndex = offsetBeforeParameters(); 124 Collection vars = hostType().enclosingVariables(); 125 if (vars.isEmpty()) { 126 return localIndex; 127 } 128 String name = "val$" + ((Variable)vars.iterator().next()).name(); 129 for (int i = 0; !getParameter(i).name().equals(name); i++) { 130 localIndex += getParameter(i).type().variableSize(); 131 } 132 return localIndex; 133 } 134 135 syn int ConstructorDecl.localIndexOfEnclosingVariable(Variable v) { 136 int localIndex = offsetFirstEnclosingVariable(); 137 Iterator iter = hostType().enclosingVariables().iterator(); 138 Variable varDecl = (Variable)iter.next(); 139 while(varDecl != v && iter.hasNext()) { 140 localIndex += varDecl.type().variableSize(); 141 varDecl = (Variable)iter.next(); 142 } 143 return localIndex; 144 } 145 146 syn lazy int ConstructorDecl.offsetAfterParameters() { 147 if (getNumParameter() == 0) { 148 return offsetBeforeParameters(); 149 } else { 150 ParameterDeclaration last = getParameter(getNumParameter()-1); 151 return last.localNum() + last.type().variableSize(); 152 } 153 } 154 155 eq ConstructorDecl.getParameter(int index).localNum() { 156 if (index == 0) { 157 return offsetBeforeParameters(); 158 } else { 159 ParameterDeclaration last = getParameter(index-1); 160 return last.localNum() + last.type().variableSize(); 161 } 162 } 163 164 eq ConstructorDecl.getBlock().localNum() = offsetAfterParameters(); 165 166 eq ForStmt.getStmt().localNum() { 167 if (getNumInitStmt() == 0) { 168 return localNum(); 169 } else { 170 Stmt last = getInitStmt(getNumInitStmt()-1); 171 return last.localNum() + last.localSize(); 172 } 173 } 174 175 eq ForStmt.getInitStmt(int index).localNum() { 176 if (index == 0) { 177 return localNum(); 178 } else { 179 return getInitStmt(index-1).localNum() + getInitStmt(index-1).localSize(); 180 } 181 } 182 183 eq Block.getStmt(int index).localNum() { 184 if (index == 0) { 185 return localNum(); 186 } else { 187 return getStmt(index-1).localNum() + getStmt(index-1).localSize(); 188 } 189 } 190 191 eq TryStmt.getChild().localNum() = localNum(); 192 eq TryStmt.getFinally().localNum() = localNum(); 193 eq TryStmt.getExceptionHandler().localNum() = localNum() + 1;// leave room for throwable stored by exceptionHandler 194 195 eq BasicCatch.getBlock().localNum() = getParameter().localNum() + getParameter().type().variableSize(); 196 197 eq SynchronizedStmt.getBlock().localNum() = localNum() + 3; 198 199 syn int TypeDecl.variableSize() = 0; 200 eq ReferenceType.variableSize() = 1; 201 eq PrimitiveType.variableSize() = 1; 202 eq LongType.variableSize() = 2; 203 eq DoubleType.variableSize() = 2; 204 eq NullType.variableSize() = 1; 205 } 206