001 /* Copyright (c) 2005-2008, Torbjorn Ekman 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 ConstantExpression { 032 syn Constant Expr.constant() { 033 throw new UnsupportedOperationException("ConstantExpression operation constant" 034 + " not supported for type " + getClass().getName()); 035 } 036 // enable caching for Literal constants 037 syn lazy Constant Literal.constant() { 038 throw new UnsupportedOperationException("ConstantExpression operation constant" 039 + " not supported for type " + getClass().getName()); 040 } 041 042 eq VarAccess.constant() = type().cast(decl().getInit().constant()); 043 eq AbstractDot.constant() = lastAccess().constant(); 044 eq CastExpr.constant() = type().cast(getExpr().constant()); 045 eq ParExpr.constant() = getExpr().constant(); 046 047 eq PlusExpr.constant() = type().plus(getOperand().constant()); 048 eq MinusExpr.constant() = type().minus(getOperand().constant()); 049 eq BitNotExpr.constant() = type().bitNot(getOperand().constant()); 050 051 eq MulExpr.constant() = type().mul(getLeftOperand().constant(), getRightOperand().constant()); 052 eq DivExpr.constant() = type().div(getLeftOperand().constant(), getRightOperand().constant()); 053 eq ModExpr.constant() = type().mod(getLeftOperand().constant(), getRightOperand().constant()); 054 055 eq AddExpr.constant() = type().add(getLeftOperand().constant(), getRightOperand().constant()); 056 eq SubExpr.constant() = type().sub(getLeftOperand().constant(), getRightOperand().constant()); 057 058 eq LShiftExpr.constant() = type().lshift(getLeftOperand().constant(), getRightOperand().constant()); 059 eq RShiftExpr.constant() = type().rshift(getLeftOperand().constant(), getRightOperand().constant()); 060 eq URShiftExpr.constant() = type().urshift(getLeftOperand().constant(), getRightOperand().constant()); 061 062 eq AndBitwiseExpr.constant() = type().andBitwise(getLeftOperand().constant(), getRightOperand().constant()); 063 eq XorBitwiseExpr.constant() = type().xorBitwise(getLeftOperand().constant(), getRightOperand().constant()); 064 eq OrBitwiseExpr.constant() = type().orBitwise(getLeftOperand().constant(), getRightOperand().constant()); 065 066 syn lazy Constant ConditionalExpr.constant() = type().questionColon(getCondition().constant(), getTrueExpr().constant(),getFalseExpr().constant()); 067 068 eq BooleanLiteral.constant() = Constant.create(Boolean.valueOf(getLITERAL()).booleanValue()); 069 eq CharacterLiteral.constant() = Constant.create(getLITERAL().charAt(0)); 070 eq StringLiteral.constant() = Constant.create(getLITERAL()); 071 072 syn Constant TypeDecl.cast(Constant c) { 073 throw new UnsupportedOperationException("ConstantExpression operation cast" 074 + " not supported for type " + getClass().getName()); 075 } 076 eq IntegralType.cast(Constant c)= Constant.create(c.intValue()); 077 eq ShortType.cast(Constant c) = Constant.create((short) c.intValue()); 078 eq CharType.cast(Constant c) = Constant.create((char) c.intValue()); 079 eq ByteType.cast(Constant c) = Constant.create((byte) c.intValue()); 080 eq LongType.cast(Constant c) = Constant.create(c.longValue()); 081 eq FloatType.cast(Constant c) = Constant.create(c.floatValue()); 082 eq DoubleType.cast(Constant c) = Constant.create(c.doubleValue()); 083 eq BooleanType.cast(Constant c) = Constant.create(c.booleanValue()); 084 eq ClassDecl.cast(Constant c) = Constant.create(c.stringValue()); 085 086 syn Constant TypeDecl.plus(Constant c) { 087 throw new UnsupportedOperationException("ConstantExpression operation plus" 088 + " not supported for type " + getClass().getName()); 089 } 090 eq IntegralType.plus(Constant c) = c; 091 eq LongType.plus(Constant c) = c; 092 eq FloatType.plus(Constant c) = c; 093 eq DoubleType.plus(Constant c) = c; 094 095 syn Constant TypeDecl.minus(Constant c) { 096 throw new UnsupportedOperationException("ConstantExpression operation minus" 097 + " not supported for type " + getClass().getName()); 098 } 099 eq IntegralType.minus(Constant c) = Constant.create(-c.intValue()); 100 eq LongType.minus(Constant c) = Constant.create(-c.longValue()); 101 eq FloatType.minus(Constant c) = Constant.create(-c.floatValue()); 102 eq DoubleType.minus(Constant c) = Constant.create(-c.doubleValue()); 103 104 syn Constant TypeDecl.bitNot(Constant c) { 105 throw new UnsupportedOperationException("ConstantExpression operation bitNot" 106 + " not supported for type " + getClass().getName()); 107 } 108 eq IntegralType.bitNot(Constant c) = Constant.create(~c.intValue()); 109 eq LongType.bitNot(Constant c) = Constant.create(~c.longValue()); 110 111 syn Constant TypeDecl.mul(Constant c1, Constant c2) { 112 throw new UnsupportedOperationException("ConstantExpression operation mul" 113 + " not supported for type " + getClass().getName()); 114 } 115 eq IntegralType.mul(Constant c1, Constant c2) = Constant.create(c1.intValue() * c2.intValue()); 116 eq LongType.mul(Constant c1, Constant c2) = Constant.create(c1.longValue() * c2.longValue()); 117 eq FloatType.mul(Constant c1, Constant c2) = Constant.create(c1.floatValue() * c2.floatValue()); 118 eq DoubleType.mul(Constant c1, Constant c2) = Constant.create(c1.doubleValue() * c2.doubleValue()); 119 120 syn Constant TypeDecl.div(Constant c1, Constant c2) { 121 throw new UnsupportedOperationException("ConstantExpression operation div" 122 + " not supported for type " + getClass().getName()); 123 } 124 eq IntegralType.div(Constant c1, Constant c2) = Constant.create(c1.intValue() / c2.intValue()); 125 eq LongType.div(Constant c1, Constant c2) = Constant.create(c1.longValue() / c2.longValue()); 126 eq FloatType.div(Constant c1, Constant c2) = Constant.create(c1.floatValue() / c2.floatValue()); 127 eq DoubleType.div(Constant c1, Constant c2) = Constant.create(c1.doubleValue() / c2.doubleValue()); 128 129 syn Constant TypeDecl.mod(Constant c1, Constant c2) { 130 throw new UnsupportedOperationException("ConstantExpression operation mod" 131 + " not supported for type " + getClass().getName()); 132 } 133 eq IntegralType.mod(Constant c1, Constant c2) = Constant.create(c1.intValue() % c2.intValue()); 134 eq LongType.mod(Constant c1, Constant c2) = Constant.create(c1.longValue() % c2.longValue()); 135 eq FloatType.mod(Constant c1, Constant c2) = Constant.create(c1.floatValue() % c2.floatValue()); 136 eq DoubleType.mod(Constant c1, Constant c2) = Constant.create(c1.doubleValue() % c2.doubleValue()); 137 138 syn Constant TypeDecl.add(Constant c1, Constant c2) { 139 throw new UnsupportedOperationException("ConstantExpression operation add" 140 + " not supported for type " + getClass().getName()); 141 } 142 eq IntegralType.add(Constant c1, Constant c2) = Constant.create(c1.intValue() + c2.intValue()); 143 eq LongType.add(Constant c1, Constant c2) = Constant.create(c1.longValue() + c2.longValue()); 144 eq FloatType.add(Constant c1, Constant c2) = Constant.create(c1.floatValue() + c2.floatValue()); 145 eq DoubleType.add(Constant c1, Constant c2) = Constant.create(c1.doubleValue() + c2.doubleValue()); 146 eq ClassDecl.add(Constant c1, Constant c2) = Constant.create(c1.stringValue() + c2.stringValue()); 147 148 syn Constant TypeDecl.sub(Constant c1, Constant c2) { 149 throw new UnsupportedOperationException("ConstantExpression operation sub" 150 + " not supported for type " + getClass().getName()); 151 } 152 eq IntegralType.sub(Constant c1, Constant c2) = Constant.create(c1.intValue() - c2.intValue()); 153 eq LongType.sub(Constant c1, Constant c2) = Constant.create(c1.longValue() - c2.longValue()); 154 eq FloatType.sub(Constant c1, Constant c2) = Constant.create(c1.floatValue() - c2.floatValue()); 155 eq DoubleType.sub(Constant c1, Constant c2) = Constant.create(c1.doubleValue() - c2.doubleValue()); 156 157 syn Constant TypeDecl.lshift(Constant c1, Constant c2) { 158 throw new UnsupportedOperationException("ConstantExpression operation lshift" 159 + " not supported for type " + getClass().getName()); 160 } 161 eq IntegralType.lshift(Constant c1, Constant c2) = Constant.create(c1.intValue() << c2.intValue()); 162 eq LongType.lshift(Constant c1, Constant c2) = Constant.create(c1.longValue() << c2.longValue()); 163 164 syn Constant TypeDecl.rshift(Constant c1, Constant c2) { 165 throw new UnsupportedOperationException("ConstantExpression operation rshift" 166 + " not supported for type " + getClass().getName()); 167 } 168 eq IntegralType.rshift(Constant c1, Constant c2) = Constant.create(c1.intValue() >> c2.intValue()); 169 eq LongType.rshift(Constant c1, Constant c2) = Constant.create(c1.longValue() >> c2.longValue()); 170 171 syn Constant TypeDecl.urshift(Constant c1, Constant c2) { 172 throw new UnsupportedOperationException("ConstantExpression operation urshift" 173 + " not supported for type " + getClass().getName()); 174 } 175 eq IntegralType.urshift(Constant c1, Constant c2) = Constant.create(c1.intValue() >>> c2.intValue()); 176 eq LongType.urshift(Constant c1, Constant c2) = Constant.create(c1.longValue() >>> c2.longValue()); 177 178 syn Constant TypeDecl.andBitwise(Constant c1, Constant c2) { 179 throw new UnsupportedOperationException("ConstantExpression operation andBitwise" 180 + " not supported for type " + getClass().getName()); 181 } 182 eq IntegralType.andBitwise(Constant c1, Constant c2) = Constant.create(c1.intValue() & c2.intValue()); 183 eq LongType.andBitwise(Constant c1, Constant c2) = Constant.create(c1.longValue() & c2.longValue()); 184 eq BooleanType.andBitwise(Constant c1, Constant c2) = Constant.create(c1.booleanValue() & c2.booleanValue()); 185 186 syn Constant TypeDecl.xorBitwise(Constant c1, Constant c2) { 187 throw new UnsupportedOperationException("ConstantExpression operation xorBitwise" 188 + " not supported for type " + getClass().getName()); 189 } 190 eq IntegralType.xorBitwise(Constant c1, Constant c2) = Constant.create(c1.intValue() ^ c2.intValue()); 191 eq LongType.xorBitwise(Constant c1, Constant c2) = Constant.create(c1.longValue() ^ c2.longValue()); 192 eq BooleanType.xorBitwise(Constant c1, Constant c2) = Constant.create(c1.booleanValue() ^ c2.booleanValue()); 193 194 syn Constant TypeDecl.orBitwise(Constant c1, Constant c2) { 195 throw new UnsupportedOperationException("ConstantExpression operation orBitwise" 196 + " not supported for type " + getClass().getName()); 197 } 198 eq IntegralType.orBitwise(Constant c1, Constant c2) = Constant.create(c1.intValue() | c2.intValue()); 199 eq LongType.orBitwise(Constant c1, Constant c2) = Constant.create(c1.longValue() | c2.longValue()); 200 eq BooleanType.orBitwise(Constant c1, Constant c2) = Constant.create(c1.booleanValue() | c2.booleanValue()); 201 202 syn Constant TypeDecl.questionColon(Constant cond, Constant c1, Constant c2) { 203 throw new UnsupportedOperationException("ConstantExpression operation questionColon" 204 + " not supported for type " + getClass().getName()); 205 } 206 eq IntegralType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.intValue() : c2.intValue()); 207 eq LongType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.longValue() : c2.longValue()); 208 eq FloatType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.floatValue() : c2.floatValue()); 209 eq DoubleType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.doubleValue() : c2.doubleValue()); 210 eq BooleanType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.booleanValue() : c2.booleanValue()); 211 eq ClassDecl.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.stringValue() : c2.stringValue()); 212 213 /* 214 * representableIn(T) is true if and only if the the expression is a 215 * compile-time constant of type byte, char, short or int, and the value 216 * of the expression can be represented (by an expression) in the type T 217 * where T must be byte, char or short. 218 */ 219 220 syn boolean Expr.representableIn(TypeDecl t) { 221 if (!type().isByte() && !type().isChar() && !type().isShort() && !type().isInt()) { 222 return false; 223 } 224 if (t.isByte()) { 225 return constant().intValue() >= Byte.MIN_VALUE && constant().intValue() <= Byte.MAX_VALUE; 226 } 227 if (t.isChar()) { 228 return constant().intValue() >= Character.MIN_VALUE && constant().intValue() <= Character.MAX_VALUE; 229 } 230 if (t.isShort()) { 231 return constant().intValue() >= Short.MIN_VALUE && constant().intValue() <= Short.MAX_VALUE; 232 } 233 if (t.isInt()) { 234 return constant().intValue() >= Integer.MIN_VALUE && constant().intValue() <= Integer.MAX_VALUE; 235 } 236 return false; 237 } 238 239 eq ArrayInit.representableIn(TypeDecl t) { 240 for (int i = 0; i < getNumInit(); i++) { 241 if (!getInit(i).representableIn(t)) { 242 return false; 243 } 244 } 245 return true; 246 } 247 248 // isConstant() 249 250 syn boolean MemberDecl.isConstant() = false; 251 eq FieldDeclaration.isConstant() = isFinal() && hasInit() && getInit().isConstant() && (type() instanceof PrimitiveType || type().isString()); 252 253 254 syn boolean Expr.isConstant() = false; 255 eq Literal.isConstant() = true; 256 eq NullLiteral.isConstant() = false; 257 eq CastExpr.isConstant() = getExpr().isConstant() && 258 (getTypeAccess().type().isPrimitive() || getTypeAccess().type().isString()); 259 eq PlusExpr.isConstant() = getOperand().isConstant(); 260 eq MinusExpr.isConstant() = getOperand().isConstant(); 261 eq BitNotExpr.isConstant() = getOperand().isConstant(); 262 eq LogNotExpr.isConstant() = getOperand().isConstant(); 263 syn lazy boolean Binary.isConstant() circular [false] = getLeftOperand().isConstant() && getRightOperand().isConstant(); 264 eq InstanceOfExpr.isConstant() = false; 265 syn lazy boolean ConditionalExpr.isConstant() = getCondition().isConstant() && getTrueExpr().isConstant() && getFalseExpr().isConstant(); 266 eq ParExpr.isConstant() = getExpr().isConstant(); 267 eq AbstractDot.isConstant() = lastAccess().isConstant(); 268 269 eq DivExpr.isConstant() = getLeftOperand().isConstant() && getRightOperand().isConstant() && !(getRightOperand().type().isInt() && getRightOperand().constant().intValue() == 0); 270 eq ModExpr.isConstant() = getLeftOperand().isConstant() && getRightOperand().isConstant() && !(getRightOperand().type().isInt() && getRightOperand().constant().intValue() == 0); 271 272 syn lazy boolean VarAccess.isConstant() circular [false] { 273 Variable v = decl(); 274 if (v instanceof FieldDeclaration) { 275 FieldDeclaration f = (FieldDeclaration) v; 276 return f.isConstant() && (!isQualified() || (isQualified() && qualifier().isTypeAccess())); 277 } 278 boolean result = v.isFinal() && v.hasInit() && v.getInit().isConstant() && (v.type().isPrimitive() || v.type().isString()); 279 return result && (!isQualified() || (isQualified() && qualifier().isTypeAccess())); 280 } 281 282 // BooleanType is used to discard UnknownType which also responds true for isBoolean() 283 syn boolean Expr.isTrue() = isConstant() && type() instanceof BooleanType && constant().booleanValue(); 284 syn boolean Expr.isFalse() = isConstant() && type() instanceof BooleanType && !constant().booleanValue(); 285 286 eq ParExpr.isTrue() = getExpr().isTrue(); 287 eq Literal.isTrue() = false; 288 eq BooleanLiteral.isTrue() = constant().booleanValue(); 289 eq LogNotExpr.isTrue() = getOperand().isFalse(); 290 291 eq ParExpr.isFalse() = getExpr().isFalse(); 292 eq Literal.isFalse() = false; 293 eq BooleanLiteral.isFalse() = !constant().booleanValue(); 294 eq LogNotExpr.isFalse() = getOperand().isTrue(); 295 296 syn Expr Binary.left() = getLeftOperand(); 297 syn Expr Binary.right() = getRightOperand(); 298 syn TypeDecl Binary.binaryNumericPromotedType() { 299 TypeDecl leftType = left().type(); 300 TypeDecl rightType = right().type(); 301 if (leftType.isString()) { 302 return leftType; 303 } 304 if (rightType.isString()) { 305 return rightType; 306 } 307 if (leftType.isNumericType() && rightType.isNumericType()) { 308 return leftType.binaryNumericPromotion(rightType); 309 } 310 if (leftType.isBoolean() && rightType.isBoolean()) { 311 return leftType; 312 } 313 return unknownType(); 314 } 315 316 eq LogNotExpr.constant() = Constant.create(!getOperand().constant().booleanValue()); 317 eq EQExpr.constant() = Constant.create(binaryNumericPromotedType().eqIsTrue(left(), right())); 318 eq NEExpr.constant() = Constant.create(!binaryNumericPromotedType().eqIsTrue(left(), right())); 319 eq LTExpr.constant() = Constant.create(binaryNumericPromotedType().ltIsTrue(left(), right())); 320 eq LEExpr.constant() = Constant.create(binaryNumericPromotedType().leIsTrue(left(), right())); 321 eq GTExpr.constant() = Constant.create(!binaryNumericPromotedType().leIsTrue(left(), right())); 322 eq GEExpr.constant() = Constant.create(!binaryNumericPromotedType().ltIsTrue(left(), right())); 323 eq AndLogicalExpr.constant() = Constant.create(left().constant().booleanValue() && right().constant().booleanValue()); 324 eq OrLogicalExpr.constant() = Constant.create(left().constant().booleanValue() || right().constant().booleanValue()); 325 326 syn boolean TypeDecl.eqIsTrue(Expr left, Expr right) { 327 System.err.println("Evaluation eqIsTrue for unknown type: " + getClass().getName()); 328 return false; 329 } 330 eq IntegralType.eqIsTrue(Expr left, Expr right) = left.constant().intValue() == right.constant().intValue(); 331 eq LongType.eqIsTrue(Expr left, Expr right) = left.constant().longValue() == right.constant().longValue(); 332 eq FloatType.eqIsTrue(Expr left, Expr right) = left.constant().floatValue() == right.constant().floatValue(); 333 eq DoubleType.eqIsTrue(Expr left, Expr right) = left.constant().doubleValue() == right.constant().doubleValue(); 334 eq BooleanType.eqIsTrue(Expr left, Expr right) = left.isTrue() && right.isTrue() || left.isFalse() && right.isFalse(); 335 eq ClassDecl.eqIsTrue(Expr left, Expr right) = isString() && left.constant().stringValue().equals(right.constant().stringValue()); 336 337 syn boolean TypeDecl.ltIsTrue(Expr left, Expr right) = false; 338 eq IntegralType.ltIsTrue(Expr left, Expr right) = left.constant().intValue() < right.constant().intValue(); 339 eq LongType.ltIsTrue(Expr left, Expr right) = left.constant().longValue() < right.constant().longValue(); 340 eq FloatType.ltIsTrue(Expr left, Expr right) = left.constant().floatValue() < right.constant().floatValue(); 341 eq DoubleType.ltIsTrue(Expr left, Expr right) = left.constant().doubleValue() < right.constant().doubleValue(); 342 343 syn boolean TypeDecl.leIsTrue(Expr left, Expr right) = false; 344 eq IntegralType.leIsTrue(Expr left, Expr right) = left.constant().intValue() <= right.constant().intValue(); 345 eq LongType.leIsTrue(Expr left, Expr right) = left.constant().longValue() <= right.constant().longValue(); 346 eq FloatType.leIsTrue(Expr left, Expr right) = left.constant().floatValue() <= right.constant().floatValue(); 347 eq DoubleType.leIsTrue(Expr left, Expr right) = left.constant().doubleValue() <= right.constant().doubleValue(); 348 } 349