001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * 2011 Jesper Öqvist <jesper.oqvist@cs.lth.se> 008 * All rights reserved. 009 */ 010 011 aspect ConstantExpression { 012 class Constant { 013 static class ConstantInt extends Constant { 014 private int value; 015 public ConstantInt(int i) { this.value = i; } 016 int intValue() { return value; } 017 long longValue() { return value; } 018 float floatValue() { return value; } 019 double doubleValue() { return value; } 020 String stringValue() { return new Integer(value).toString(); } 021 } 022 static class ConstantLong extends Constant { 023 private long value; 024 public ConstantLong(long l) { this.value = l; } 025 int intValue() { return (int)value; } 026 long longValue() { return value; } 027 float floatValue() { return value; } 028 double doubleValue() { return value; } 029 String stringValue() { return new Long(value).toString(); } 030 } 031 static class ConstantFloat extends Constant { 032 private float value; 033 public ConstantFloat(float f) { this.value = f; } 034 int intValue() { return (int)value; } 035 long longValue() { return (long)value; } 036 float floatValue() { return value; } 037 double doubleValue() { return value; } 038 String stringValue() { return new Float(value).toString(); } 039 } 040 static class ConstantDouble extends Constant { 041 private double value; 042 public ConstantDouble(double d) { this.value = d; } 043 int intValue() { return (int)value; } 044 long longValue() { return (long)value; } 045 float floatValue() { return (float)value; } 046 double doubleValue() { return value; } 047 String stringValue() { return new Double(value).toString(); } 048 } 049 static class ConstantChar extends Constant { 050 private char value; 051 public ConstantChar(char c) { this.value = c; } 052 int intValue() { return value; } 053 long longValue() { return value; } 054 float floatValue() { return value; } 055 double doubleValue() { return value; } 056 String stringValue() { return new Character(value).toString(); } 057 } 058 static class ConstantBoolean extends Constant { 059 private boolean value; 060 public ConstantBoolean(boolean b) { this.value = b; } 061 boolean booleanValue() { return value; } 062 String stringValue() { return new Boolean(value).toString(); } 063 } 064 static class ConstantString extends Constant { 065 private String value; 066 public ConstantString(String s) { this.value = s; } 067 String stringValue() { return value; } 068 } 069 070 int intValue() { throw new UnsupportedOperationException(); } 071 long longValue() { throw new UnsupportedOperationException(); } 072 float floatValue() { throw new UnsupportedOperationException(); } 073 double doubleValue() { throw new UnsupportedOperationException(); } 074 boolean booleanValue() { throw new UnsupportedOperationException(getClass().getName()); } 075 String stringValue() { throw new UnsupportedOperationException(); } 076 077 protected Constant() { 078 } 079 080 public boolean error = false; 081 082 static Constant create(int i) { return new ConstantInt(i); } 083 static Constant create(long l) { return new ConstantLong(l); } 084 static Constant create(float f) { return new ConstantFloat(f); } 085 static Constant create(double d) { return new ConstantDouble(d); } 086 static Constant create(boolean b) { return new ConstantBoolean(b); } 087 static Constant create(char c) { return new ConstantChar(c); } 088 static Constant create(String s) { return new ConstantString(s); } 089 } 090 091 syn Constant Expr.constant() { 092 throw new UnsupportedOperationException("ConstantExpression operation constant" + 093 " not supported for type " + getClass().getName()); 094 } 095 // enable caching for Literal constants 096 syn lazy Constant Literal.constant() { 097 throw new UnsupportedOperationException("ConstantExpression operation constant" + 098 " not supported for type " + getClass().getName()); 099 } 100 101 eq VarAccess.constant() = type().cast(decl().getInit().constant()); 102 eq AbstractDot.constant() = lastAccess().constant(); 103 eq CastExpr.constant() = type().cast(getExpr().constant()); 104 eq ParExpr.constant() = getExpr().constant(); 105 106 eq PlusExpr.constant() = type().plus(getOperand().constant()); 107 eq MinusExpr.constant() = type().minus(getOperand().constant()); 108 eq BitNotExpr.constant() = type().bitNot(getOperand().constant()); 109 110 eq MulExpr.constant() = type().mul(getLeftOperand().constant(), getRightOperand().constant()); 111 eq DivExpr.constant() = type().div(getLeftOperand().constant(), getRightOperand().constant()); 112 eq ModExpr.constant() = type().mod(getLeftOperand().constant(), getRightOperand().constant()); 113 114 eq AddExpr.constant() = type().add(getLeftOperand().constant(), getRightOperand().constant()); 115 eq SubExpr.constant() = type().sub(getLeftOperand().constant(), getRightOperand().constant()); 116 117 eq LShiftExpr.constant() = type().lshift(getLeftOperand().constant(), getRightOperand().constant()); 118 eq RShiftExpr.constant() = type().rshift(getLeftOperand().constant(), getRightOperand().constant()); 119 eq URShiftExpr.constant() = type().urshift(getLeftOperand().constant(), getRightOperand().constant()); 120 121 eq AndBitwiseExpr.constant() = type().andBitwise(getLeftOperand().constant(), getRightOperand().constant()); 122 eq XorBitwiseExpr.constant() = type().xorBitwise(getLeftOperand().constant(), getRightOperand().constant()); 123 eq OrBitwiseExpr.constant() = type().orBitwise(getLeftOperand().constant(), getRightOperand().constant()); 124 125 syn lazy Constant ConditionalExpr.constant() = type().questionColon(getCondition().constant(), getTrueExpr().constant(),getFalseExpr().constant()); 126 127 /*syn lazy boolean FloatingPointLiteral.isZero() { 128 String s = getLITERAL(); 129 for(int i = 0; i < s.length(); i++) { 130 char c = s.charAt(i); 131 if(c == 'E' || c == 'e') 132 break; 133 if(Character.isDigit(c) && c != '0') { 134 return false; 135 } 136 } 137 return true; 138 } 139 syn lazy boolean DoubleLiteral.isZero() { 140 String s = getLITERAL(); 141 for(int i = 0; i < s.length(); i++) { 142 char c = s.charAt(i); 143 if(c == 'E' || c == 'e') 144 break; 145 if(Character.isDigit(c) && c != '0') { 146 return false; 147 } 148 } 149 return true; 150 }*/ 151 152 syn boolean Expr.isPositive() = false; 153 eq IntegerLiteral.isPositive() = !getLITERAL().startsWith("-"); 154 eq LongLiteral.isPositive() = !getLITERAL().startsWith("-"); 155 156 eq BooleanLiteral.constant() = Constant.create(Boolean.valueOf(getLITERAL()).booleanValue()); 157 eq CharacterLiteral.constant() = Constant.create(getLITERAL().charAt(0)); 158 eq StringLiteral.constant() = Constant.create(getLITERAL()); 159 160 syn Constant TypeDecl.cast(Constant c) { 161 throw new UnsupportedOperationException("ConstantExpression operation cast" + 162 " not supported for type " + getClass().getName()); 163 } 164 eq IntegralType.cast(Constant c)= Constant.create(c.intValue()); 165 eq ShortType.cast(Constant c) = Constant.create((short)c.intValue()); 166 eq CharType.cast(Constant c) = Constant.create((char)c.intValue()); 167 eq ByteType.cast(Constant c) = Constant.create((byte)c.intValue()); 168 eq LongType.cast(Constant c) = Constant.create(c.longValue()); 169 eq FloatType.cast(Constant c) = Constant.create(c.floatValue()); 170 eq DoubleType.cast(Constant c) = Constant.create(c.doubleValue()); 171 eq BooleanType.cast(Constant c) = Constant.create(c.booleanValue()); 172 eq ClassDecl.cast(Constant c) = Constant.create(c.stringValue()); 173 174 syn Constant TypeDecl.plus(Constant c) { 175 throw new UnsupportedOperationException("ConstantExpression operation plus" + 176 " not supported for type " + getClass().getName()); 177 } 178 eq IntegralType.plus(Constant c) = c; 179 eq LongType.plus(Constant c) = c; 180 eq FloatType.plus(Constant c) = c; 181 eq DoubleType.plus(Constant c) = c; 182 183 syn Constant TypeDecl.minus(Constant c) { 184 throw new UnsupportedOperationException("ConstantExpression operation minus" + 185 " not supported for type " + getClass().getName()); 186 } 187 eq IntegralType.minus(Constant c) = Constant.create(-c.intValue()); 188 eq LongType.minus(Constant c) = Constant.create(-c.longValue()); 189 eq FloatType.minus(Constant c) = Constant.create(-c.floatValue()); 190 eq DoubleType.minus(Constant c) = Constant.create(-c.doubleValue()); 191 192 syn Constant TypeDecl.bitNot(Constant c) { 193 throw new UnsupportedOperationException("ConstantExpression operation bitNot" + 194 " not supported for type " + getClass().getName()); 195 } 196 eq IntegralType.bitNot(Constant c) = Constant.create(~c.intValue()); 197 eq LongType.bitNot(Constant c) = Constant.create(~c.longValue()); 198 199 syn Constant TypeDecl.mul(Constant c1, Constant c2) { 200 throw new UnsupportedOperationException("ConstantExpression operation mul" + 201 " not supported for type " + getClass().getName()); 202 } 203 eq IntegralType.mul(Constant c1, Constant c2) = Constant.create(c1.intValue() * c2.intValue()); 204 eq LongType.mul(Constant c1, Constant c2) = Constant.create(c1.longValue() * c2.longValue()); 205 eq FloatType.mul(Constant c1, Constant c2) = Constant.create(c1.floatValue() * c2.floatValue()); 206 eq DoubleType.mul(Constant c1, Constant c2) = Constant.create(c1.doubleValue() * c2.doubleValue()); 207 208 syn Constant TypeDecl.div(Constant c1, Constant c2) { 209 throw new UnsupportedOperationException("ConstantExpression operation div" + 210 " not supported for type " + getClass().getName()); 211 } 212 eq IntegralType.div(Constant c1, Constant c2) = Constant.create(c1.intValue() / c2.intValue()); 213 eq LongType.div(Constant c1, Constant c2) = Constant.create(c1.longValue() / c2.longValue()); 214 eq FloatType.div(Constant c1, Constant c2) = Constant.create(c1.floatValue() / c2.floatValue()); 215 eq DoubleType.div(Constant c1, Constant c2) = Constant.create(c1.doubleValue() / c2.doubleValue()); 216 217 syn Constant TypeDecl.mod(Constant c1, Constant c2) { 218 throw new UnsupportedOperationException("ConstantExpression operation mod" + 219 " not supported for type " + getClass().getName()); 220 } 221 eq IntegralType.mod(Constant c1, Constant c2) = Constant.create(c1.intValue() % c2.intValue()); 222 eq LongType.mod(Constant c1, Constant c2) = Constant.create(c1.longValue() % c2.longValue()); 223 eq FloatType.mod(Constant c1, Constant c2) = Constant.create(c1.floatValue() % c2.floatValue()); 224 eq DoubleType.mod(Constant c1, Constant c2) = Constant.create(c1.doubleValue() % c2.doubleValue()); 225 226 syn Constant TypeDecl.add(Constant c1, Constant c2) { 227 throw new UnsupportedOperationException("ConstantExpression operation add" + 228 " not supported for type " + getClass().getName()); 229 } 230 eq IntegralType.add(Constant c1, Constant c2) = Constant.create(c1.intValue() + c2.intValue()); 231 eq LongType.add(Constant c1, Constant c2) = Constant.create(c1.longValue() + c2.longValue()); 232 eq FloatType.add(Constant c1, Constant c2) = Constant.create(c1.floatValue() + c2.floatValue()); 233 eq DoubleType.add(Constant c1, Constant c2) = Constant.create(c1.doubleValue() + c2.doubleValue()); 234 eq ClassDecl.add(Constant c1, Constant c2) = Constant.create(c1.stringValue() + c2.stringValue()); 235 236 syn Constant TypeDecl.sub(Constant c1, Constant c2) { 237 throw new UnsupportedOperationException("ConstantExpression operation sub" + 238 " not supported for type " + getClass().getName()); 239 } 240 eq IntegralType.sub(Constant c1, Constant c2) = Constant.create(c1.intValue() - c2.intValue()); 241 eq LongType.sub(Constant c1, Constant c2) = Constant.create(c1.longValue() - c2.longValue()); 242 eq FloatType.sub(Constant c1, Constant c2) = Constant.create(c1.floatValue() - c2.floatValue()); 243 eq DoubleType.sub(Constant c1, Constant c2) = Constant.create(c1.doubleValue() - c2.doubleValue()); 244 245 syn Constant TypeDecl.lshift(Constant c1, Constant c2) { 246 throw new UnsupportedOperationException("ConstantExpression operation lshift" + 247 " not supported for type " + getClass().getName()); 248 } 249 eq IntegralType.lshift(Constant c1, Constant c2) = Constant.create(c1.intValue() << c2.intValue()); 250 eq LongType.lshift(Constant c1, Constant c2) = Constant.create(c1.longValue() << c2.longValue()); 251 252 syn Constant TypeDecl.rshift(Constant c1, Constant c2) { 253 throw new UnsupportedOperationException("ConstantExpression operation rshift" + 254 " not supported for type " + getClass().getName()); 255 } 256 eq IntegralType.rshift(Constant c1, Constant c2) = Constant.create(c1.intValue() >> c2.intValue()); 257 eq LongType.rshift(Constant c1, Constant c2) = Constant.create(c1.longValue() >> c2.longValue()); 258 259 syn Constant TypeDecl.urshift(Constant c1, Constant c2) { 260 throw new UnsupportedOperationException("ConstantExpression operation urshift" + 261 " not supported for type " + getClass().getName()); 262 } 263 eq IntegralType.urshift(Constant c1, Constant c2) = Constant.create(c1.intValue() >>> c2.intValue()); 264 eq LongType.urshift(Constant c1, Constant c2) = Constant.create(c1.longValue() >>> c2.longValue()); 265 266 syn Constant TypeDecl.andBitwise(Constant c1, Constant c2) { 267 throw new UnsupportedOperationException("ConstantExpression operation andBitwise" + 268 " not supported for type " + getClass().getName()); 269 } 270 eq IntegralType.andBitwise(Constant c1, Constant c2) = Constant.create(c1.intValue() & c2.intValue()); 271 eq LongType.andBitwise(Constant c1, Constant c2) = Constant.create(c1.longValue() & c2.longValue()); 272 eq BooleanType.andBitwise(Constant c1, Constant c2) = Constant.create(c1.booleanValue() & c2.booleanValue()); 273 274 syn Constant TypeDecl.xorBitwise(Constant c1, Constant c2) { 275 throw new UnsupportedOperationException("ConstantExpression operation xorBitwise" + 276 " not supported for type " + getClass().getName()); 277 } 278 eq IntegralType.xorBitwise(Constant c1, Constant c2) = Constant.create(c1.intValue() ^ c2.intValue()); 279 eq LongType.xorBitwise(Constant c1, Constant c2) = Constant.create(c1.longValue() ^ c2.longValue()); 280 eq BooleanType.xorBitwise(Constant c1, Constant c2) = Constant.create(c1.booleanValue() ^ c2.booleanValue()); 281 282 syn Constant TypeDecl.orBitwise(Constant c1, Constant c2) { 283 throw new UnsupportedOperationException("ConstantExpression operation orBitwise" + 284 " not supported for type " + getClass().getName()); 285 } 286 eq IntegralType.orBitwise(Constant c1, Constant c2) = Constant.create(c1.intValue() | c2.intValue()); 287 eq LongType.orBitwise(Constant c1, Constant c2) = Constant.create(c1.longValue() | c2.longValue()); 288 eq BooleanType.orBitwise(Constant c1, Constant c2) = Constant.create(c1.booleanValue() | c2.booleanValue()); 289 290 syn Constant TypeDecl.questionColon(Constant cond, Constant c1, Constant c2) { 291 throw new UnsupportedOperationException("ConstantExpression operation questionColon" + 292 " not supported for type " + getClass().getName()); 293 } 294 eq IntegralType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.intValue() : c2.intValue()); 295 eq LongType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.longValue() : c2.longValue()); 296 eq FloatType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.floatValue() : c2.floatValue()); 297 eq DoubleType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.doubleValue() : c2.doubleValue()); 298 eq BooleanType.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.booleanValue() : c2.booleanValue()); 299 eq ClassDecl.questionColon(Constant cond, Constant c1, Constant c2) = Constant.create(cond.booleanValue() ? c1.stringValue() : c2.stringValue()); 300 301 /* 302 * representableIn(T) is true if and only if the the expression is a 303 * compile-time constant of type byte, char, short or int, and the value 304 * of the expression can be represented (by an expression) in the type T 305 * where T must be byte, char or short. 306 */ 307 308 syn boolean Expr.representableIn(TypeDecl t) { 309 if (!type().isByte() && !type().isChar() && !type().isShort() && !type().isInt()) { 310 return false; 311 } 312 if (t.isByte()) 313 return constant().intValue() >= Byte.MIN_VALUE && constant().intValue() <= Byte.MAX_VALUE; 314 if (t.isChar()) 315 return constant().intValue() >= Character.MIN_VALUE && constant().intValue() <= Character.MAX_VALUE; 316 if (t.isShort()) 317 return constant().intValue() >= Short.MIN_VALUE && constant().intValue() <= Short.MAX_VALUE; 318 if(t.isInt()) 319 return constant().intValue() >= Integer.MIN_VALUE && constant().intValue() <= Integer.MAX_VALUE; 320 return false; 321 } 322 323 eq ArrayInit.representableIn(TypeDecl t) { 324 for(int i = 0; i < getNumInit(); i++) 325 if(!getInit(i).representableIn(t)) 326 return false; 327 return true; 328 } 329 330 // isConstant() 331 332 syn boolean MemberDecl.isConstant() = false; 333 eq FieldDeclaration.isConstant() = isFinal() && hasInit() && getInit().isConstant() && (type() instanceof PrimitiveType || type().isString()); 334 335 336 syn boolean Expr.isConstant() = false; 337 eq Literal.isConstant() = true; 338 eq NullLiteral.isConstant() = false; 339 eq CastExpr.isConstant() = getExpr().isConstant() && 340 (getTypeAccess().type().isPrimitive() || getTypeAccess().type().isString()); 341 eq PlusExpr.isConstant() = getOperand().isConstant(); 342 eq MinusExpr.isConstant() = getOperand().isConstant(); 343 eq BitNotExpr.isConstant() = getOperand().isConstant(); 344 eq LogNotExpr.isConstant() = getOperand().isConstant(); 345 syn lazy boolean Binary.isConstant() circular [false] = getLeftOperand().isConstant() && getRightOperand().isConstant(); 346 eq InstanceOfExpr.isConstant() = false; 347 syn lazy boolean ConditionalExpr.isConstant() = getCondition().isConstant() && getTrueExpr().isConstant() && getFalseExpr().isConstant(); 348 eq ParExpr.isConstant() = getExpr().isConstant(); 349 eq AbstractDot.isConstant() = lastAccess().isConstant(); 350 351 eq DivExpr.isConstant() = getLeftOperand().isConstant() && getRightOperand().isConstant() && !(getRightOperand().type().isInt() && getRightOperand().constant().intValue() == 0); 352 eq ModExpr.isConstant() = getLeftOperand().isConstant() && getRightOperand().isConstant() && !(getRightOperand().type().isInt() && getRightOperand().constant().intValue() == 0); 353 354 syn lazy boolean VarAccess.isConstant() circular [false] { 355 Variable v = decl(); 356 if(v instanceof FieldDeclaration) { 357 FieldDeclaration f = (FieldDeclaration)v; 358 return f.isConstant() && (!isQualified() || (isQualified() && qualifier().isTypeAccess())); 359 } 360 boolean result = v.isFinal() && v.hasInit() && v.getInit().isConstant() && (v.type().isPrimitive() || v.type().isString()); 361 return result && (!isQualified() || (isQualified() && qualifier().isTypeAccess())); 362 } 363 364 // BooleanType is used to discard UnknownType which also responds true for isBoolean() 365 syn boolean Expr.isTrue() = isConstant() && type() instanceof BooleanType && constant().booleanValue(); 366 syn boolean Expr.isFalse() = isConstant() && type() instanceof BooleanType && !constant().booleanValue(); 367 368 syn Expr Binary.left() = getLeftOperand(); 369 syn Expr Binary.right() = getRightOperand(); 370 syn TypeDecl Binary.binaryNumericPromotedType() { 371 TypeDecl leftType = left().type(); 372 TypeDecl rightType = right().type(); 373 if(leftType.isString()) 374 return leftType; 375 if(rightType.isString()) 376 return rightType; 377 if(leftType.isNumericType() && rightType.isNumericType()) 378 return leftType.binaryNumericPromotion(rightType); 379 if(leftType.isBoolean() && rightType.isBoolean()) 380 return leftType; 381 return unknownType(); 382 } 383 384 eq LogNotExpr.constant() = Constant.create(!getOperand().constant().booleanValue()); 385 eq EQExpr.constant() = Constant.create(binaryNumericPromotedType().eqIsTrue(left(), right())); 386 eq NEExpr.constant() = Constant.create(!binaryNumericPromotedType().eqIsTrue(left(), right())); 387 eq LTExpr.constant() = Constant.create(binaryNumericPromotedType().ltIsTrue(left(), right())); 388 eq LEExpr.constant() = Constant.create(binaryNumericPromotedType().leIsTrue(left(), right())); 389 eq GTExpr.constant() = Constant.create(!binaryNumericPromotedType().leIsTrue(left(), right())); 390 eq GEExpr.constant() = Constant.create(!binaryNumericPromotedType().ltIsTrue(left(), right())); 391 eq AndLogicalExpr.constant() = Constant.create(left().constant().booleanValue() && right().constant().booleanValue()); 392 eq OrLogicalExpr.constant() = Constant.create(left().constant().booleanValue() || right().constant().booleanValue()); 393 394 syn boolean TypeDecl.eqIsTrue(Expr left, Expr right) { 395 System.err.println("Evaluation eqIsTrue for unknown type: " + getClass().getName()); 396 return false; 397 } 398 eq IntegralType.eqIsTrue(Expr left, Expr right) = left.constant().intValue() == right.constant().intValue(); 399 eq LongType.eqIsTrue(Expr left, Expr right) = left.constant().longValue() == right.constant().longValue(); 400 eq FloatType.eqIsTrue(Expr left, Expr right) = left.constant().floatValue() == right.constant().floatValue(); 401 eq DoubleType.eqIsTrue(Expr left, Expr right) = left.constant().doubleValue() == right.constant().doubleValue(); 402 eq BooleanType.eqIsTrue(Expr left, Expr right) = left.isTrue() && right.isTrue() || left.isFalse() && right.isFalse(); 403 eq ClassDecl.eqIsTrue(Expr left, Expr right) = isString() && left.constant().stringValue().equals(right.constant().stringValue()); 404 405 syn boolean TypeDecl.ltIsTrue(Expr left, Expr right) = false; 406 eq IntegralType.ltIsTrue(Expr left, Expr right) = left.constant().intValue() < right.constant().intValue(); 407 eq LongType.ltIsTrue(Expr left, Expr right) = left.constant().longValue() < right.constant().longValue(); 408 eq FloatType.ltIsTrue(Expr left, Expr right) = left.constant().floatValue() < right.constant().floatValue(); 409 eq DoubleType.ltIsTrue(Expr left, Expr right) = left.constant().doubleValue() < right.constant().doubleValue(); 410 411 syn boolean TypeDecl.leIsTrue(Expr left, Expr right) = false; 412 eq IntegralType.leIsTrue(Expr left, Expr right) = left.constant().intValue() <= right.constant().intValue(); 413 eq LongType.leIsTrue(Expr left, Expr right) = left.constant().longValue() <= right.constant().longValue(); 414 eq FloatType.leIsTrue(Expr left, Expr right) = left.constant().floatValue() <= right.constant().floatValue(); 415 eq DoubleType.leIsTrue(Expr left, Expr right) = left.constant().doubleValue() <= right.constant().doubleValue(); 416 } 417