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