1/* 2 * Copyright 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.turbine.binder; 18 19import static com.google.common.base.Preconditions.checkNotNull; 20 21import com.google.common.collect.ImmutableList; 22import com.google.common.collect.ImmutableMap; 23import com.google.common.collect.Iterables; 24import com.google.turbine.binder.bound.AnnotationValue; 25import com.google.turbine.binder.bound.ClassValue; 26import com.google.turbine.binder.bound.EnumConstantValue; 27import com.google.turbine.binder.bound.SourceTypeBoundClass; 28import com.google.turbine.binder.bound.TypeBoundClass; 29import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; 30import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; 31import com.google.turbine.binder.env.CompoundEnv; 32import com.google.turbine.binder.env.Env; 33import com.google.turbine.binder.lookup.CompoundScope; 34import com.google.turbine.binder.lookup.LookupKey; 35import com.google.turbine.binder.lookup.LookupResult; 36import com.google.turbine.binder.sym.ClassSymbol; 37import com.google.turbine.binder.sym.FieldSymbol; 38import com.google.turbine.diag.TurbineError; 39import com.google.turbine.diag.TurbineError.ErrorKind; 40import com.google.turbine.model.Const; 41import com.google.turbine.model.Const.Value; 42import com.google.turbine.model.TurbineConstantTypeKind; 43import com.google.turbine.model.TurbineFlag; 44import com.google.turbine.tree.Tree; 45import com.google.turbine.tree.Tree.ArrayInit; 46import com.google.turbine.tree.Tree.Binary; 47import com.google.turbine.tree.Tree.ClassLiteral; 48import com.google.turbine.tree.Tree.ClassTy; 49import com.google.turbine.tree.Tree.Conditional; 50import com.google.turbine.tree.Tree.ConstVarName; 51import com.google.turbine.tree.Tree.Expression; 52import com.google.turbine.tree.Tree.PrimTy; 53import com.google.turbine.tree.Tree.TypeCast; 54import com.google.turbine.tree.Tree.Unary; 55import com.google.turbine.type.AnnoInfo; 56import com.google.turbine.type.Type; 57import java.util.ArrayDeque; 58import java.util.Iterator; 59import java.util.LinkedHashMap; 60import java.util.Map; 61 62/** 63 * Constant expression evaluation. 64 * 65 * <p>JLS §15.4 requires this class to be strictfp. 66 */ 67public strictfp class ConstEvaluator { 68 69 /** The symbol of the originating class, for visibility checks. */ 70 private final ClassSymbol origin; 71 72 /** The symbol of the enclosing class, for lexical field lookups. */ 73 private final ClassSymbol owner; 74 75 /** The bound node of the enclosing class. */ 76 private final SourceTypeBoundClass base; 77 78 /** The constant variable environment. */ 79 private final Env<FieldSymbol, Const.Value> values; 80 81 /** The class environment. */ 82 private final CompoundEnv<ClassSymbol, TypeBoundClass> env; 83 84 private final CompoundScope scope; 85 86 public ConstEvaluator( 87 ClassSymbol origin, 88 ClassSymbol owner, 89 SourceTypeBoundClass base, 90 CompoundScope scope, 91 Env<FieldSymbol, Const.Value> values, 92 CompoundEnv<ClassSymbol, TypeBoundClass> env) { 93 94 this.origin = origin; 95 this.owner = owner; 96 this.base = base; 97 this.values = values; 98 this.env = env; 99 this.scope = scope; 100 } 101 102 /** Evaluates the given expression's value. */ 103 public Const eval(Tree t) { 104 switch (t.kind()) { 105 case LITERAL: 106 { 107 Const.Value a = (Const.Value) ((Tree.Literal) t).value(); 108 if (a == null) { 109 return null; 110 } 111 switch (a.constantTypeKind()) { 112 case CHAR: 113 return new Const.CharValue(((com.google.turbine.model.Const.CharValue) a).value()); 114 case INT: 115 return new Const.IntValue(((com.google.turbine.model.Const.IntValue) a).value()); 116 case LONG: 117 return new Const.LongValue(((com.google.turbine.model.Const.LongValue) a).value()); 118 case FLOAT: 119 return new Const.FloatValue(((com.google.turbine.model.Const.FloatValue) a).value()); 120 case DOUBLE: 121 return new Const.DoubleValue( 122 ((com.google.turbine.model.Const.DoubleValue) a).value()); 123 case BOOLEAN: 124 return new Const.BooleanValue( 125 ((com.google.turbine.model.Const.BooleanValue) a).value()); 126 case STRING: 127 return new Const.StringValue( 128 ((com.google.turbine.model.Const.StringValue) a).value()); 129 case SHORT: 130 case BYTE: 131 case NULL: 132 default: 133 throw new AssertionError(a.constantTypeKind()); 134 } 135 } 136 case VOID_TY: 137 throw new AssertionError(t.kind()); 138 case CONST_VAR_NAME: 139 return evalConstVar((ConstVarName) t); 140 case CLASS_LITERAL: 141 return evalClassLiteral((ClassLiteral) t); 142 case BINARY: 143 return evalBinary((Binary) t); 144 case TYPE_CAST: 145 return evalCast((TypeCast) t); 146 case UNARY: 147 return evalUnary((Unary) t); 148 case CONDITIONAL: 149 return evalConditional((Conditional) t); 150 case ARRAY_INIT: 151 return evalArrayInit((ArrayInit) t); 152 case ANNO_EXPR: 153 return evalAnno(((Tree.AnnoExpr) t).value()); 154 default: 155 throw new AssertionError(t.kind()); 156 } 157 } 158 159 /** Evaluates a class literal. */ 160 Const evalClassLiteral(ClassLiteral t) { 161 return new ClassValue(evalClassLiteralType(t.type())); 162 } 163 164 private Type evalClassLiteralType(Tree.Type type) { 165 switch (type.kind()) { 166 case PRIM_TY: 167 return new Type.PrimTy(((PrimTy) type).tykind(), ImmutableList.of()); 168 case VOID_TY: 169 return Type.VOID; 170 case CLASS_TY: 171 return Type.ClassTy.asNonParametricClassTy(resolveClass((ClassTy) type)); 172 case ARR_TY: 173 return new Type.ArrayTy( 174 evalClassLiteralType(((Tree.ArrTy) type).elem()), ImmutableList.of()); 175 default: 176 throw new AssertionError(type.kind()); 177 } 178 } 179 180 /** 181 * Resolves the {@link ClassSymbol} for the given {@link Tree.ClassTy}, with handling for 182 * non-canonical qualified type names. 183 * 184 * <p>Similar to {@link HierarchyBinder#resolveClass}, except we can't unconditionally consider 185 * members of the current class (e.g. when binding constants inside annotations on that class), 186 * and when we do want to consider members we can rely on them being in the current scope (it 187 * isn't completed during the hierarchy phase). 188 */ 189 private ClassSymbol resolveClass(ClassTy classTy) { 190 ArrayDeque<String> flat = new ArrayDeque<>(); 191 for (ClassTy curr = classTy; curr != null; curr = curr.base().orNull()) { 192 flat.addFirst(curr.name()); 193 } 194 LookupResult result = scope.lookup(new LookupKey(flat)); 195 if (result == null) { 196 throw error(classTy.position(), ErrorKind.SYMBOL_NOT_FOUND, flat.peekFirst()); 197 } 198 ClassSymbol classSym = (ClassSymbol) result.sym(); 199 for (String bit : result.remaining()) { 200 classSym = Resolve.resolve(env, origin, classSym, bit); 201 if (classSym == null) { 202 throw error(classTy.position(), ErrorKind.SYMBOL_NOT_FOUND, bit); 203 } 204 } 205 return classSym; 206 } 207 208 /** Evaluates a reference to another constant variable. */ 209 Const evalConstVar(ConstVarName t) { 210 FieldInfo field = resolveField(t); 211 if (field == null) { 212 return null; 213 } 214 if ((field.access() & TurbineFlag.ACC_ENUM) == TurbineFlag.ACC_ENUM) { 215 return new EnumConstantValue(field.sym()); 216 } 217 if (field.value() != null) { 218 return field.value(); 219 } 220 return values.get(field.sym()); 221 } 222 223 FieldInfo resolveField(ConstVarName t) { 224 String simpleName = t.name().get(0); 225 FieldInfo field = lexicalField(env, owner, simpleName); 226 if (field != null) { 227 return field; 228 } 229 field = resolveQualifiedField(t); 230 if (field != null) { 231 return field; 232 } 233 ClassSymbol classSymbol = base.memberImports().singleMemberImport(simpleName); 234 if (classSymbol != null) { 235 field = Resolve.resolveField(env, origin, classSymbol, simpleName); 236 if (field != null) { 237 return field; 238 } 239 } 240 Iterator<ClassSymbol> it = base.memberImports().onDemandImports(); 241 while (it.hasNext()) { 242 field = Resolve.resolveField(env, origin, it.next(), simpleName); 243 if (field == null) { 244 continue; 245 } 246 // resolve handles visibility of inherited members; on-demand imports of private members are 247 // a special case 248 if ((field.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) { 249 continue; 250 } 251 return field; 252 } 253 return null; 254 } 255 256 private FieldInfo resolveQualifiedField(ConstVarName t) { 257 if (t.name().size() <= 1) { 258 return null; 259 } 260 LookupResult result = scope.lookup(new LookupKey(t.name())); 261 if (result == null) { 262 return null; 263 } 264 ClassSymbol sym = (ClassSymbol) result.sym(); 265 for (int i = 0; i < result.remaining().size() - 1; i++) { 266 sym = Resolve.resolve(env, sym, sym, result.remaining().get(i)); 267 if (sym == null) { 268 return null; 269 } 270 } 271 return Resolve.resolveField(env, origin, sym, Iterables.getLast(result.remaining())); 272 } 273 274 /** Search for constant variables in lexically enclosing scopes. */ 275 private FieldInfo lexicalField( 276 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, String name) { 277 while (sym != null) { 278 TypeBoundClass info = env.get(sym); 279 FieldInfo field = Resolve.resolveField(env, origin, sym, name); 280 if (field != null) { 281 return field; 282 } 283 sym = info.owner(); 284 } 285 return null; 286 } 287 288 /** Casts the value to the given type. */ 289 static Const cast(Type ty, Const value) { 290 checkNotNull(value); 291 switch (ty.tyKind()) { 292 case CLASS_TY: 293 case TY_VAR: 294 return value; 295 case PRIM_TY: 296 return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind()); 297 default: 298 throw new AssertionError(ty.tyKind()); 299 } 300 } 301 302 private static Const.Value coerce(Const.Value value, TurbineConstantTypeKind kind) { 303 switch (kind) { 304 case BOOLEAN: 305 return value.asBoolean(); 306 case STRING: 307 return value.asString(); 308 case LONG: 309 return value.asLong(); 310 case INT: 311 return value.asInteger(); 312 case BYTE: 313 return value.asByte(); 314 case CHAR: 315 return value.asChar(); 316 case SHORT: 317 return value.asShort(); 318 case DOUBLE: 319 return value.asDouble(); 320 case FLOAT: 321 return value.asFloat(); 322 default: 323 throw new AssertionError(kind); 324 } 325 } 326 327 private Const.Value evalValue(Expression tree) { 328 Const result = eval(tree); 329 // TODO(cushon): consider distinguishing between constant field and annotation values, 330 // and only allowing class literals / enum constants in the latter 331 return (result instanceof Const.Value) ? (Const.Value) result : null; 332 } 333 334 private Const.Value evalConditional(Conditional t) { 335 Const.Value condition = evalValue(t.cond()); 336 if (condition == null) { 337 return null; 338 } 339 return condition.asBoolean().value() ? evalValue(t.iftrue()) : evalValue(t.iffalse()); 340 } 341 342 private Const.Value evalUnary(Unary t) { 343 Const.Value expr = evalValue(t.expr()); 344 if (expr == null) { 345 return null; 346 } 347 switch (t.op()) { 348 case NOT: 349 return unaryNegate(expr); 350 case BITWISE_COMP: 351 return bitwiseComp(expr); 352 case UNARY_PLUS: 353 return unaryPlus(expr); 354 case NEG: 355 return unaryMinus(expr); 356 default: 357 throw new AssertionError(t.op()); 358 } 359 } 360 361 private Value unaryNegate(Value expr) { 362 switch (expr.constantTypeKind()) { 363 case BOOLEAN: 364 return new Const.BooleanValue(!expr.asBoolean().value()); 365 default: 366 throw new AssertionError(expr.constantTypeKind()); 367 } 368 } 369 370 private Value bitwiseComp(Value expr) { 371 expr = promoteUnary(expr); 372 switch (expr.constantTypeKind()) { 373 case INT: 374 return new Const.IntValue(~expr.asInteger().value()); 375 case LONG: 376 return new Const.LongValue(~expr.asLong().value()); 377 default: 378 throw new AssertionError(expr.constantTypeKind()); 379 } 380 } 381 382 private Value unaryPlus(Value expr) { 383 expr = promoteUnary(expr); 384 switch (expr.constantTypeKind()) { 385 case INT: 386 return new Const.IntValue(+expr.asInteger().value()); 387 case LONG: 388 return new Const.LongValue(+expr.asLong().value()); 389 case FLOAT: 390 return new Const.FloatValue(+expr.asFloat().value()); 391 case DOUBLE: 392 return new Const.DoubleValue(+expr.asDouble().value()); 393 default: 394 throw new AssertionError(expr.constantTypeKind()); 395 } 396 } 397 398 private Value unaryMinus(Value expr) { 399 expr = promoteUnary(expr); 400 switch (expr.constantTypeKind()) { 401 case INT: 402 return new Const.IntValue(-expr.asInteger().value()); 403 case LONG: 404 return new Const.LongValue(-expr.asLong().value()); 405 case FLOAT: 406 return new Const.FloatValue(-expr.asFloat().value()); 407 case DOUBLE: 408 return new Const.DoubleValue(-expr.asDouble().value()); 409 default: 410 throw new AssertionError(expr.constantTypeKind()); 411 } 412 } 413 414 private Const.Value evalCast(TypeCast t) { 415 Const.Value expr = evalValue(t.expr()); 416 if (expr == null) { 417 return null; 418 } 419 switch (t.ty().kind()) { 420 case PRIM_TY: 421 return coerce(expr, ((Tree.PrimTy) t.ty()).tykind()); 422 case CLASS_TY: 423 { 424 ClassTy classTy = (ClassTy) t.ty(); 425 // TODO(cushon): check package? 426 if (!classTy.name().equals("String")) { 427 throw new AssertionError(classTy); 428 } 429 return expr.asString(); 430 } 431 default: 432 throw new AssertionError(t.ty().kind()); 433 } 434 } 435 436 static Const.Value add(Const.Value a, Const.Value b) { 437 if (a.constantTypeKind() == TurbineConstantTypeKind.STRING 438 || b.constantTypeKind() == TurbineConstantTypeKind.STRING) { 439 return new Const.StringValue(a.asString().value() + b.asString().value()); 440 } 441 TurbineConstantTypeKind type = promoteBinary(a, b); 442 a = coerce(a, type); 443 b = coerce(b, type); 444 switch (type) { 445 case INT: 446 return new Const.IntValue(a.asInteger().value() + b.asInteger().value()); 447 case LONG: 448 return new Const.LongValue(a.asLong().value() + b.asLong().value()); 449 case FLOAT: 450 return new Const.FloatValue(a.asFloat().value() + b.asFloat().value()); 451 case DOUBLE: 452 return new Const.DoubleValue(a.asDouble().value() + b.asDouble().value()); 453 default: 454 throw new AssertionError(type); 455 } 456 } 457 458 static Const.Value subtract(Const.Value a, Const.Value b) { 459 TurbineConstantTypeKind type = promoteBinary(a, b); 460 a = coerce(a, type); 461 b = coerce(b, type); 462 switch (type) { 463 case INT: 464 return new Const.IntValue(a.asInteger().value() - b.asInteger().value()); 465 case LONG: 466 return new Const.LongValue(a.asLong().value() - b.asLong().value()); 467 case FLOAT: 468 return new Const.FloatValue(a.asFloat().value() - b.asFloat().value()); 469 case DOUBLE: 470 return new Const.DoubleValue(a.asDouble().value() - b.asDouble().value()); 471 default: 472 throw new AssertionError(type); 473 } 474 } 475 476 static Const.Value mult(Const.Value a, Const.Value b) { 477 TurbineConstantTypeKind type = promoteBinary(a, b); 478 a = coerce(a, type); 479 b = coerce(b, type); 480 switch (type) { 481 case INT: 482 return new Const.IntValue(a.asInteger().value() * b.asInteger().value()); 483 case LONG: 484 return new Const.LongValue(a.asLong().value() * b.asLong().value()); 485 case FLOAT: 486 return new Const.FloatValue(a.asFloat().value() * b.asFloat().value()); 487 case DOUBLE: 488 return new Const.DoubleValue(a.asDouble().value() * b.asDouble().value()); 489 default: 490 throw new AssertionError(type); 491 } 492 } 493 494 static Const.Value divide(Const.Value a, Const.Value b) { 495 TurbineConstantTypeKind type = promoteBinary(a, b); 496 a = coerce(a, type); 497 b = coerce(b, type); 498 switch (type) { 499 case INT: 500 return new Const.IntValue(a.asInteger().value() / b.asInteger().value()); 501 case LONG: 502 return new Const.LongValue(a.asLong().value() / b.asLong().value()); 503 case FLOAT: 504 return new Const.FloatValue(a.asFloat().value() / b.asFloat().value()); 505 case DOUBLE: 506 return new Const.DoubleValue(a.asDouble().value() / b.asDouble().value()); 507 default: 508 throw new AssertionError(type); 509 } 510 } 511 512 static Const.Value mod(Const.Value a, Const.Value b) { 513 TurbineConstantTypeKind type = promoteBinary(a, b); 514 a = coerce(a, type); 515 b = coerce(b, type); 516 switch (type) { 517 case INT: 518 return new Const.IntValue(a.asInteger().value() % b.asInteger().value()); 519 case LONG: 520 return new Const.LongValue(a.asLong().value() % b.asLong().value()); 521 case FLOAT: 522 return new Const.FloatValue(a.asFloat().value() % b.asFloat().value()); 523 case DOUBLE: 524 return new Const.DoubleValue(a.asDouble().value() % b.asDouble().value()); 525 default: 526 throw new AssertionError(type); 527 } 528 } 529 530 static final int INT_SHIFT_MASK = 0b11111; 531 532 static final int LONG_SHIFT_MASK = 0b111111; 533 534 static Const.Value shiftLeft(Const.Value a, Const.Value b) { 535 a = promoteUnary(a); 536 b = promoteUnary(b); 537 switch (a.constantTypeKind()) { 538 case INT: 539 return new Const.IntValue( 540 a.asInteger().value() << (b.asInteger().value() & INT_SHIFT_MASK)); 541 case LONG: 542 return new Const.LongValue(a.asLong().value() << (b.asInteger().value() & LONG_SHIFT_MASK)); 543 default: 544 throw new AssertionError(a.constantTypeKind()); 545 } 546 } 547 548 static Const.Value shiftRight(Const.Value a, Const.Value b) { 549 a = promoteUnary(a); 550 b = promoteUnary(b); 551 switch (a.constantTypeKind()) { 552 case INT: 553 return new Const.IntValue( 554 a.asInteger().value() >> (b.asInteger().value() & INT_SHIFT_MASK)); 555 case LONG: 556 return new Const.LongValue(a.asLong().value() >> (b.asInteger().value() & LONG_SHIFT_MASK)); 557 default: 558 throw new AssertionError(a.constantTypeKind()); 559 } 560 } 561 562 static Const.Value unsignedShiftRight(Const.Value a, Const.Value b) { 563 a = promoteUnary(a); 564 b = promoteUnary(b); 565 switch (a.constantTypeKind()) { 566 case INT: 567 return new Const.IntValue( 568 a.asInteger().value() >>> (b.asInteger().value() & INT_SHIFT_MASK)); 569 case LONG: 570 return new Const.LongValue( 571 a.asLong().value() >>> (b.asInteger().value() & LONG_SHIFT_MASK)); 572 default: 573 throw new AssertionError(a.constantTypeKind()); 574 } 575 } 576 577 static Const.Value lessThan(Const.Value a, Const.Value b) { 578 TurbineConstantTypeKind type = promoteBinary(a, b); 579 a = coerce(a, type); 580 b = coerce(b, type); 581 switch (type) { 582 case INT: 583 return new Const.BooleanValue(a.asInteger().value() < b.asInteger().value()); 584 case LONG: 585 return new Const.BooleanValue(a.asLong().value() < b.asLong().value()); 586 case FLOAT: 587 return new Const.BooleanValue(a.asFloat().value() < b.asFloat().value()); 588 case DOUBLE: 589 return new Const.BooleanValue(a.asDouble().value() < b.asDouble().value()); 590 default: 591 throw new AssertionError(type); 592 } 593 } 594 595 static Const.Value lessThanEqual(Const.Value a, Const.Value b) { 596 TurbineConstantTypeKind type = promoteBinary(a, b); 597 a = coerce(a, type); 598 b = coerce(b, type); 599 switch (type) { 600 case INT: 601 return new Const.BooleanValue(a.asInteger().value() <= b.asInteger().value()); 602 case LONG: 603 return new Const.BooleanValue(a.asLong().value() <= b.asLong().value()); 604 case FLOAT: 605 return new Const.BooleanValue(a.asFloat().value() <= b.asFloat().value()); 606 case DOUBLE: 607 return new Const.BooleanValue(a.asDouble().value() <= b.asDouble().value()); 608 default: 609 throw new AssertionError(type); 610 } 611 } 612 613 static Const.Value greaterThan(Const.Value a, Const.Value b) { 614 TurbineConstantTypeKind type = promoteBinary(a, b); 615 a = coerce(a, type); 616 b = coerce(b, type); 617 switch (type) { 618 case INT: 619 return new Const.BooleanValue(a.asInteger().value() > b.asInteger().value()); 620 case LONG: 621 return new Const.BooleanValue(a.asLong().value() > b.asLong().value()); 622 case FLOAT: 623 return new Const.BooleanValue(a.asFloat().value() > b.asFloat().value()); 624 case DOUBLE: 625 return new Const.BooleanValue(a.asDouble().value() > b.asDouble().value()); 626 default: 627 throw new AssertionError(type); 628 } 629 } 630 631 static Const.Value greaterThanEqual(Const.Value a, Const.Value b) { 632 TurbineConstantTypeKind type = promoteBinary(a, b); 633 a = coerce(a, type); 634 b = coerce(b, type); 635 switch (type) { 636 case INT: 637 return new Const.BooleanValue(a.asInteger().value() >= b.asInteger().value()); 638 case LONG: 639 return new Const.BooleanValue(a.asLong().value() >= b.asLong().value()); 640 case FLOAT: 641 return new Const.BooleanValue(a.asFloat().value() >= b.asFloat().value()); 642 case DOUBLE: 643 return new Const.BooleanValue(a.asDouble().value() >= b.asDouble().value()); 644 default: 645 throw new AssertionError(type); 646 } 647 } 648 649 static Const.Value equal(Const.Value a, Const.Value b) { 650 switch (a.constantTypeKind()) { 651 case STRING: 652 return new Const.BooleanValue(a.asString().value().equals(b.asString().value())); 653 case BOOLEAN: 654 return new Const.BooleanValue(a.asBoolean().value() == b.asBoolean().value()); 655 default: 656 break; 657 } 658 TurbineConstantTypeKind type = promoteBinary(a, b); 659 a = coerce(a, type); 660 b = coerce(b, type); 661 switch (type) { 662 case INT: 663 return new Const.BooleanValue(a.asInteger().value() == b.asInteger().value()); 664 case LONG: 665 return new Const.BooleanValue(a.asLong().value() == b.asLong().value()); 666 case FLOAT: 667 return new Const.BooleanValue(a.asFloat().value() == b.asFloat().value()); 668 case DOUBLE: 669 return new Const.BooleanValue(a.asDouble().value() == b.asDouble().value()); 670 default: 671 throw new AssertionError(type); 672 } 673 } 674 675 static Const.Value notEqual(Const.Value a, Const.Value b) { 676 switch (a.constantTypeKind()) { 677 case STRING: 678 return new Const.BooleanValue(!a.asString().value().equals(b.asString().value())); 679 case BOOLEAN: 680 return new Const.BooleanValue(a.asBoolean().value() != b.asBoolean().value()); 681 default: 682 break; 683 } 684 TurbineConstantTypeKind type = promoteBinary(a, b); 685 a = coerce(a, type); 686 b = coerce(b, type); 687 switch (type) { 688 case INT: 689 return new Const.BooleanValue(a.asInteger().value() != b.asInteger().value()); 690 case LONG: 691 return new Const.BooleanValue(a.asLong().value() != b.asLong().value()); 692 case FLOAT: 693 return new Const.BooleanValue(a.asFloat().value() != b.asFloat().value()); 694 case DOUBLE: 695 return new Const.BooleanValue(a.asDouble().value() != b.asDouble().value()); 696 default: 697 throw new AssertionError(type); 698 } 699 } 700 701 static Const.Value bitwiseAnd(Const.Value a, Const.Value b) { 702 switch (a.constantTypeKind()) { 703 case BOOLEAN: 704 return new Const.BooleanValue(a.asBoolean().value() & b.asBoolean().value()); 705 default: 706 break; 707 } 708 TurbineConstantTypeKind type = promoteBinary(a, b); 709 a = coerce(a, type); 710 b = coerce(b, type); 711 switch (type) { 712 case INT: 713 return new Const.IntValue(a.asInteger().value() & b.asInteger().value()); 714 case LONG: 715 return new Const.LongValue(a.asLong().value() & b.asLong().value()); 716 default: 717 throw new AssertionError(type); 718 } 719 } 720 721 static Const.Value bitwiseOr(Const.Value a, Const.Value b) { 722 switch (a.constantTypeKind()) { 723 case BOOLEAN: 724 return new Const.BooleanValue(a.asBoolean().value() | b.asBoolean().value()); 725 default: 726 break; 727 } 728 TurbineConstantTypeKind type = promoteBinary(a, b); 729 a = coerce(a, type); 730 b = coerce(b, type); 731 switch (type) { 732 case INT: 733 return new Const.IntValue(a.asInteger().value() | b.asInteger().value()); 734 case LONG: 735 return new Const.LongValue(a.asLong().value() | b.asLong().value()); 736 default: 737 throw new AssertionError(type); 738 } 739 } 740 741 static Const.Value bitwiseXor(Const.Value a, Const.Value b) { 742 switch (a.constantTypeKind()) { 743 case BOOLEAN: 744 return new Const.BooleanValue(a.asBoolean().value() ^ b.asBoolean().value()); 745 default: 746 break; 747 } 748 TurbineConstantTypeKind type = promoteBinary(a, b); 749 a = coerce(a, type); 750 b = coerce(b, type); 751 switch (type) { 752 case INT: 753 return new Const.IntValue(a.asInteger().value() ^ b.asInteger().value()); 754 case LONG: 755 return new Const.LongValue(a.asLong().value() ^ b.asLong().value()); 756 default: 757 throw new AssertionError(type); 758 } 759 } 760 761 private Const.Value evalBinary(Binary t) { 762 Const.Value lhs = evalValue(t.lhs()); 763 Const.Value rhs = evalValue(t.rhs()); 764 if (lhs == null || rhs == null) { 765 return null; 766 } 767 switch (t.op()) { 768 case PLUS: 769 return add(lhs, rhs); 770 case MINUS: 771 return subtract(lhs, rhs); 772 case MULT: 773 return mult(lhs, rhs); 774 case DIVIDE: 775 return divide(lhs, rhs); 776 case MODULO: 777 return mod(lhs, rhs); 778 case SHIFT_LEFT: 779 return shiftLeft(lhs, rhs); 780 case SHIFT_RIGHT: 781 return shiftRight(lhs, rhs); 782 case UNSIGNED_SHIFT_RIGHT: 783 return unsignedShiftRight(lhs, rhs); 784 case LESS_THAN: 785 return lessThan(lhs, rhs); 786 case GREATER_THAN: 787 return greaterThan(lhs, rhs); 788 case LESS_THAN_EQ: 789 return lessThanEqual(lhs, rhs); 790 case GREATER_THAN_EQ: 791 return greaterThanEqual(lhs, rhs); 792 case EQUAL: 793 return equal(lhs, rhs); 794 case NOT_EQUAL: 795 return notEqual(lhs, rhs); 796 case AND: 797 return new Const.BooleanValue(lhs.asBoolean().value() && rhs.asBoolean().value()); 798 case OR: 799 return new Const.BooleanValue(lhs.asBoolean().value() || rhs.asBoolean().value()); 800 case BITWISE_AND: 801 return bitwiseAnd(lhs, rhs); 802 case BITWISE_XOR: 803 return bitwiseXor(lhs, rhs); 804 case BITWISE_OR: 805 return bitwiseOr(lhs, rhs); 806 default: 807 throw new AssertionError(t.op()); 808 } 809 } 810 811 private static Const.Value promoteUnary(Const.Value v) { 812 switch (v.constantTypeKind()) { 813 case CHAR: 814 case SHORT: 815 case BYTE: 816 return v.asInteger(); 817 case INT: 818 case LONG: 819 case FLOAT: 820 case DOUBLE: 821 return v; 822 default: 823 throw new AssertionError(v.constantTypeKind()); 824 } 825 } 826 827 private static TurbineConstantTypeKind promoteBinary(Const.Value a, Const.Value b) { 828 a = promoteUnary(a); 829 b = promoteUnary(b); 830 switch (a.constantTypeKind()) { 831 case INT: 832 switch (b.constantTypeKind()) { 833 case INT: 834 case LONG: 835 case DOUBLE: 836 case FLOAT: 837 return b.constantTypeKind(); 838 default: 839 throw new AssertionError(b.constantTypeKind()); 840 } 841 case LONG: 842 switch (b.constantTypeKind()) { 843 case INT: 844 return TurbineConstantTypeKind.LONG; 845 case LONG: 846 case DOUBLE: 847 case FLOAT: 848 return b.constantTypeKind(); 849 default: 850 throw new AssertionError(b.constantTypeKind()); 851 } 852 case FLOAT: 853 switch (b.constantTypeKind()) { 854 case INT: 855 case LONG: 856 case FLOAT: 857 return TurbineConstantTypeKind.FLOAT; 858 case DOUBLE: 859 return TurbineConstantTypeKind.DOUBLE; 860 default: 861 throw new AssertionError(b.constantTypeKind()); 862 } 863 case DOUBLE: 864 switch (b.constantTypeKind()) { 865 case INT: 866 case LONG: 867 case FLOAT: 868 case DOUBLE: 869 return TurbineConstantTypeKind.DOUBLE; 870 default: 871 throw new AssertionError(b.constantTypeKind()); 872 } 873 default: 874 throw new AssertionError(a.constantTypeKind()); 875 } 876 } 877 878 ImmutableList<AnnoInfo> evaluateAnnotations(ImmutableList<AnnoInfo> annotations) { 879 ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder(); 880 for (AnnoInfo annotation : annotations) { 881 result.add(evaluateAnnotation(annotation)); 882 } 883 return result.build(); 884 } 885 886 /** 887 * Evaluates annotation arguments given the symbol of the annotation declaration and a list of 888 * expression trees. 889 */ 890 AnnoInfo evaluateAnnotation(AnnoInfo info) { 891 Map<String, Type> template = new LinkedHashMap<>(); 892 for (MethodInfo method : env.get(info.sym()).methods()) { 893 template.put(method.name(), method.returnType()); 894 } 895 896 ImmutableMap.Builder<String, Const> values = ImmutableMap.builder(); 897 for (Expression arg : info.args()) { 898 Expression expr; 899 String key; 900 if (arg.kind() == Tree.Kind.ASSIGN) { 901 Tree.Assign assign = (Tree.Assign) arg; 902 key = assign.name(); 903 expr = assign.expr(); 904 } else { 905 // expand the implicit 'value' name; `@Foo(42)` is sugar for `@Foo(value=42)` 906 key = "value"; 907 expr = arg; 908 } 909 Type ty = template.get(key); 910 if (ty == null) { 911 throw error(arg.position(), ErrorKind.CANNOT_RESOLVE, key); 912 } 913 Const value = evalAnnotationValue(expr, ty); 914 if (value == null) { 915 throw error(expr.position(), ErrorKind.EXPRESSION_ERROR); 916 } 917 values.put(key, value); 918 } 919 return info.withValues(values.build()); 920 } 921 922 private AnnotationValue evalAnno(Tree.Anno t) { 923 LookupResult result = scope.lookup(new LookupKey(t.name())); 924 ClassSymbol sym = (ClassSymbol) result.sym(); 925 for (String name : result.remaining()) { 926 sym = Resolve.resolve(env, sym, sym, name); 927 } 928 AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(base.source(), sym, t, null)); 929 return new AnnotationValue(annoInfo.sym(), annoInfo.values()); 930 } 931 932 private Const.ArrayInitValue evalArrayInit(ArrayInit t) { 933 ImmutableList.Builder<Const> elements = ImmutableList.builder(); 934 for (Expression e : t.exprs()) { 935 Const arg = eval(e); 936 if (arg == null) { 937 return null; 938 } 939 elements.add(arg); 940 } 941 return new Const.ArrayInitValue(elements.build()); 942 } 943 944 Const evalAnnotationValue(Tree tree, Type ty) { 945 if (ty == null) { 946 throw error(tree.position(), ErrorKind.EXPRESSION_ERROR); 947 } 948 Const value = eval(tree); 949 if (value == null) { 950 throw error(tree.position(), ErrorKind.EXPRESSION_ERROR); 951 } 952 switch (ty.tyKind()) { 953 case PRIM_TY: 954 return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind()); 955 case CLASS_TY: 956 case TY_VAR: 957 return value; 958 case ARRAY_TY: 959 { 960 Type elementType = ((Type.ArrayTy) ty).elementType(); 961 ImmutableList<Const> elements = 962 value.kind() == Const.Kind.ARRAY 963 ? ((Const.ArrayInitValue) value).elements() 964 : ImmutableList.of(value); 965 ImmutableList.Builder<Const> coerced = ImmutableList.builder(); 966 for (Const element : elements) { 967 coerced.add(cast(elementType, element)); 968 } 969 return new Const.ArrayInitValue(coerced.build()); 970 } 971 default: 972 throw new AssertionError(ty.tyKind()); 973 } 974 } 975 976 private TurbineError error(int position, ErrorKind kind, Object... args) { 977 return TurbineError.format(base.source(), position, kind, args); 978 } 979 980 public Const.Value evalFieldInitializer(Expression expression, Type type) { 981 Const value = eval(expression); 982 if (value == null || value.kind() != Const.Kind.PRIMITIVE) { 983 return null; 984 } 985 return (Const.Value) cast(type, value); 986 } 987} 988