001 /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com> 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 * * Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * * Redistributions in binary form must reproduce the above copyright 010 * notice, this list of conditions and the following disclaimer in the 011 * documentation and/or other materials provided with the distribution. 012 * * Neither the name of the Lund University nor the names of its 013 * contributors may be used to endorse or promote products derived from 014 * this software without specific prior written permission. 015 * 016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 026 * POSSIBILITY OF SUCH DAMAGE. 027 */ 028 029 aspect TargetType { 030 inh lazy TypeDecl Expr.targetType(); 031 032 eq Program.getChild().targetType() = typeNull(); 033 034 eq ConditionalExpr.getTrueExpr().targetType() = targetType(); 035 eq ConditionalExpr.getFalseExpr().targetType() = targetType(); 036 eq AbstractDot.getRight().targetType() = targetType(); 037 eq ParExpr.getExpr().targetType() = targetType(); 038 eq AssignExpr.getSource().targetType() = getDest().type(); 039 eq VariableDeclaration.getInit().targetType() = getTypeAccess().type(); 040 eq FieldDeclaration.getInit().targetType() = getTypeAccess().type(); 041 eq ReturnStmt.getResult().targetType() = returnType(); 042 eq CastExpr.getExpr().targetType() = type(); 043 044 eq AddExpr.getLeftOperand().targetType() { 045 if (getLeftOperand().stringContext()) { 046 return getRightOperand().type(); 047 } else if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) { 048 return type(); 049 } else { 050 return targetType(); 051 } 052 } 053 eq AddExpr.getRightOperand().targetType() { 054 if (getRightOperand().stringContext()) { 055 return getLeftOperand().type(); 056 } else if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) { 057 return type(); 058 } else { 059 return targetType(); 060 } 061 } 062 063 eq ArithmeticExpr.getLeftOperand().targetType() { 064 if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) { 065 return type(); 066 } else { 067 return targetType(); 068 } 069 } 070 071 eq ArithmeticExpr.getRightOperand().targetType() { 072 if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) { 073 return type(); 074 } else { 075 return targetType(); 076 } 077 } 078 079 eq ArrayInit.getInit().targetType() { 080 if (!(targetType() instanceof ArrayDecl)) { 081 return targetType(); 082 } else { 083 return ((ArrayDecl) targetType()).componentType(); 084 } 085 } 086 087 eq MethodAccess.getArg(int i).targetType() { 088 MethodDecl decl = decl(); 089 if (decl.unknownMethod() == decl) { 090 return decl.type().unknownType(); 091 } 092 093 if (decl.isVariableArity() && i >= decl.arity() - 1) { 094 return decl.getParameter(decl.arity() - 1).type().componentType(); 095 } else { 096 return decl.getParameter(i).type(); 097 } 098 } 099 100 eq ConstructorAccess.getArg(int i).targetType() { 101 ConstructorDecl decl = decl(); 102 if (unknownConstructor() == decl) { 103 return decl.type().unknownType(); 104 } 105 106 if (decl.isVariableArity() && i >= decl.arity() - 1) { 107 return decl.getParameter(decl.arity() - 1).type().componentType(); 108 } else { 109 return decl.getParameter(i).type(); 110 } 111 } 112 113 eq ClassInstanceExpr.getArg(int i).targetType() { 114 ConstructorDecl decl = decl(); 115 if (unknownConstructor() == decl) { 116 return decl.type().unknownType(); 117 } 118 119 if (decl.isVariableArity() && i >= decl.arity() - 1) { 120 return decl.getParameter(decl.arity() - 1).type().componentType(); 121 } else { 122 return decl.getParameter(i).type(); 123 } 124 } 125 126 eq ExprLambdaBody.getExpr().targetType() { 127 TypeDecl decl = enclosingLambda().targetType(); 128 if (decl.isNull()) { 129 return unknownType(); 130 } else if (!(decl instanceof InterfaceDecl)) { 131 return unknownType(); 132 } else { 133 InterfaceDecl iDecl = (InterfaceDecl)decl; 134 if (!iDecl.isFunctional()) { 135 return unknownType(); 136 } else { 137 return iDecl.functionDescriptor().method.type(); 138 } 139 } 140 } 141 142 syn lazy InterfaceDecl LambdaExpr.targetInterface() { 143 if (targetType().isNull()) { 144 return null; 145 } else if (!(targetType() instanceof InterfaceDecl)) { 146 return null; 147 } else { 148 return (InterfaceDecl)targetType(); 149 } 150 } 151 152 syn lazy InterfaceDecl MethodReference.targetInterface() { 153 if (targetType().isNull()) { 154 return null; 155 } else if (!(targetType() instanceof InterfaceDecl)) { 156 return null; 157 } else { 158 return (InterfaceDecl) targetType(); 159 } 160 } 161 162 syn lazy InterfaceDecl ConstructorReference.targetInterface() { 163 if (targetType().isNull()) { 164 return null; 165 } else if (!(targetType() instanceof InterfaceDecl)) { 166 return null; 167 } else { 168 return (InterfaceDecl)targetType(); 169 } 170 } 171 172 173 // This is required for type inference to work with method references 174 syn lazy TypeDecl MethodReferenceAccess.assignConvertedType() = 175 targetDescriptor.method.type(); 176 177 syn lazy TypeDecl ParMethodReferenceAccess.assignConvertedType() = 178 targetDescriptor.method.type(); 179 180 // Required for diamond type inference to work 181 eq ClassInstanceExpr.getAccess().assignConvertedType() = targetType(); 182 183 syn lazy TypeDecl ConstructorReferenceAccess.targetType() = 184 targetDescriptor.method.type(); 185 186 syn lazy TypeDecl ParConstructorReferenceAccess.targetType() = 187 targetDescriptor.method.type(); 188 189 eq ConstructorReferenceAccess.getAccess().targetType() = 190 targetDescriptor.method.type(); 191 } 192 193 194 aspect Contexts { 195 // Ch 5 196 inh lazy boolean Expr.assignmentContext(); 197 inh lazy boolean Expr.invocationContext(); 198 inh lazy boolean Expr.castContext(); 199 inh lazy boolean Expr.stringContext(); 200 inh lazy boolean Expr.numericContext(); 201 202 eq CompilationUnit.getChild().assignmentContext() = false; 203 eq CompilationUnit.getChild().invocationContext() = false; 204 eq CompilationUnit.getChild().castContext() = false; 205 eq CompilationUnit.getChild().stringContext() = false; 206 eq CompilationUnit.getChild().numericContext() = false; 207 208 eq ExprLambdaBody.getExpr().assignmentContext() = true; 209 eq ExprLambdaBody.getExpr().invocationContext() = false; 210 eq ExprLambdaBody.getExpr().castContext() = false; 211 eq ExprLambdaBody.getExpr().stringContext() = false; 212 eq ExprLambdaBody.getExpr().numericContext() = false; 213 214 eq BlockLambdaBody.getBlock().assignmentContext() = false; 215 eq BlockLambdaBody.getBlock().invocationContext() = false; 216 eq BlockLambdaBody.getBlock().castContext() = false; 217 eq BlockLambdaBody.getBlock().stringContext() = false; 218 eq BlockLambdaBody.getBlock().numericContext() = false; 219 220 eq Binary.getChild().assignmentContext() = false; 221 eq Binary.getChild().invocationContext() = false; 222 eq Binary.getChild().castContext() = false; 223 eq Binary.getChild().stringContext() = false; 224 eq Binary.getChild().numericContext() = false; 225 226 eq AddExpr.getLeftOperand().stringContext() { 227 if (!getRightOperand().isPolyExpression() && !getLeftOperand().isPolyExpression()) { 228 if (getRightOperand().type().isString() && !getLeftOperand().type().isString()) { 229 return true; 230 } 231 } 232 return false; 233 } 234 eq AddExpr.getRightOperand().stringContext() { 235 if (!getRightOperand().isPolyExpression() && !getLeftOperand().isPolyExpression()) { 236 if (getLeftOperand().type().isString() && !getRightOperand().type().isString()) { 237 return true; 238 } 239 } 240 return false; 241 } 242 243 eq ArithmeticExpr.getRightOperand().numericContext() = true; 244 eq ArithmeticExpr.getLeftOperand().numericContext() = true; 245 246 eq Unary.getOperand().assignmentContext() = false; 247 eq Unary.getOperand().invocationContext() = false; 248 eq Unary.getOperand().castContext() = false; 249 eq Unary.getOperand().stringContext() = false; 250 eq Unary.getOperand().numericContext() = false; 251 252 eq InstanceOfExpr.getExpr().assignmentContext() = false; 253 eq InstanceOfExpr.getExpr().invocationContext() = false; 254 eq InstanceOfExpr.getExpr().castContext() = false; 255 eq InstanceOfExpr.getExpr().stringContext() = false; 256 eq InstanceOfExpr.getExpr().numericContext() = false; 257 258 eq ConditionalExpr.getCondition().assignmentContext() = false; 259 eq ConditionalExpr.getCondition().invocationContext() = false; 260 eq ConditionalExpr.getCondition().castContext() = false; 261 eq ConditionalExpr.getCondition().numericContext() = false; 262 eq ConditionalExpr.getCondition().stringContext() = false; 263 264 265 eq ConditionalExpr.getTrueExpr().assignmentContext() = 266 isPolyExpression() ? assignmentContext() : false; 267 eq ConditionalExpr.getTrueExpr().invocationContext() = 268 isPolyExpression() ? invocationContext() : false; 269 // 15.25.3 270 eq ConditionalExpr.getTrueExpr().castContext() = false; 271 eq ConditionalExpr.getTrueExpr().stringContext() = false; 272 eq ConditionalExpr.getTrueExpr().numericContext() = false; 273 eq ConditionalExpr.getFalseExpr().assignmentContext() = 274 isPolyExpression() ? assignmentContext() : false; 275 eq ConditionalExpr.getFalseExpr().invocationContext() = 276 isPolyExpression() ? invocationContext() : false; 277 // 15.25.3 278 eq ConditionalExpr.getFalseExpr().castContext() = false; 279 eq ConditionalExpr.getFalseExpr().stringContext() = false; 280 eq ConditionalExpr.getFalseExpr().numericContext() = false; 281 282 eq ArrayAccess.getExpr().assignmentContext() = false; 283 eq ArrayAccess.getExpr().invocationContext() = false; 284 eq ArrayAccess.getExpr().castContext() = false; 285 eq ArrayAccess.getExpr().stringContext() = false; 286 eq ArrayAccess.getExpr().numericContext() = false; 287 288 eq AbstractDot.getRight().assignmentContext() = assignmentContext(); 289 eq AbstractDot.getRight().invocationContext() = invocationContext(); 290 eq AbstractDot.getRight().castContext() = castContext(); 291 eq AbstractDot.getRight().stringContext() = stringContext(); 292 eq AbstractDot.getRight().numericContext() = numericContext(); 293 294 eq AbstractDot.getLeft().assignmentContext() = false; 295 eq AbstractDot.getLeft().invocationContext() = false; 296 eq AbstractDot.getLeft().castContext() = false; 297 eq AbstractDot.getLeft().stringContext() = false; 298 eq AbstractDot.getLeft().numericContext() = false; 299 300 // 15.8.5 301 eq ParExpr.getExpr().assignmentContext() = assignmentContext(); 302 eq ParExpr.getExpr().invocationContext() = invocationContext(); 303 eq ParExpr.getExpr().castContext() = castContext(); 304 eq ParExpr.getExpr().stringContext() = stringContext(); 305 eq ParExpr.getExpr().numericContext() = numericContext(); 306 307 eq CastExpr.getExpr().assignmentContext() = false; 308 eq CastExpr.getExpr().invocationContext() = false; 309 eq CastExpr.getExpr().castContext() = true; 310 eq CastExpr.getExpr().stringContext() = false; 311 eq CastExpr.getExpr().numericContext() = false; 312 313 eq AssignExpr.getDest().assignmentContext() = false; 314 eq AssignExpr.getDest().invocationContext() = false; 315 eq AssignExpr.getDest().castContext() = false; 316 eq AssignExpr.getDest().numericContext() = false; 317 eq AssignExpr.getDest().stringContext() = false; 318 319 eq AssignExpr.getSource().assignmentContext() = true; 320 eq AssignExpr.getSource().invocationContext() = false; 321 eq AssignExpr.getSource().castContext() = false; 322 eq AssignExpr.getSource().stringContext() = false; 323 eq AssignExpr.getSource().numericContext() = false; 324 325 eq ClassInstanceExpr.getArg().assignmentContext() = false; 326 eq ClassInstanceExpr.getArg().invocationContext() = true; 327 eq ClassInstanceExpr.getArg().castContext() = false; 328 eq ClassInstanceExpr.getArg().stringContext() = false; 329 eq ClassInstanceExpr.getArg().numericContext() = false; 330 331 eq MethodAccess.getArg().assignmentContext() = false; 332 eq MethodAccess.getArg().invocationContext() = true; 333 eq MethodAccess.getArg().castContext() = false; 334 eq MethodAccess.getArg().stringContext() = false; 335 eq MethodAccess.getArg().numericContext() = false; 336 337 eq ConstructorAccess.getArg().assignmentContext() = false; 338 eq ConstructorAccess.getArg().invocationContext() = true; 339 eq ConstructorAccess.getArg().castContext() = false; 340 eq ConstructorAccess.getArg().stringContext() = false; 341 eq ConstructorAccess.getArg().numericContext() = false; 342 343 eq ArrayInit.getInit().assignmentContext() = true; 344 eq ArrayInit.getInit().invocationContext() = false; 345 eq ArrayInit.getInit().castContext() = false; 346 eq ArrayInit.getInit().stringContext() = false; 347 eq ArrayInit.getInit().numericContext() = false; 348 349 eq VariableDeclaration.getInit().assignmentContext() = true; 350 eq VariableDeclaration.getInit().invocationContext() = false; 351 eq VariableDeclaration.getInit().castContext() = false; 352 eq VariableDeclaration.getInit().numericContext() = false; 353 eq VariableDeclaration.getInit().stringContext() = false; 354 355 eq ReturnStmt.getResult().assignmentContext() = true; 356 eq ReturnStmt.getResult().invocationContext() = false; 357 eq ReturnStmt.getResult().castContext() = false; 358 eq ReturnStmt.getResult().stringContext() = false; 359 eq ReturnStmt.getResult().numericContext() = false; 360 361 eq VariableDecl.getInit().assignmentContext() = true; 362 eq VariableDecl.getInit().invocationContext() = false; 363 eq VariableDecl.getInit().castContext() = false; 364 eq VariableDecl.getInit().stringContext() = false; 365 eq VariableDecl.getInit().numericContext() = false; 366 367 eq ArrayTypeWithSizeAccess.getExpr().assignmentContext() = false; 368 eq ArrayTypeWithSizeAccess.getExpr().invocationContext() = false; 369 eq ArrayTypeWithSizeAccess.getExpr().castContext() = false; 370 eq ArrayTypeWithSizeAccess.getExpr().stringContext() = false; 371 eq ArrayTypeWithSizeAccess.getExpr().numericContext() = false; 372 373 eq FieldDeclaration.getInit().assignmentContext() = true; 374 eq FieldDeclaration.getInit().invocationContext() = false; 375 eq FieldDeclaration.getInit().castContext() = false; 376 eq FieldDeclaration.getInit().stringContext() = false; 377 eq FieldDeclaration.getInit().numericContext() = false; 378 379 eq Dims.getExpr().assignmentContext() = false; 380 eq Dims.getExpr().invocationContext() = false; 381 eq Dims.getExpr().castContext() = false; 382 eq Dims.getExpr().stringContext() = false; 383 eq Dims.getExpr().numericContext() = false; 384 385 eq ExprMethodReference.getExpr().assignmentContext() = false; 386 eq ExprMethodReference.getExpr().invocationContext() = false; 387 eq ExprMethodReference.getExpr().castContext() = false; 388 eq ExprMethodReference.getExpr().stringContext() = false; 389 eq ExprMethodReference.getExpr().numericContext() = false; 390 391 eq TypeMethodReference.getTypeAccess().assignmentContext() = false; 392 eq TypeMethodReference.getTypeAccess().invocationContext() = false; 393 eq TypeMethodReference.getTypeAccess().castContext() = false; 394 eq TypeMethodReference.getTypeAccess().stringContext() = false; 395 eq TypeMethodReference.getTypeAccess().numericContext() = false; 396 397 eq ConstructorReference.getTypeAccess().assignmentContext() = false; 398 eq ConstructorReference.getTypeAccess().invocationContext() = false; 399 eq ConstructorReference.getTypeAccess().castContext() = false; 400 eq ConstructorReference.getTypeAccess().stringContext() = false; 401 eq ConstructorReference.getTypeAccess().numericContext() = false; 402 } 403